diff --git a/app/build.gradle b/app/build.gradle index 0294d49f9c..d558896ee6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,7 +45,7 @@ android { targetSdkVersion 23 multiDexEnabled true versionCode 1500 - version "1.54-dev" + version "1.56-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", generateGitBuild() @@ -149,6 +149,7 @@ dependencies { compile('com.github.tony19:logback-android-classic:1.1.1-6') { exclude group: 'com.google.android', module: 'android' } + compile 'org.apache.commons:commons-lang3:3.6' compile 'org.slf4j:slf4j-api:1.7.12' compile 'com.jjoe64:graphview:4.0.1' compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index be3c0e5d80..13a6400b79 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -42,6 +42,9 @@ + @@ -140,6 +143,9 @@ android:name=".Services.AlarmSoundService" android:enabled="true" android:exported="true" /> + > 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: "); + } + + super.post(event); + } + + @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: "); + } + + 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; + } + + 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 2cfc2d96ab..d900da7d43 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -34,6 +34,7 @@ public class Config { public static final boolean logPumpActions = true; public static final boolean logCongigBuilderActions = true; public static final boolean logAutosensData = false; + public static final boolean logEvents = false; // DanaR specific public static final boolean logDanaBTComm = true; diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index e37a5b4b9f..46e8bc33a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -58,4 +58,7 @@ public class Constants { //Autosens public static final double DEVIATION_TO_BE_EQUAL = 2.0; + + // Pump + public static final int PUMP_MAX_CONNECTION_TIME_IN_SECONDS = 60 - 1; } diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index cafeec6dd6..f8b4bcf0f7 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -13,6 +13,7 @@ import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.j256.ormlite.android.apptools.OpenHelperManager; import com.squareup.otto.Bus; +import com.squareup.otto.LoggingBus; import com.squareup.otto.ThreadEnforcer; import org.slf4j.Logger; @@ -31,6 +32,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; +import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinFastactingProlongedPlugin; import info.nightscout.androidaps.plugins.Insulin.InsulinOrefFreePeakPlugin; @@ -103,7 +105,8 @@ public class MainApp extends Application { log.info("Version: " + BuildConfig.VERSION_NAME); log.info("BuildVersion: " + BuildConfig.BUILDVERSION); - sBus = new Bus(ThreadEnforcer.ANY); + sBus = Config.logEvents ? new LoggingBus(ThreadEnforcer.ANY) : new Bus(ThreadEnforcer.ANY); + sInstance = this; sResources = getResources(); @@ -149,6 +152,7 @@ public class MainApp extends Application { if (!Config.NSCLIENT) pluginsList.add(SourceGlimpPlugin.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); + pluginsList.add(FoodPlugin.getPlugin()); pluginsList.add(WearPlugin.initPlugin(this)); pluginsList.add(StatuslinePlugin.initPlugin(this)); @@ -165,19 +169,14 @@ public class MainApp extends Application { else Answers.getInstance().logCustom(new CustomEvent("AppStart")); - - startKeepAliveService(); - - Thread t = new Thread(new Runnable() { + new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(5000); - PumpInterface pump = MainApp.getConfigBuilder(); - if (pump != null) - pump.refreshDataFromPump("Initialization"); + ConfigBuilderPlugin.getCommandQueue().readStatus("Initialization", null); + startKeepAliveService(); } - }); - t.start(); + }).start(); } @@ -186,6 +185,9 @@ public class MainApp extends Application { lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_FOOD)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_FOOD)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_FOOD)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS)); @@ -206,12 +208,6 @@ public class MainApp extends Application { private void startKeepAliveService() { if (keepAliveReceiver == null) { keepAliveReceiver = new KeepAliveReceiver(); - if (Config.DANAR) { - startService(new Intent(this, DanaRExecutionService.class)); - startService(new Intent(this, DanaRKoreanExecutionService.class)); - startService(new Intent(this, DanaRv2ExecutionService.class)); - startService(new Intent(this, DanaRSService.class)); - } keepAliveReceiver.setAlarm(this); } } diff --git a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java index 8d5a174ca7..ad795f6421 100644 --- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps; -import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.EditTextPreference; @@ -23,7 +22,6 @@ import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.BluetoothDevicePreference; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; @@ -46,7 +44,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myPreferenceFragment = new MyPreferenceFragment(); - myPreferenceFragment.setCaller(getIntent()); + Bundle args = new Bundle(); + args.putInt("id", getIntent().getIntExtra("id", -1)); + myPreferenceFragment.setArguments(args); getFragmentManager().beginTransaction().replace(android.R.id.content, myPreferenceFragment).commit(); PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); } @@ -70,7 +70,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } private static void updatePrefSummary(Preference pref) { - if (pref instanceof ListPreference || pref instanceof BluetoothDevicePreference) { + if (pref instanceof ListPreference) { ListPreference listPref = (ListPreference) pref; pref.setSummary(listPref.getEntry()); } @@ -83,14 +83,10 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) { ((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage()); pref.setSummary(editTextPref.getText()); - } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().toString().trim())) { + } else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) { pref.setSummary(MainApp.sResources.getString(R.string.smscommunicator_allowednumbers_summary)); } } - if (pref instanceof MultiSelectListPreference) { - EditTextPreference editTextPref = (EditTextPreference) pref; - pref.setSummary(editTextPref.getText()); - } } public static void initSummary(Preference p) { @@ -105,10 +101,12 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } public static class MyPreferenceFragment extends PreferenceFragment { - Intent caller; + private Integer id; - public void setCaller(Intent i) { - caller = i; + @Override + public void setArguments(Bundle args) { + super.setArguments(args); + id = args.getInt("id"); } void addPreferencesFromResourceIfEnabled(PluginBase p, int type) { @@ -120,7 +118,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Integer id = caller.getIntExtra("id", -1); + if (savedInstanceState != null && savedInstanceState.containsKey("id")) { + id = savedInstanceState.getInt("id"); + } if (id != -1) { addPreferencesFromResource(id); @@ -184,6 +184,12 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre initSummary(getPreferenceScreen()); } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt("id", id); + } + public Preference getPreference(String key) { return findPreference(key); } diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java index dc52107c26..0b475ddf4f 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -24,7 +24,7 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; @@ -116,6 +116,9 @@ public class DataService extends IntentService { Intents.ACTION_REMOVED_TREATMENT.equals(action) || Intents.ACTION_NEW_STATUS.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action) || + Intents.ACTION_NEW_FOOD.equals(action) || + Intents.ACTION_CHANGED_FOOD.equals(action) || + Intents.ACTION_REMOVED_FOOD.equals(action) || Intents.ACTION_NEW_CAL.equals(action) || Intents.ACTION_NEW_MBG.equals(action)) ) { @@ -413,6 +416,56 @@ public class DataService extends IntentService { log.error("Unhandled exception", e); } } + + if (intent.getAction().equals(Intents.ACTION_NEW_FOOD) || intent.getAction().equals(Intents.ACTION_CHANGED_FOOD)) { + try { + if (bundles.containsKey("food")) { + String trstring = bundles.getString("food"); + handleAddChangeFoodRecord(new JSONObject(trstring)); + } + if (bundles.containsKey("foods")) { + String trstring = bundles.getString("foods"); + JSONArray jsonArray = new JSONArray(trstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject trJson = jsonArray.getJSONObject(i); + handleAddChangeFoodRecord(trJson); + } + } + } catch (Exception e) { + log.error("Unhandled exception", e); + } + } + + if (intent.getAction().equals(Intents.ACTION_REMOVED_FOOD)) { + try { + if (bundles.containsKey("food")) { + String trstring = bundles.getString("food"); + JSONObject trJson = new JSONObject(trstring); + String _id = trJson.getString("_id"); + handleRemovedFoodRecord(_id); + } + + if (bundles.containsKey("foods")) { + String trstring = bundles.getString("foods"); + JSONArray jsonArray = new JSONArray(trstring); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject trJson = jsonArray.getJSONObject(i); + String _id = trJson.getString("_id"); + handleRemovedFoodRecord(_id); + } + } + } catch (Exception e) { + log.error("Unhandled exception", e); + } + } + } + + private void handleRemovedFoodRecord(String _id) { + MainApp.getDbHelper().foodHelper.deleteFoodById(_id); + } + + public void handleAddChangeFoodRecord(JSONObject trJson) throws JSONException { + MainApp.getDbHelper().foodHelper.createFoodFromJsonIfNotExists(trJson); } private void handleRemovedRecordFromNS(String _id) { 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 61c7397694..5b2db2c912 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -12,17 +12,15 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; import java.util.Calendar; -import java.util.Date; import java.util.TimeZone; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; public class Profile { @@ -30,21 +28,21 @@ public class Profile { private JSONObject json; private String units = null; - double dia = Constants.defaultDIA; - TimeZone timeZone = TimeZone.getDefault(); - JSONArray isf; + private double dia = Constants.defaultDIA; + private TimeZone timeZone = TimeZone.getDefault(); + private JSONArray isf; private LongSparseArray isf_v = null; // oldest at index 0 - JSONArray ic; + private JSONArray ic; private LongSparseArray ic_v = null; // oldest at index 0 - JSONArray basal; + private JSONArray basal; private LongSparseArray basal_v = null; // oldest at index 0 - JSONArray targetLow; + private JSONArray targetLow; private LongSparseArray targetLow_v = null; // oldest at index 0 - JSONArray targetHigh; + private JSONArray targetHigh; private LongSparseArray targetHigh_v = null; // oldest at index 0 - int percentage = 100; - int timeshift = 0; + private int percentage = 100; + private int timeshift = 0; public Profile(JSONObject json, String units) { this(json, 100, 0); @@ -206,7 +204,7 @@ public class Profile { return shiftedTime; } - double getMultiplier(LongSparseArray array) { + private double getMultiplier(LongSparseArray array) { double multiplier = 1d; if (array == isf_v) @@ -220,7 +218,7 @@ public class Profile { return multiplier; } - double getMultiplier(JSONArray array) { + private double getMultiplier(JSONArray array) { double multiplier = 1d; if (array == isf) 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 7a4a520bee..c50166d5a4 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java +++ b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java @@ -32,6 +32,56 @@ public class PumpEnactResult extends Object { public boolean queued = false; + public PumpEnactResult success(boolean success) { + this.success = success; + return this; + } + + public PumpEnactResult enacted(boolean enacted) { + this.enacted = enacted; + return this; + } + + public PumpEnactResult comment(String comment) { + this.comment = comment; + return this; + } + + public PumpEnactResult duration(Integer duration) { + this.duration = duration; + return this; + } + + public PumpEnactResult absolute(Double absolute) { + this.absolute = absolute; + return this; + } + + public PumpEnactResult isPercent(boolean isPercent) { + this.isPercent = isPercent; + return this; + } + + public PumpEnactResult isTempCancel(boolean isTempCancel) { + this.isTempCancel = isTempCancel; + return this; + } + + public PumpEnactResult bolusDelivered(Double bolusDelivered) { + this.bolusDelivered = bolusDelivered; + return this; + } + + public PumpEnactResult carbsDelivered(Double carbsDelivered) { + this.carbsDelivered = carbsDelivered; + return this; + } + + public PumpEnactResult queued(boolean queued) { + this.queued = queued; + return this; + } + public String log() { return "Success: " + success + " Enacted: " + enacted + " Comment: " + comment + " Duration: " + duration + " Absolute: " + absolute + " Percent: " + percent + " IsPercent: " + isPercent + " Queued: " + queued; } diff --git a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java index fd5406f974..992e328532 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/FoodHelper.java @@ -87,6 +87,8 @@ public class FoodHelper { log.debug("FOOD: Updating record by _id: " + old.toString()); scheduleFoodChange(); return true; + } else { + return false; } } } 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 8bcd192d59..7aea077e0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java +++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java @@ -72,7 +72,10 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface { name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U "; } if (isCPP) { - name += "(" + percentage + "%," + timeshift + "h)"; + name += "(" + percentage + "%"; + if (timeshift != 0) + name += "," + timeshift + "h"; + name += ")"; } return name; } diff --git a/app/src/main/java/info/nightscout/androidaps/events/Event.java b/app/src/main/java/info/nightscout/androidaps/events/Event.java new file mode 100644 index 0000000000..864d55d6f7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/Event.java @@ -0,0 +1,16 @@ +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/EventAppExit.java b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java index 0f23643fef..9ce91a9a39 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventAppExit.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 07.07.2016. */ -public class EventAppExit { +public class EventAppExit extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java index 1f41119b4b..cb727758bb 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventBolusRequested.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.events; * Created by adrian on 07/02/17. */ -public class EventBolusRequested { +public class EventBolusRequested extends Event { private double amount; public EventBolusRequested (double amount){ diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java index d86fe679fb..9b47ed39cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 25.05.2017. */ -public class EventCareportalEventChange { +public class EventCareportalEventChange extends 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 index 38331ca581..ad5f558fe8 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventConfigBuilderChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 17.02.2017. */ -public class EventConfigBuilderChange { +public class EventConfigBuilderChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java index 78dee60388..8881b0ecc1 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 15.05.2017. */ -public class EventExtendedBolusChange { +public class EventExtendedBolusChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java index 075993c530..48e6be3a14 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventFoodDatabaseChanged.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 20.09.2017. */ -public class EventFoodDatabaseChanged { +public class EventFoodDatabaseChanged extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java index e9a9ce511d..f2bef1d3d0 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventInitializationChanged.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 13.12.2016. */ -public class EventInitializationChanged { +public class EventInitializationChanged extends 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 new file mode 100644 index 0000000000..d694d52537 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventLoop.java @@ -0,0 +1,5 @@ +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/EventNewBG.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java index 2d6454406a..2fb9919b00 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBG.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 05.06.2016. */ -public class EventNewBG { +public class EventNewBG extends EventLoop { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java index 1309625b98..f26a310b6b 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 04.06.2016. */ -public class EventNewBasalProfile { +public class EventNewBasalProfile extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java index 76da0a4e67..f99cb54568 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventPreferenceChange.java @@ -5,7 +5,7 @@ import info.nightscout.androidaps.MainApp; /** * Created by mike on 19.06.2016. */ -public class EventPreferenceChange { +public class EventPreferenceChange extends Event { public String changedKey; public EventPreferenceChange(String key) { changedKey = key; diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java index 476a571d70..7bab9d4518 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 02.06.2017. */ -public class EventProfileSwitchChange { +public class EventProfileSwitchChange extends 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 index 3cfe7cc6a7..52c3183821 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.R; * Created by mike on 19.02.2017. */ -public class EventPumpStatusChanged { +public class EventPumpStatusChanged extends Event { public static final int CONNECTING = 0; public static final int CONNECTED = 1; public static final int PERFORMING = 2; diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java index f20dfb9329..1dae34d2af 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 13.06.2016. */ -public class EventRefreshGui { +public class EventRefreshGui extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java index bf14f5f585..2ba78fa9ec 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.events; * Created by mike on 16.06.2017. */ -public class EventRefreshOverview { +public class EventRefreshOverview extends Event { public String from; public EventRefreshOverview(String from) { diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java index 20073a7cf0..212e8856d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 12.06.2017. */ -public class EventReloadProfileSwitchData { +public class EventReloadProfileSwitchData extends 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 index 38b1b86186..80125cbb4a 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 29.05.2017. */ -public class EventReloadTempBasalData { +public class EventReloadTempBasalData extends 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 index d4ea0d3f70..0ba9b95ad7 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java @@ -4,7 +4,7 @@ package info.nightscout.androidaps.events; * Created by mike on 29.05.2017. */ -public class EventReloadTreatmentData { +public class EventReloadTreatmentData extends Event { public Object next; public EventReloadTreatmentData(Object next) { diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java index 5d8f961e75..73660bb00e 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempBasalChange.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 05.06.2016. */ -public class EventTempBasalChange { +public class EventTempBasalChange extends 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 index d0ef42d830..4e3bf5c5f8 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java @@ -4,5 +4,5 @@ package info.nightscout.androidaps.events; * Created by mike on 13.01.2017. */ -public class EventTempTargetChange { +public class EventTempTargetChange extends 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 index a8597189bc..439d9a7124 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTreatmentChange.java @@ -3,5 +3,5 @@ package info.nightscout.androidaps.events; /** * Created by mike on 04.06.2016. */ -public class EventTreatmentChange { +public class EventTreatmentChange extends 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 new file mode 100644 index 0000000000..3471d2e851 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventUpdateGui.java @@ -0,0 +1,5 @@ +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/interfaces/DanaRInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java index abd1d8e304..1c5ee83834 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java @@ -1,9 +1,12 @@ package info.nightscout.androidaps.interfaces; +import info.nightscout.androidaps.data.PumpEnactResult; + /** * Created by mike on 12.06.2017. */ public interface DanaRInterface { - boolean loadHistory(byte type); + PumpEnactResult loadHistory(byte type); // for history browser + PumpEnactResult loadEvents(); // events history to build treatments from } 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 9da9cb0dd0..a3ada67538 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -16,16 +16,20 @@ public interface PumpInterface { boolean isInitialized(); boolean isSuspended(); boolean isBusy(); + boolean isConnected(); + boolean isConnecting(); + + void connect(String reason); + void disconnect(String reason); + void stopConnecting(); + + void getPumpStatus(); // Upload to pump new basal profile - int SUCCESS = 0; - int FAILED = 1; - int NOT_NEEDED = 2; - int setNewBasalProfile(Profile profile); + PumpEnactResult setNewBasalProfile(Profile profile); boolean isThisProfileSet(Profile profile); Date lastDataTime(); - void refreshDataFromPump(String reason); double getBaseBasalRate(); // base basal rate, not temp basal @@ -36,7 +40,7 @@ public interface PumpInterface { 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 force); + PumpEnactResult cancelTempBasal(boolean enforceNew); PumpEnactResult cancelExtendedBolus(); // Status to be passed to NS diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java index fdb1953531..18f092966e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java @@ -3,8 +3,6 @@ package info.nightscout.androidaps.plugins.Actions; import android.app.Activity; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; @@ -34,6 +32,7 @@ import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; /** * A simple {@link Fragment} subclass. @@ -54,16 +53,8 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL Button tempBasalCancel; Button fill; - private static Handler sHandler; - private static HandlerThread sHandlerThread; - public ActionsFragment() { super(); - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(ActionsFragment.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } } @@ -135,14 +126,15 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL fill.setVisibility(View.GONE); return; } + final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); boolean allowProfileSwitch = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile().getProfileList().size() > 1; - if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !allowProfileSwitch) + if (!pump.getPumpDescription().isSetBasalProfileCapable || !pump.isInitialized() || pump.isSuspended() || !allowProfileSwitch) profileSwitch.setVisibility(View.GONE); else profileSwitch.setVisibility(View.VISIBLE); - if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { + if (!pump.getPumpDescription().isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || pump.isFakingTempsByExtendedBoluses()) { extendedBolus.setVisibility(View.GONE); extendedBolusCancel.setVisibility(View.GONE); } else { @@ -158,7 +150,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL } - if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { + if (!pump.getPumpDescription().isTempBasalCapable || !pump.isInitialized() || pump.isSuspended()) { tempBasal.setVisibility(View.GONE); tempBasalCancel.setVisibility(View.GONE); } else { @@ -166,14 +158,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL tempBasal.setVisibility(View.GONE); tempBasalCancel.setVisibility(View.VISIBLE); final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); - tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + "\n" + activeTemp.toStringShort()); + tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + activeTemp.toStringShort()); } else { tempBasal.setVisibility(View.VISIBLE); tempBasalCancel.setVisibility(View.GONE); } } - if (!MainApp.getConfigBuilder().getPumpDescription().isRefillingCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) + if (!pump.getPumpDescription().isRefillingCapable || !pump.isInitialized() || pump.isSuspended()) fill.setVisibility(View.GONE); else fill.setVisibility(View.VISIBLE); @@ -190,7 +182,6 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL @Override public void onClick(View view) { FragmentManager manager = getFragmentManager(); - final PumpInterface pump = MainApp.getConfigBuilder(); switch (view.getId()) { case R.id.actions_profileswitch: NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); @@ -212,24 +203,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL break; case R.id.actions_extendedbolus_cancel: if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { - sHandler.post(new Runnable() { - @Override - public void run() { - pump.cancelExtendedBolus(); - Answers.getInstance().logCustom(new CustomEvent("CancelExtended")); - } - }); + ConfigBuilderPlugin.getCommandQueue().cancelExtended(null); + Answers.getInstance().logCustom(new CustomEvent("CancelExtended")); } break; case R.id.actions_canceltempbasal: if (MainApp.getConfigBuilder().isTempBasalInProgress()) { - sHandler.post(new Runnable() { - @Override - public void run() { - pump.cancelTempBasal(true); - Answers.getInstance().logCustom(new CustomEvent("CancelTemp")); - } - }); + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null); + Answers.getInstance().logCustom(new CustomEvent("CancelTemp")); } break; case R.id.actions_settempbasal: diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java index f6c9d4c3d6..8391f93492 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java @@ -2,9 +2,8 @@ package info.nightscout.androidaps.plugins.Actions.dialogs; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; @@ -27,11 +26,10 @@ 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.PumpEnactResult; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SP; @@ -48,13 +46,7 @@ public class FillDialog extends DialogFragment implements OnClickListener { NumberPicker editInsulin; - Handler mHandler; - public static HandlerThread mHandlerThread; - public FillDialog() { - mHandlerThread = new HandlerThread(FillDialog.class.getSimpleName()); - mHandlerThread.start(); - this.mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -69,7 +61,7 @@ public class FillDialog extends DialogFragment implements OnClickListener { getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); - double bolusstep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; + double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep; editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false); @@ -158,28 +150,21 @@ public class FillDialog extends DialogFragment implements OnClickListener { builder.setPositiveButton(getString(R.string.primefill), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (finalInsulinAfterConstraints > 0) { - final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); - mHandler.post(new Runnable() { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { @Override public void run() { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) - PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); if (!result.success) { - try { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - } catch (WindowManager.BadTokenException | NullPointerException e) { - // window has been destroyed - Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java index 0b7445e9e7..d9017fd6a9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java @@ -2,15 +2,13 @@ package info.nightscout.androidaps.plugins.Actions.dialogs; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; @@ -23,10 +21,9 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SafeParse; @@ -36,13 +33,7 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli NumberPicker editInsulin; NumberPicker editDuration; - Handler mHandler; - public static HandlerThread mHandlerThread; - public NewExtendedBolusDialog() { - mHandlerThread = new HandlerThread(NewExtendedBolusDialog.class.getSimpleName()); - mHandlerThread.start(); - this.mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -56,8 +47,8 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin); editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false); - double extendedDurationStep = MainApp.getConfigBuilder().getPumpDescription().extendedBolusDurationStep; - double extendedMaxDuration = MainApp.getConfigBuilder().getPumpDescription().extendedBolusMaxDuration; + double extendedDurationStep = ConfigBuilderPlugin.getActivePump().getPumpDescription().extendedBolusDurationStep; + double extendedMaxDuration = ConfigBuilderPlugin.getActivePump().getPumpDescription().extendedBolusMaxDuration; editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration); editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false); @@ -99,24 +90,15 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli builder.setMessage(confirmMessage); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - final PumpInterface pump = MainApp.getConfigBuilder(); - mHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().extendedBolus(finalInsulin, finalDurationInMinutes, new Callback() { @Override public void run() { - PumpEnactResult result = pump.setExtendedBolus(finalInsulin, finalDurationInMinutes); - if (!result.success) { - try { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(context.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(context.getString(R.string.ok), null); - builder.show(); - } catch (WindowManager.BadTokenException | NullPointerException e) { - // window has been destroyed - Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } - } + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } }); Answers.getInstance().logCustom(new CustomEvent("ExtendedBolus")); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java index 68652b0a8b..e734cd4f96 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java @@ -1,11 +1,9 @@ package info.nightscout.androidaps.plugins.Actions.dialogs; -import android.app.Activity; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; @@ -26,9 +24,10 @@ import java.text.DecimalFormat; 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.interfaces.PumpDescription; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SafeParse; @@ -47,13 +46,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi NumberPicker basalAbsolute; NumberPicker duration; - Handler mHandler; - public static HandlerThread mHandlerThread; - public NewTempBasalDialog() { - mHandlerThread = new HandlerThread(NewTempBasalDialog.class.getSimpleName()); - mHandlerThread.start(); - this.mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -70,7 +63,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio); typeSelectorLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_typeselector_layout); - PumpDescription pumpDescription = MainApp.getConfigBuilder().getPumpDescription(); + PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput); double maxTempPercent = pumpDescription.maxTempPercent; @@ -143,37 +136,29 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi final Double finalBasal = absolute; final int finalDurationInMinutes = durationInMinutes; - final Context context = getContext(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(this.getContext().getString(R.string.confirmation)); builder.setMessage(confirmMessage); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - final PumpInterface pump = MainApp.getConfigBuilder(); - mHandler.post(new Runnable() { + Callback callback = new Callback() { @Override public void run() { - PumpEnactResult result; - if (setAsPercent) { - result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes); - } else { - result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes, true); - } if (!result.success) { - if (context instanceof Activity) { - Activity activity = (Activity) context; - if (activity.isFinishing()) { - return; - } - } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } - }); + }; + if (setAsPercent) { + ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, callback); + } else { + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, callback); + } Answers.getInstance().logCustom(new CustomEvent("TempBasal")); } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index 1b976195ae..b284acff91 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -3,9 +3,8 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs; import android.app.Activity; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.text.Editable; @@ -51,9 +50,10 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventNewBasalProfile; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; import info.nightscout.utils.NSUpload; import info.nightscout.utils.NumberPicker; @@ -105,10 +105,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick Date eventTime; - private static Handler sHandler; - private static HandlerThread sHandlerThread; - - public void setOptions(OptionsToShow options, int event) { this.options = options; this.event = MainApp.sResources.getString(event); @@ -116,11 +112,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick public NewNSTreatmentDialog() { super(); - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(NewNSTreatmentDialog.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } } @Override @@ -138,6 +129,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (options == null) return null; getDialog().setTitle(getString(options.eventName)); setStyle(DialogFragment.STYLE_NORMAL, getTheme()); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); @@ -202,27 +194,30 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick public void onItemSelected(AdapterView parent, View view, int position, long id) { double defaultDuration = 0; double defaultTarget = 0; - if(profile!=null){ + if (profile != null) { defaultTarget = bg.doubleValue(); } boolean erase = false; - if(MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))){ + if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) { defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d); - defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d);; - } else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))){ - defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d);; - defaultTarget = SP.getDouble(R.string.key_activity_target, 0d);; + defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d); + ; + } else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) { + defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d); + ; + defaultTarget = SP.getDouble(R.string.key_activity_target, 0d); + ; } else { defaultDuration = 0; erase = true; } - if(defaultTarget != 0 || erase){ + if (defaultTarget != 0 || erase) { editTemptarget.setValue(defaultTarget); } - if(defaultDuration != 0){ + if (defaultDuration != 0) { editDuration.setValue(defaultDuration); - } else if (erase){ + } else if (erase) { editDuration.setValue(0d); } } @@ -236,7 +231,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick // bg bgUnitsView.setText(units); - TextWatcher bgTextWatcher = new TextWatcher() { + TextWatcher bgTextWatcher = new TextWatcher() { public void afterTextChanged(Editable s) { } @@ -336,15 +331,15 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false); ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); - if(ps!=null && ps.isCPP){ + if (ps != null && ps.isCPP) { final int percentage = ps.percentage; final int timeshift = ps.timeshift; - reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift +"h"); + reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift + "h"); reuseButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - editPercentage.setValue((double)percentage); - editTimeshift.setValue((double)timeshift); + editPercentage.setValue((double) percentage); + editTimeshift.setValue((double) timeshift); } }); } @@ -362,7 +357,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_profile_layout), options.profile); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_percentage_layout), options.profile); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_timeshift_layout), options.profile); - showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_reuse_layout), options.profile && ps!=null && ps.isCPP); + showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_reuse_layout), options.profile && ps != null && ps.isCPP); showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout), options.tempTarget); return view; @@ -673,31 +668,22 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } else if (options.executeTempTarget) { try { if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) { - sHandler.post(new Runnable() { - @Override - public void run() { - try { - TempTarget tempTarget = new TempTarget(); - tempTarget.date = eventTime.getTime(); - tempTarget.durationInMinutes = data.getInt("duration"); - tempTarget.reason = data.getString("reason"); - tempTarget.source = Source.USER; - if (tempTarget.durationInMinutes != 0) { - tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits()); - tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits()); - } else { - tempTarget.low = 0; - tempTarget.high = 0; - } - log.debug("Creating new TempTarget db record: " + tempTarget.toString()); - MainApp.getDbHelper().createOrUpdate(tempTarget); - NSUpload.uploadCareportalEntryToNS(data); - Answers.getInstance().logCustom(new CustomEvent("TempTarget")); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - }); + TempTarget tempTarget = new TempTarget(); + tempTarget.date = eventTime.getTime(); + tempTarget.durationInMinutes = data.getInt("duration"); + tempTarget.reason = data.getString("reason"); + tempTarget.source = Source.USER; + if (tempTarget.durationInMinutes != 0) { + tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits()); + tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits()); + } else { + tempTarget.low = 0; + tempTarget.high = 0; + } + log.debug("Creating new TempTarget db record: " + tempTarget.toString()); + MainApp.getDbHelper().createOrUpdate(tempTarget); + NSUpload.uploadCareportalEntryToNS(data); + Answers.getInstance().logCustom(new CustomEvent("TempTarget")); } } catch (JSONException e) { log.error("Unhandled exception", e); @@ -713,64 +699,68 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { - sHandler.post(new Runnable() { + ProfileSwitch profileSwitch = new ProfileSwitch(); + profileSwitch.date = System.currentTimeMillis(); + profileSwitch.source = Source.USER; + profileSwitch.profileName = profileName; + profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); + profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); + profileSwitch.durationInMinutes = duration; + profileSwitch.isCPP = percentage != 100 || timeshift != 0; + profileSwitch.timeshift = timeshift; + profileSwitch.percentage = percentage; + MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); + + ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), new Callback() { @Override public void run() { - ProfileSwitch profileSwitch = new ProfileSwitch(); - profileSwitch.date = System.currentTimeMillis(); - profileSwitch.source = Source.USER; - profileSwitch.profileName = profileName; - profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); - profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); - profileSwitch.durationInMinutes = duration; - profileSwitch.isCPP = percentage != 100 || timeshift != 0; - profileSwitch.timeshift = timeshift; - profileSwitch.percentage = percentage; - MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); - - PumpInterface pump = MainApp.getConfigBuilder(); - if (pump != null) { - pump.setNewBasalProfile(profileSwitch.getProfileObject()); - MainApp.bus().post(new EventNewBasalProfile()); - } else { - log.error("No active pump selected"); + 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.sResources.getString(R.string.failedupdatebasalprofile)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } - Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); + MainApp.bus().post(new EventNewBasalProfile()); } }); + Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); } public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) { - sHandler.post(new Runnable() { - @Override - public void run() { - ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); - if (profileSwitch != null) { - profileSwitch = new ProfileSwitch(); - profileSwitch.date = System.currentTimeMillis(); - profileSwitch.source = Source.USER; - profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false); - profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString(); - profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); - profileSwitch.durationInMinutes = duration; - profileSwitch.isCPP = percentage != 100 || timeshift != 0; - profileSwitch.timeshift = timeshift; - profileSwitch.percentage = percentage; - MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); + ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); + if (profileSwitch != null) { + profileSwitch = new ProfileSwitch(); + profileSwitch.date = System.currentTimeMillis(); + profileSwitch.source = Source.USER; + profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false); + profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString(); + profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); + profileSwitch.durationInMinutes = duration; + profileSwitch.isCPP = percentage != 100 || timeshift != 0; + profileSwitch.timeshift = timeshift; + profileSwitch.percentage = percentage; + MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); - PumpInterface pump = MainApp.getConfigBuilder(); - if (pump != null) { - pump.setNewBasalProfile(profileSwitch.getProfileObject()); - MainApp.bus().post(new EventNewBasalProfile()); - } else { - log.error("No active pump selected"); + ConfigBuilderPlugin.getCommandQueue().setProfile(profileSwitch.getProfileObject(), 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.sResources.getString(R.string.failedupdatebasalprofile)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } - Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); - } else { - log.error("No profile switch existing"); + MainApp.bus().post(new EventNewBasalProfile()); } - } - }); + }); + Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); + } else { + log.error("No profile switch existing"); + } } } 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 12f1f46c1c..e40f839933 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,12 +1,8 @@ package info.nightscout.androidaps.plugins.ConfigBuilder; -import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; -import android.os.PowerManager; import android.preference.PreferenceManager; import android.support.annotation.Nullable; -import android.support.v7.app.AppCompatActivity; import org.json.JSONException; import org.json.JSONObject; @@ -14,7 +10,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; -import java.util.Date; import java.util.List; import info.nightscout.androidaps.Config; @@ -32,33 +27,29 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.events.EventBolusRequested; 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.ProfileInterface; -import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.SensitivityInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.androidaps.queue.CommandQueue; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. */ -public class ConfigBuilderPlugin implements PluginBase, PumpInterface, ConstraintsInterface, TreatmentsInterface { +public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, TreatmentsInterface { private static Logger log = LoggerFactory.getLogger(ConfigBuilderPlugin.class); private static BgSourceInterface activeBgSource; @@ -77,12 +68,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain private static ArrayList pluginList; - private PowerManager.WakeLock mWakeLock; + private static CommandQueue commandQueue = new CommandQueue(); public ConfigBuilderPlugin() { MainApp.bus().register(this); - PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ConfigBuilderPlugin"); } @Override @@ -197,6 +186,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain verifySelectionInCategories(); } + public static CommandQueue getCommandQueue() { + return commandQueue; + } + public static BgSourceInterface getActiveBgSource() { return activeBgSource; } @@ -358,259 +351,77 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } /* - * Pump interface + * Ex Pump interface * * Config builder return itself as a pump and check constraints before it passes command to pump driver */ - @Override - public boolean isInitialized() { - if (activePump != null) - return activePump.isInitialized(); - else return true; - } - @Override - public boolean isSuspended() { - if (activePump != null) - return activePump.isSuspended(); - else return false; - } - - @Override - public boolean isBusy() { - if (activePump != null) - return activePump.isBusy(); - else return false; - } - - @Override - public int setNewBasalProfile(Profile profile) { - // Compare with pump limits - Profile.BasalValue[] basalValues = profile.getBasalValues(); - - for (int index = 0; index < basalValues.length; index++) { - if (basalValues[index].value < getPumpDescription().basalMinimumRate) { - Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.sResources.getString(R.string.basalvaluebelowminimum), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; - } - } - - MainApp.bus().post(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM)); - - if (isThisProfileSet(profile)) { - log.debug("Correct profile already set"); - return NOT_NEEDED; - } else if (activePump != null) { - return activePump.setNewBasalProfile(profile); - } else - return SUCCESS; - } - - @Override - public boolean isThisProfileSet(Profile profile) { - if (activePump != null) - return activePump.isThisProfileSet(profile); - else return true; - } - - @Override - public Date lastDataTime() { - if (activePump != null) - return activePump.lastDataTime(); - else return new Date(); - } - - @Override - public void refreshDataFromPump(String reason) { - if (activePump != null) - activePump.refreshDataFromPump(reason); - } - - @Override - public double getBaseBasalRate() { - if (activePump != null) - return activePump.getBaseBasalRate(); - else - return 0d; - } - - @Override - public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { - mWakeLock.acquire(); - PumpEnactResult result; - detailedBolusInfo.insulin = applyBolusConstraints(detailedBolusInfo.insulin); - detailedBolusInfo.carbs = applyCarbsConstraints((int) detailedBolusInfo.carbs); - - BolusProgressDialog bolusProgressDialog = null; - if (detailedBolusInfo.context != null) { - bolusProgressDialog = new BolusProgressDialog(); - bolusProgressDialog.setInsulin(detailedBolusInfo.insulin); - bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress"); - } else { - Intent i = new Intent(); - i.putExtra("insulin", detailedBolusInfo.insulin); - i.setClass(MainApp.instance(), BolusProgressHelperActivity.class); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - - - MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); - - result = activePump.deliverTreatment(detailedBolusInfo); - - BolusProgressDialog.bolusEnded = true; - MainApp.bus().post(new EventDismissBolusprogressIfRunning(result)); - - mWakeLock.release(); - return result; - } - - @Override - public void stopBolusDelivering() { - activePump.stopBolusDelivering(); - } - - /** - * apply constraints, set temp based on absolute valus and expecting absolute result - * - * @param absoluteRate - * @param durationInMinutes - * @return - */ - @Override - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { - Double rateAfterConstraints = applyBasalConstraints(absoluteRate); - PumpEnactResult result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes, force); - if (Config.logCongigBuilderActions) - log.debug("setTempBasalAbsolute rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted); - return result; - } - - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { - return setTempBasalAbsolute(absoluteRate, durationInMinutes, false); - } - - /** - * apply constraints, set temp based on percent and expecting result in percent - * - * @param percent 0 ... 100 ... - * @param durationInMinutes - * @return result - */ - @Override - public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) { - Integer percentAfterConstraints = applyBasalConstraints(percent); - PumpEnactResult result = activePump.setTempBasalPercent(percentAfterConstraints, durationInMinutes); - if (Config.logCongigBuilderActions) - log.debug("setTempBasalPercent percent: " + percentAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted); - return result; - } - - @Override - public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - Double rateAfterConstraints = applyBolusConstraints(insulin); - PumpEnactResult result = activePump.setExtendedBolus(rateAfterConstraints, durationInMinutes); - if (Config.logCongigBuilderActions) - log.debug("setExtendedBolus rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted); - return result; - } - - @Override - public PumpEnactResult cancelTempBasal(boolean force) { - PumpEnactResult result = activePump.cancelTempBasal(force); - if (Config.logCongigBuilderActions) - log.debug("cancelTempBasal success: " + result.success + " enacted: " + result.enacted); - return result; - } - - @Override - public PumpEnactResult cancelExtendedBolus() { - PumpEnactResult result = activePump.cancelExtendedBolus(); - if (Config.logCongigBuilderActions) - log.debug("cancelExtendedBolus success: " + result.success + " enacted: " + result.enacted); - return result; - } /** * expect absolute request and allow both absolute and percent response based on pump capabilities * * @param request * @return + * true if command is going to be executed + * false if error */ - public PumpEnactResult applyAPSRequest(APSResult request) { + public boolean applyAPSRequest(APSResult request, Callback callback) { + PumpInterface pump = getActivePump(); request.rate = applyBasalConstraints(request.rate); PumpEnactResult result; - if (!isInitialized()) { - result = new PumpEnactResult(); - result.comment = MainApp.sResources.getString(R.string.pumpNotInitialized); - result.enacted = false; - result.success = false; + if (!pump.isInitialized()) { log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpNotInitialized)); - return result; + if (callback != null) { + callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpNotInitialized)).enacted(false).success(false)).run(); + } + return false; } - if (isSuspended()) { - result = new PumpEnactResult(); - result.comment = MainApp.sResources.getString(R.string.pumpsuspended); - result.enacted = false; - result.success = false; + if (pump.isSuspended()) { log.debug("applyAPSRequest: " + MainApp.sResources.getString(R.string.pumpsuspended)); - return result; + if (callback != null) { + callback.result(new PumpEnactResult().comment(MainApp.sResources.getString(R.string.pumpsuspended)).enacted(false).success(false)).run(); + } + return false; } if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: " + request.toString()); - if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - getBaseBasalRate()) < 0.05) { + if ((request.rate == 0 && request.duration == 0) || Math.abs(request.rate - pump.getBaseBasalRate()) < pump.getPumpDescription().basalStep) { if (isTempBasalInProgress()) { if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: cancelTempBasal()"); - result = cancelTempBasal(false); + getCommandQueue().cancelTempBasal(false, callback); + return true; } else { - result = new PumpEnactResult(); - result.absolute = request.rate; - result.duration = 0; - result.enacted = false; - result.comment = "Basal set correctly"; - result.success = true; if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: Basal set correctly"); + if (callback != null) { + callback.result(new PumpEnactResult().absolute(request.rate).duration(0).enacted(false).success(true).comment("Basal set correctly")).run(); + } + return false; } - } else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < getPumpDescription().basalStep) { - result = new PumpEnactResult(); - result.absolute = getTempBasalAbsoluteRateHistory(); - result.duration = getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes(); - result.enacted = false; - result.comment = "Temp basal set correctly"; - result.success = true; + } else if (isTempBasalInProgress() + && getTempBasalRemainingMinutesFromHistory() > 5 + && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < pump.getPumpDescription().basalStep) { if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: Temp basal set correctly"); + if (callback != null) { + callback.result(new PumpEnactResult().absolute(getTempBasalAbsoluteRateHistory()).duration(getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes()).enacted(false).success(true).comment("Temp basal set correctly")).run(); + } + return false; } else { if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: setTempBasalAbsolute()"); - result = setTempBasalAbsolute(request.rate, request.duration); + getCommandQueue().tempBasalAbsolute(request.rate, request.duration, false, callback); + return true; } - return result; } - @Nullable - @Override - public JSONObject getJSONStatus() { - if (activePump != null) - return activePump.getJSONStatus(); - else return null; - } - - @Override - public String deviceID() { - if (activePump != null) - return activePump.deviceID(); - else return "No Pump active!"; - } +/* @Override public PumpDescription getPumpDescription() { if (activePump != null) @@ -625,20 +436,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return emptyDescription; } } - - @Override - public String shortStatus(boolean veryShort) { - if (activePump != null) { - return activePump.shortStatus(veryShort); - } else { - return "No Pump active!"; - } - } - - @Override - public boolean isFakingTempsByExtendedBoluses() { - return activePump.isFakingTempsByExtendedBoluses(); - } +*/ /** * Constraints interface diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java index 04edeb43a1..9f91080710 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java @@ -16,7 +16,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.Loop.LoopPlugin; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.SP; /** @@ -62,7 +62,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.objectives_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -72,7 +72,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { @Override public boolean isEnabled(int type) { - return type == CONSTRAINTS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + return type == CONSTRAINTS && ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java index a64241a4b9..ecb7aad47d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java @@ -10,9 +10,10 @@ 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.Profile; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.HardLimits; import info.nightscout.utils.Round; import info.nightscout.utils.SP; @@ -93,7 +94,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { @Override public boolean isLoopEnabled() { - return MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + return ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; } /** diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java new file mode 100644 index 0000000000..558cf0d02f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodFragment.java @@ -0,0 +1,315 @@ +package info.nightscout.androidaps.plugins.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; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import com.crashlytics.android.Crashlytics; +import com.squareup.otto.Subscribe; + +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.db.Food; +import info.nightscout.androidaps.events.EventFoodDatabaseChanged; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SpinnerHelper; + +/** + * Created by mike on 16.10.2017. + */ + +public class FoodFragment extends SubscriberFragment { + private static Logger log = LoggerFactory.getLogger(FoodFragment.class); + + EditText filter; + ImageView clearFilter; + SpinnerHelper category; + SpinnerHelper subcategory; + RecyclerView recyclerView; + + List unfiltered; + List filtered; + ArrayList categories; + ArrayList subcategories; + + final String EMPTY = MainApp.sResources.getString(R.string.none); + + @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); + + 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(); + } + + @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(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + filterData(); + } + }); + + 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 afterTextChanged(Editable s) { + } + }); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().foodHelper.getFoodData()); + recyclerView.setAdapter(adapter); + + loadData(); + fillCategories(); + fillSubcategories(); + filterData(); + return view; + } catch (Exception e) { + Crashlytics.logException(e); + } + + return null; + } + + @Subscribe + @SuppressWarnings("unused") + public void onStatusEvent(final EventFoodDatabaseChanged ev) { + loadData(); + filterData(); + } + + void loadData() { + unfiltered = MainApp.getDbHelper().foodHelper.getFoodData(); + } + + void fillCategories() { + categories = new ArrayList<>(); + + for (Food f : unfiltered) { + if (f.category != null && !f.category.equals("")) + categories.add(f.category); + } + + // make it unique + categories = new ArrayList<>(new HashSet<>(categories)); + + categories.add(0, MainApp.sResources.getString(R.string.none)); + + ArrayAdapter adapterCategories = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, categories); + category.setAdapter(adapterCategories); + } + + void fillSubcategories() { + String categoryFilter = category.getSelectedItem().toString(); + subcategories = new ArrayList<>(); + + if (!categoryFilter.equals(EMPTY)) { + for (Food f : unfiltered) { + if (f.category != null && f.category.equals(categoryFilter)) + if (f.subcategory != null && !f.subcategory.equals("")) + subcategories.add(f.subcategory); + } + } + + // make it unique + subcategories = new ArrayList<>(new HashSet<>(subcategories)); + + subcategories.add(0, MainApp.sResources.getString(R.string.none)); + + ArrayAdapter adapterSubcategories = new ArrayAdapter<>(getContext(), + R.layout.spinner_centered, subcategories); + subcategory.setAdapter(adapterSubcategories); + } + + void filterData() { + String textFilter = filter.getText().toString(); + String categoryFilter = category.getSelectedItem().toString(); + String subcategoryFilter = subcategory.getSelectedItem().toString(); + + filtered = new ArrayList<>(); + + for (Food f : unfiltered) { + if (f.name == null || f.category == null || f.subcategory == null) + continue; + + if (!subcategoryFilter.equals(EMPTY) && !f.subcategory.equals(subcategoryFilter)) + continue; + if (!categoryFilter.equals(EMPTY) && !f.category.equals(categoryFilter)) + continue; + if (!textFilter.equals("") && !f.name.toLowerCase().contains(textFilter.toLowerCase())) + continue; + filtered.add(f); + } + + 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); + } + }); + } + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List foodList; + + RecyclerViewAdapter(List foodList) { + this.foodList = foodList; + } + + @Override + public FoodsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false); + return new FoodsViewHolder(v); + } + + @Override + public void onBindViewHolder(FoodsViewHolder holder, int position) { + Food food = foodList.get(position); + holder.ns.setVisibility(food._id != null ? View.VISIBLE : View.GONE); + holder.name.setText(food.name); + holder.portion.setText(food.portion + food.units); + holder.carbs.setText(food.carbs + MainApp.sResources.getString(R.string.shortgramm)); + holder.fat.setText(MainApp.sResources.getString(R.string.shortfat) + ": " + food.fat + MainApp.sResources.getString(R.string.shortgramm)); + if (food.fat == 0) + holder.fat.setVisibility(View.INVISIBLE); + holder.protein.setText(MainApp.sResources.getString(R.string.shortprotein) + ": " + food.protein + MainApp.sResources.getString(R.string.shortgramm)); + if (food.protein == 0) + holder.protein.setVisibility(View.INVISIBLE); + holder.energy.setText(MainApp.sResources.getString(R.string.shortenergy) + ": " + food.energy + MainApp.sResources.getString(R.string.shortkilojoul)); + if (food.energy == 0) + holder.energy.setVisibility(View.INVISIBLE); + holder.remove.setTag(food); + } + + @Override + public int getItemCount() { + return foodList.size(); + } + + class FoodsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView name; + TextView portion; + TextView carbs; + TextView fat; + TextView protein; + TextView energy; + TextView ns; + TextView remove; + + FoodsViewHolder(View itemView) { + super(itemView); + name = (TextView) itemView.findViewById(R.id.food_name); + portion = (TextView) itemView.findViewById(R.id.food_portion); + carbs = (TextView) itemView.findViewById(R.id.food_carbs); + fat = (TextView) itemView.findViewById(R.id.food_fat); + protein = (TextView) itemView.findViewById(R.id.food_protein); + energy = (TextView) itemView.findViewById(R.id.food_energy); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.food_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final Food food = (Food) v.getTag(); + switch (v.getId()) { + + case R.id.food_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + food.name); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = food._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeFoodFromNS(_id); + } + MainApp.getDbHelper().foodHelper.delete(food); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + + } + } + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java new file mode 100644 index 0000000000..255b4fd951 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java @@ -0,0 +1,85 @@ +package info.nightscout.androidaps.plugins.Food; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.PluginBase; + +/** + * Created by mike on 05.08.2016. + */ +public class FoodPlugin implements PluginBase { + private boolean fragmentEnabled = true; + private boolean fragmentVisible = false; + + private static FoodPlugin plugin = null; + + public static FoodPlugin getPlugin() { + if (plugin == null) + plugin = new FoodPlugin(); + return plugin; + } + + @Override + public String getFragmentClass() { + return FoodFragment.class.getName(); + } + + @Override + public int getType() { + return PluginBase.GENERAL; + } + + @Override + public String getName() { + return MainApp.instance().getString(R.string.food); + } + + @Override + public String getNameShort() { + // use long name as fallback (not visible in tabs) + return getName(); + } + + + @Override + public boolean isEnabled(int type) { + return type == GENERAL && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == GENERAL && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == GENERAL) this.fragmentVisible = fragmentVisible; + } + + @Override + public int getPreferencesId() { + return -1; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java index b37e3b5c85..6210f91c9a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java @@ -1,13 +1,12 @@ package info.nightscout.androidaps.plugins.Insulin; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; /** @@ -61,7 +60,7 @@ public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterf } public double getUserDefinedDia() { - return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : Constants.defaultDIA; + return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : MIN_DIA; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java index f2977c90c5..ea73915436 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.IobCobCalculator.events; +import info.nightscout.androidaps.events.EventLoop; + /** * Created by mike on 30.04.2017. */ -public class EventAutosensCalculationFinished { +public class EventAutosensCalculationFinished extends EventLoop { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java index 7499fad383..8814741099 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.IobCobCalculator.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 26.04.2017. */ -public class EventNewHistoryData { +public class EventNewHistoryData extends Event { public long time = 0; public EventNewHistoryData(long time) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java index a1a3d9c904..f8ca0ab8c4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.DecimalFormatter; @@ -25,15 +26,16 @@ public class APSResult { public double rate; public int duration; public boolean changeRequested = false; + @Override public String toString() { - final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder(); + final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); if (changeRequested) { if (rate == 0 && duration == 0) return MainApp.sResources.getString(R.string.canceltemp); else return MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(rate/configBuilder.getBaseBasalRate() *100) + "%)\n" + + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)\n" + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(duration) + " min\n" + MainApp.sResources.getString(R.string.reason) + ": " + reason; } else @@ -41,13 +43,13 @@ public class APSResult { } public Spanned toSpanned() { - final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder(); + final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); if (changeRequested) { String ret = ""; if (rate == 0 && duration == 0) ret = MainApp.sResources.getString(R.string.canceltemp); else ret = "" + MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(rate/configBuilder.getBaseBasalRate() *100) + "%)
" + + "(" + DecimalFormatter.to2Decimal(rate / pump.getBaseBasalRate() * 100) + "%)
" + "" + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to2Decimal(duration) + " min
" + "" + MainApp.sResources.getString(R.string.reason) + ": " + reason.replace("<", "<").replace(">", ">"); return Html.fromHtml(ret); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java index 1b6d05664e..736dbeec44 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java @@ -6,15 +6,12 @@ import android.app.PendingIntent; import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v7.app.NotificationCompat; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.squareup.otto.Subscribe; -import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,14 +28,14 @@ import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; -import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; /** * Created by mike on 05.08.2016. @@ -55,14 +52,12 @@ public class LoopPlugin implements PluginBase { return loopPlugin; } - private static Handler sHandler; - private static HandlerThread sHandlerThread; - private boolean fragmentEnabled = false; private boolean fragmentVisible = false; private long loopSuspendedTill = 0L; // end of manual loop suspend private boolean isSuperBolus = false; + private boolean isDisconnected = false; public class LastRun { public APSResult request = null; @@ -77,14 +72,10 @@ public class LoopPlugin implements PluginBase { static public LastRun lastRun = null; public LoopPlugin() { - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(LoopPlugin.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } MainApp.bus().register(this); loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L); isSuperBolus = SP.getBoolean("isSuperBolus", false); + isDisconnected = SP.getBoolean("isDisconnected", false); } @Override @@ -105,7 +96,7 @@ public class LoopPlugin implements PluginBase { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.loop_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -115,12 +106,14 @@ public class LoopPlugin implements PluginBase { @Override public boolean isEnabled(int type) { - return type == LOOP && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + return type == LOOP && fragmentEnabled && pumpCapable; } @Override public boolean isVisibleInTabs(int type) { - return type == LOOP && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + return type == LOOP && fragmentVisible && pumpCapable; } @Override @@ -170,13 +163,28 @@ public class LoopPlugin implements PluginBase { public void suspendTo(long endTime) { loopSuspendedTill = endTime; isSuperBolus = false; + isDisconnected = false; SP.putLong("loopSuspendedTill", loopSuspendedTill); + SP.putBoolean("isSuperBolus", isSuperBolus); + SP.putBoolean("isDisconnected", isDisconnected); } public void superBolusTo(long endTime) { loopSuspendedTill = endTime; isSuperBolus = true; + isDisconnected = false; SP.putLong("loopSuspendedTill", loopSuspendedTill); + SP.putBoolean("isSuperBolus", isSuperBolus); + SP.putBoolean("isDisconnected", isDisconnected); + } + + public void disconnectTo(long endTime) { + loopSuspendedTill = endTime; + isSuperBolus = false; + isDisconnected = true; + SP.putLong("loopSuspendedTill", loopSuspendedTill); + SP.putBoolean("isSuperBolus", isSuperBolus); + SP.putBoolean("isDisconnected", isDisconnected); } public int minutesToEndOfSuspend() { @@ -208,7 +216,7 @@ public class LoopPlugin implements PluginBase { return true; } - public boolean isSuperBolus() { + public boolean isSuperBolus() { if (loopSuspendedTill == 0) return false; @@ -222,6 +230,19 @@ public class LoopPlugin implements PluginBase { return isSuperBolus; } + public boolean isDisconnected() { + if (loopSuspendedTill == 0) + return false; + + long now = System.currentTimeMillis(); + + if (loopSuspendedTill <= now) { // time exceeded + suspendTo(0L); + return false; + } + return isDisconnected; + } + public void invoke(String initiator, boolean allowNotification) { try { if (Config.logFunctionCalls) @@ -232,10 +253,10 @@ public class LoopPlugin implements PluginBase { MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.loopdisabled))); return; } - final ConfigBuilderPlugin configBuilder = MainApp.getConfigBuilder(); + final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); APSResult result = null; - if (configBuilder == null || !isEnabled(PluginBase.LOOP)) + if (!isEnabled(PluginBase.LOOP)) return; if (isSuspended()) { @@ -244,22 +265,22 @@ public class LoopPlugin implements PluginBase { return; } - if (configBuilder.isSuspended()) { + if (pump.isSuspended()) { log.debug(MainApp.sResources.getString(R.string.pumpsuspended)); MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.pumpsuspended))); return; } - if (configBuilder.getProfile() == null) { + if (MainApp.getConfigBuilder().getProfile() == null) { log.debug(MainApp.sResources.getString(R.string.noprofileselected)); MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected))); return; } // Check if pump info is loaded - if (configBuilder.getBaseBasalRate() < 0.01d) return; + if (pump.getBaseBasalRate() < 0.01d) return; - APSInterface usedAPS = configBuilder.getActiveAPS(); + APSInterface usedAPS = MainApp.getConfigBuilder().getActiveAPS(); if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginBase.APS)) { usedAPS.invoke(initiator); result = usedAPS.getLastAPSResult(); @@ -282,20 +303,19 @@ public class LoopPlugin implements PluginBase { lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.setByPump = null; - if (constraintsInterface.isClosedModeEnabled()) { + if (constraintsInterface.isClosedModeEnabled()) { if (result.changeRequested) { final PumpEnactResult waiting = new PumpEnactResult(); final PumpEnactResult previousResult = lastRun.setByPump; waiting.queued = true; lastRun.setByPump = waiting; MainApp.bus().post(new EventLoopUpdateGui()); - sHandler.post(new Runnable() { + MainApp.getConfigBuilder().applyAPSRequest(resultAfterConstraints, new Callback() { @Override public void run() { - final PumpEnactResult applyResult = configBuilder.applyAPSRequest(resultAfterConstraints); Answers.getInstance().logCustom(new CustomEvent("APSRequest")); - if (applyResult.enacted || applyResult.success) { - lastRun.setByPump = applyResult; + if (result.enacted || result.success) { + lastRun.setByPump = result; lastRun.lastEnact = lastRun.lastAPSRun; } else { lastRun.setByPump = previousResult; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java index 7baf556546..1ef5dc4c94 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopSetLastRunGui.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.Loop.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventLoopSetLastRunGui { +public class EventLoopSetLastRunGui extends EventUpdateGui { public String text = null; public EventLoopSetLastRunGui(String text) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java index d671b3bd64..d4417dbb12 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventLoopUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.Loop.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventLoopUpdateGui { +public class EventLoopUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java index 7a6184e406..001d11661e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/events/EventNewOpenLoopNotification.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.Loop.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 07.08.2016. */ -public class EventNewOpenLoopNotification { +public class EventNewOpenLoopNotification extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java index 709c53f6d4..e90dce3bec 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAddAck.java @@ -7,14 +7,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; -import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; import io.socket.client.Ack; /** * Created by mike on 29.12.2015. */ -public class NSAddAck implements Ack { +public class NSAddAck extends Event implements Ack { private static Logger log = LoggerFactory.getLogger(NSAddAck.class); public String _id = null; public String nsClientID = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java index 3c3b173173..56055351d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSAuthAck.java @@ -3,13 +3,14 @@ package info.nightscout.androidaps.plugins.NSClientInternal.acks; import org.json.JSONObject; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.Event; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import io.socket.client.Ack; /** * Created by mike on 02.01.2016. */ -public class NSAuthAck implements Ack{ +public class NSAuthAck extends Event implements Ack{ public boolean read = false; public boolean write = false; public boolean write_treatment = false; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSPingAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSPingAck.java deleted file mode 100644 index 1ec6e3991c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSPingAck.java +++ /dev/null @@ -1,44 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.acks; - -import android.os.SystemClock; - -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.socket.client.Ack; - -/** - * Created by mike on 29.12.2015. - */ -public class NSPingAck implements Ack { - private static Logger log = LoggerFactory.getLogger(NSPingAck.class); - - public long mills = 0; - public boolean received = false; - public boolean auth_received = false; - public boolean read = false; - public boolean write = false; - public boolean write_treatment = false; - - public void call(Object...args) { - JSONObject response = (JSONObject)args[0]; - mills = response.optLong("mills"); - if (response.has("authorization")) { - auth_received = true; - try { - JSONObject authorization = response.getJSONObject("authorization"); - read = authorization.optBoolean("read"); - write = authorization.optBoolean("write"); - write_treatment = authorization.optBoolean("write_treatment"); - } catch (JSONException e) { - log.error("Unhandled exception", e); - } - } - received = true; - synchronized(this) { - this.notify(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java index 5aef754d8c..2bf520da64 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/acks/NSUpdateAck.java @@ -6,12 +6,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.Event; import io.socket.client.Ack; /** * Created by mike on 21.02.2016. */ -public class NSUpdateAck implements Ack { +public class NSUpdateAck extends Event implements Ack { private static Logger log = LoggerFactory.getLogger(NSUpdateAck.class); public boolean result = false; public String _id = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java index 2df50b2bd1..2bd61aa4a9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java @@ -336,7 +336,9 @@ public class NSDeviceStatus { try { long clock = 0L; - if (object.has("created_at")) + if (object.has("mills")) + clock = object.getLong("mills"); + else if (object.has("created_at")) clock = DateUtil.fromISODateString(object.getString("created_at")).getTime(); String device = getDevice(); Integer battery = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java index 7caafbd28a..82b11a812d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java @@ -1,19 +1,15 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; -import android.text.Html; -import android.text.Spanned; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.text.SimpleDateFormat; import java.util.Date; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 15.02.2017. */ -public class EventNSClientNewLog { +public class EventNSClientNewLog extends Event { public Date date = new Date(); public String action; public String logText; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java index 9bf90be31b..b968878da8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientRestart.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 15.02.2017. */ -public class EventNSClientRestart { +public class EventNSClientRestart extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java index 6a1c721535..977c0e31fc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientStatus.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 02.01.2016. */ -public class EventNSClientStatus { +public class EventNSClientStatus extends Event { public String status = ""; public EventNSClientStatus(String status) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java index 8f00bd3424..dd78d2cd28 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientUpdateGUI.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.NSClientInternal.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 17.02.2017. */ -public class EventNSClientUpdateGUI { +public class EventNSClientUpdateGUI extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java index d3d17b510b..2bf2e4fb4f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java @@ -58,7 +58,7 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.utils.DateUtil; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java index 3102ac95d6..466026e986 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java @@ -17,7 +17,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.util.Date; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; @@ -25,11 +24,10 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback; import info.nightscout.utils.SP; @@ -186,7 +184,7 @@ public class DetermineBasalAdapterAMAJS { double minBg, double maxBg, double targetBg, - PumpInterface pump, + double basalrate, IobTotal[] iobArray, GlucoseStatus glucoseStatus, MealData mealData, @@ -210,7 +208,7 @@ public class DetermineBasalAdapterAMAJS { mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3)); mProfile.put("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4)); mProfile.put("skip_neutral_temps", true); - mProfile.put("current_basal", pump.getBaseBasalRate()); + mProfile.put("current_basal", basalrate); mProfile.put("temptargetSet", tempTargetSet); mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true)); mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java index b64d4b6b08..4dcb174209 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java @@ -14,15 +14,15 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.utils.DateUtil; @@ -75,12 +75,14 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { @Override public boolean isEnabled(int type) { - return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + return type == APS && fragmentEnabled && pumpCapable; } @Override public boolean isVisibleInTabs(int type) { - return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + return type == APS && fragmentVisible && pumpCapable; } @Override @@ -137,7 +139,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { public void invoke(String initiator) { log.debug("invoke from " + initiator); lastAPSResult = null; - DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS = null; + DetermineBasalAdapterAMAJS determineBasalAdapterAMAJS; try { determineBasalAdapterAMAJS = new DetermineBasalAdapterAMAJS(new ScriptReader(MainApp.instance().getBaseContext())); } catch (IOException e) { @@ -147,7 +149,6 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); Profile profile = MainApp.getConfigBuilder().getProfile(); - PumpInterface pump = MainApp.getConfigBuilder(); if (profile == null) { MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected))); @@ -215,7 +216,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900)) return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; - if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; + if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5)) + return; startPart = new Date(); if (MainApp.getConfigBuilder().isAMAModeEnabled()) { @@ -229,7 +231,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { start = new Date(); try { - determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData, + determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData, lastAutosensResult.ratio, //autosensDataRatio isTempTarget, SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact @@ -248,7 +250,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) determineBasalResultAMA.changeRequested = false; - if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) + if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1) determineBasalResultAMA.changeRequested = false; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java index a7e1d5da58..723b224f90 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java @@ -22,9 +22,8 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.utils.SP; public class DetermineBasalAdapterMAJS { @@ -155,7 +154,7 @@ public class DetermineBasalAdapterMAJS { double minBg, double maxBg, double targetBg, - PumpInterface pump, + double basalRate, IobTotal iobData, GlucoseStatus glucoseStatus, MealData mealData) throws JSONException { @@ -174,7 +173,7 @@ public class DetermineBasalAdapterMAJS { mProfile.put("carb_ratio", profile.getIc()); mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units)); - mProfile.put("current_basal", pump.getBaseBasalRate()); + mProfile.put("current_basal", basalRate); if (units.equals(Constants.MMOL)) { mProfile.put("out_units", "mmol/L"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java index a0d5cddd88..ac360d4ec8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAPlugin.java @@ -14,13 +14,13 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.utils.DateUtil; @@ -63,7 +63,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.oaps_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -73,12 +73,14 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { @Override public boolean isEnabled(int type) { - return type == APS && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + return type == APS && fragmentEnabled && pumpCapable; } @Override public boolean isVisibleInTabs(int type) { - return type == APS && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; + boolean pumpCapable = ConfigBuilderPlugin.getActivePump() == null || ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable; + return type == APS && fragmentVisible && pumpCapable; } @Override @@ -145,7 +147,6 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); Profile profile = MainApp.getConfigBuilder().getProfile(); - PumpInterface pump = MainApp.getConfigBuilder(); if (profile == null) { MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected))); @@ -213,11 +214,12 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", 2, 900)) return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; - if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; + if (!checkOnlyHardLimits(ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), "current_basal", 0.01, 5)) + return; start = new Date(); try { - determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData); + determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getActivePump().getBaseBasalRate(), iobTotal, glucoseStatus, mealData); } catch (JSONException e) { log.error("Unhandled exception", e); } @@ -232,7 +234,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) determineBasalResultMA.changeRequested = false; - if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) + if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1) determineBasalResultMA.changeRequested = false; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java index 65b3b49d53..40f3c31973 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventOpenAPSUpdateGui { +public class EventOpenAPSUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java index 2aa2365eff..e65cdd2c57 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/events/EventOpenAPSUpdateResultGui.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.OpenAPSMA.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventOpenAPSUpdateResultGui { +public class EventOpenAPSUpdateResultGui extends EventUpdateGui { public String text = null; public EventOpenAPSUpdateResultGui(String text) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java index 192bffba3c..2567c49868 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/BolusProgressDialog.java @@ -20,7 +20,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; @@ -96,8 +96,8 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL case R.id.overview_bolusprogress_stop: log.debug("Stop bolus delivery button pressed"); stopPressedView.setVisibility(View.VISIBLE); - PumpInterface pump = MainApp.getConfigBuilder(); - pump.stopBolusDelivering(); + stopButton.setVisibility(View.INVISIBLE); + ConfigBuilderPlugin.getActivePump().stopBolusDelivering(); break; } } @@ -123,7 +123,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL @Subscribe public void onStatusEvent(final EventDismissBolusprogressIfRunning ev) { - if(BolusProgressDialog.running){ + if (BolusProgressDialog.running) { dismiss(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorDialog.java new file mode 100644 index 0000000000..f11283c029 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorDialog.java @@ -0,0 +1,94 @@ +package info.nightscout.androidaps.plugins.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 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); + okButton = (Button) view.findViewById(R.id.overview_error_ok); + statusView = (TextView) view.findViewById(R.id.overview_error_status); + okButton.setOnClickListener(this); + setCancelable(false); + + Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); + alarm.putExtra("soundid", soundId); + MainApp.instance().startService(alarm); + 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.dismiss(); + if (helperActivity != null) { + helperActivity.finish(); + } + Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); + MainApp.instance().stopService(alarm); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.overview_error_ok: + log.debug("Error dialog ok button pressed"); + dismiss(); + break; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorHelperActivity.java new file mode 100644 index 0000000000..259c9c76eb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/ErrorHelperActivity.java @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.plugins.Overview.Dialogs; + +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +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"); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java index dec763beff..3b50ae9950 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewTreatmentDialog.java @@ -2,9 +2,8 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.text.Editable; @@ -30,12 +29,11 @@ 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.PumpEnactResult; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -49,12 +47,11 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene private Integer maxCarbs; private Double maxInsulin; - private Handler mHandler; + //one shot guards + private boolean accepted; + private boolean okClicked; public NewTreatmentDialog() { - HandlerThread mHandlerThread = new HandlerThread(NewTreatmentDialog.class.getSimpleName()); - mHandlerThread.start(); - this.mHandler = new Handler(mHandlerThread.getLooper()); } final private TextWatcher textWatcher = new TextWatcher() { @@ -103,15 +100,21 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene 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, MainApp.getConfigBuilder().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher); + editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher); return view; } @Override - public void onClick(View view) { + 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; try { Double insulin = SafeParse.stringToDouble(editInsulin.getText()); @@ -132,48 +135,51 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene final int finalCarbsAfterConstraints = carbsAfterConstraints; final Context context = getContext(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); + final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(this.getContext().getString(R.string.confirmation)); builder.setMessage(Html.fromHtml(confirmMessage)); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - final PumpInterface pump = MainApp.getConfigBuilder(); - mHandler.post(new Runnable() { - @Override - public void run() { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - if (finalInsulinAfterConstraints == 0) - detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; - if (finalCarbsAfterConstraints == 0) - detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); - if (!result.success) { - try { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - } catch (WindowManager.BadTokenException | NullPointerException e) { - // window has been destroyed - Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + if (finalInsulinAfterConstraints == 0) + detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; + if (finalCarbsAfterConstraints == 0) + detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + ConfigBuilderPlugin.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.sResources.getString(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } - } - }); - Answers.getInstance().logCustom(new CustomEvent("Bolus")); + }); + Answers.getInstance().logCustom(new CustomEvent("Bolus")); + } } } }); - builder.setNegativeButton(getString(R.string.cancel), null); + builder.setNegativeButton( + + getString(R.string.cancel), null); builder.show(); + dismiss(); } catch (Exception e) { log.error("Unhandled exception", e); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index dbe16c0a9b..4e9a134fb0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -3,9 +3,8 @@ package info.nightscout.androidaps.plugins.Overview.Dialogs; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.text.Editable; @@ -32,7 +31,6 @@ import com.squareup.otto.Subscribe; import org.json.JSONException; import org.json.JSONObject; -import org.mozilla.javascript.tools.debugger.Main; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +45,6 @@ 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.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DatabaseHelper; @@ -59,13 +56,11 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NumberPicker; -import info.nightscout.utils.OKDialog; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -109,16 +104,14 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com JSONObject boluscalcJSON; boolean cobAvailable = false; - Handler mHandler; - public static HandlerThread mHandlerThread; - Context context; + //one shot guards + private boolean accepted; + private boolean okClicked; + public WizardDialog() { super(); - mHandlerThread = new HandlerThread(WizardDialog.class.getSimpleName()); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -253,7 +246,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com 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 = MainApp.getConfigBuilder().getPumpDescription().bolusStep; + double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep; editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, new DecimalFormat("0.00"), false, textWatcher); editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false); initDialog(); @@ -300,6 +293,12 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com public void onClick(View view) { switch (view.getId()) { case R.id.ok: + if (okClicked) { + log.debug("guarding: ok already clicked"); + dismiss(); + return; + } + okClicked = true; if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); @@ -327,56 +326,63 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); final boolean useSuperBolus = superbolusCheckbox.isChecked(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); + final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); builder.setMessage(Html.fromHtml(confirmMessage)); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); - mHandler.post(new Runnable() { - @Override - public void run() { - PumpEnactResult result; - if (useSuperBolus) { - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - if (activeloop != null) { - activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshOverview("WizardDialog")); - } - pump.cancelTempBasal(true); - result = pump.setTempBasalAbsolute(0d, 120, true); - if (!result.success) { - OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror), result.comment, null); - } + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + if (useSuperBolus) { + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); + if (activeloop != null) { + activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + MainApp.bus().post(new EventRefreshOverview("WizardDialog")); } - 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; - result = pump.deliverTreatment(detailedBolusInfo); - if (!result.success) { - try { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - } catch (WindowManager.BadTokenException | NullPointerException e) { - // window has been destroyed - Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(0d, 120, true, 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.sResources.getString(R.string.tempbasaldeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } } - } + }); } - }); - Answers.getInstance().logCustom(new CustomEvent("Wizard")); + 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; + ConfigBuilderPlugin.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.sResources.getString(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + } + }); + Answers.getInstance().logCustom(new CustomEvent("Wizard")); + } } } }); @@ -393,7 +399,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com private void initDialog() { Profile profile = MainApp.getConfigBuilder().getProfile(); - ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); + ProfileStore profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); if (profile == null) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); @@ -403,7 +409,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com ArrayList profileList; profileList = profileStore.getProfileList(); profileList.add(0, MainApp.sResources.getString(R.string.active)); - ArrayAdapter adapter = new ArrayAdapter(getContext(), + ArrayAdapter adapter = new ArrayAdapter<>(getContext(), R.layout.spinner_centered, profileList); profileSpinner.setAdapter(adapter); @@ -444,7 +450,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com } private void calculateInsulin() { - ProfileStore profile = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); + ProfileStore profile = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); if (profileSpinner == null || profileSpinner.getSelectedItem() == null) return; // not initialized yet String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index 67ab9227ed..e3cab1a62c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -5,12 +5,11 @@ import android.app.Activity; import android.app.NotificationManager; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.graphics.Color; -import android.graphics.DashPathEffect; import android.graphics.Paint; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; @@ -26,7 +25,6 @@ import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; @@ -37,13 +35,6 @@ import com.crashlytics.android.Crashlytics; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.jjoe64.graphview.GraphView; -import com.jjoe64.graphview.LabelFormatter; -import com.jjoe64.graphview.ValueDependentColor; -import com.jjoe64.graphview.Viewport; -import com.jjoe64.graphview.series.BarGraphSeries; -import com.jjoe64.graphview.series.DataPoint; -import com.jjoe64.graphview.series.LineGraphSeries; -import com.jjoe64.graphview.series.Series; import com.squareup.otto.Subscribe; import org.json.JSONException; @@ -52,10 +43,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DecimalFormat; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.Executors; @@ -72,16 +61,13 @@ import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.PumpEnactResult; 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.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; @@ -100,7 +86,6 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; @@ -109,26 +94,23 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity; import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; +import info.nightscout.androidaps.plugins.Overview.graphData.GraphData; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; import info.nightscout.androidaps.plugins.Treatments.fragments.ProfileViewerDialog; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; import info.nightscout.utils.OKDialog; import info.nightscout.utils.Profiler; -import info.nightscout.utils.Round; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; @@ -186,24 +168,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public static boolean shorttextmode = false; + private boolean accepted; + private int rangeToDisplay = 6; // for graph Handler sLoopHandler = new Handler(); Runnable sRefreshLoop = null; - private static Handler sHandler; - private static HandlerThread sHandlerThread; - private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); private static ScheduledFuture scheduledUpdate = null; public OverviewFragment() { super(); - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(OverviewFragment.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } } @Override @@ -418,10 +394,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, activeloop.setFragmentVisible(PluginBase.LOOP, false); MainApp.getConfigBuilder().storeSettings(); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -439,10 +414,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.resume))) { activeloop.suspendTo(0L); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -453,10 +427,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor1h))) { activeloop.suspendTo(System.currentTimeMillis() + 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -467,10 +440,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor2h))) { activeloop.suspendTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -481,10 +453,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor3h))) { activeloop.suspendTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -495,10 +466,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor10h))) { activeloop.suspendTo(System.currentTimeMillis() + 10 * 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -507,12 +477,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(600); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) { - activeloop.suspendTo(System.currentTimeMillis() + 30L * 60 * 1000); + activeloop.disconnectTo(System.currentTimeMillis() + 30L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(0d, 30, true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 30, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -521,12 +490,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(30); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) { - activeloop.suspendTo(System.currentTimeMillis() + 1 * 60L * 60 * 1000); + activeloop.disconnectTo(System.currentTimeMillis() + 1 * 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(0d, 60, true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 60, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -535,12 +503,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(60); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) { - activeloop.suspendTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + activeloop.disconnectTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(0d, 2 * 60, true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 2 * 60, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -549,12 +516,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NSUpload.uploadOpenAPSOffline(120); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) { - activeloop.suspendTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000); + activeloop.disconnectTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000); updateGUI("suspendmenu"); - sHandler.post(new Runnable() { + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(0d, 3 * 60, true, new Callback() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 3 * 60, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } @@ -600,13 +566,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, treatmentDialogFragment.show(manager, "TreatmentDialog"); break; case R.id.overview_pumpstatus: - if (MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().isInitialized()) - sHandler.post(new Runnable() { - @Override - public void run() { - MainApp.getConfigBuilder().refreshDataFromPump("RefreshClicked"); - } - }); + if (ConfigBuilderPlugin.getActivePump().isSuspended() || !ConfigBuilderPlugin.getActivePump().isInitialized()) + ConfigBuilderPlugin.getCommandQueue().readStatus("RefreshClicked", null); break; } @@ -622,14 +583,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - sHandler.post(new Runnable() { + hideTempRecommendation(); + clearNotification(); + MainApp.getConfigBuilder().applyAPSRequest(finalLastRun.constraintsProcessed, new Callback() { @Override public void run() { - hideTempRecommendation(); - clearNotification(); - PumpEnactResult applyResult = MainApp.getConfigBuilder().applyAPSRequest(finalLastRun.constraintsProcessed); - if (applyResult.enacted) { - finalLastRun.setByPump = applyResult; + if (result.enacted) { + finalLastRun.setByPump = result; finalLastRun.lastEnact = new Date(); finalLastRun.lastOpenModeAccept = new Date(); NSUpload.uploadDeviceStatus(); @@ -706,40 +666,41 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final Double finalInsulinAfterConstraints = insulinAfterConstraints; final Integer finalCarbsAfterConstraints = carbsAfterConstraints; final Context context = getContext(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); + final AlertDialog.Builder builder = new AlertDialog.Builder(context); + accepted = false; builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); builder.setMessage(confirmMessage); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); - sHandler.post(new Runnable() { - @Override - public void run() { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.carbs = finalCarbsAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.boluscalc = boluscalcJSON; - detailedBolusInfo.source = Source.USER; - PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); - if (!result.success) { - try { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - } catch (WindowManager.BadTokenException | NullPointerException e) { - // window has been destroyed - Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.boluscalc = boluscalcJSON; + detailedBolusInfo.source = Source.USER; + ConfigBuilderPlugin.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.sResources.getString(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } } - } - }); - Answers.getInstance().logCustom(new CustomEvent("QuickWizard")); + }); + Answers.getInstance().logCustom(new CustomEvent("QuickWizard")); + } } } }); @@ -927,7 +888,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, BgReading actualBG = DatabaseHelper.actualBg(); BgReading lastBG = DatabaseHelper.lastBg(); - PumpInterface pump = MainApp.getConfigBuilder(); + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); Profile profile = MainApp.getConfigBuilder().getProfile(); String units = profile.getUnits(); @@ -939,8 +900,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, return; } - Double lowLine = SP.getDouble("low_mark", 0d); - Double highLine = SP.getDouble("high_mark", 0d); + double lowLine = SP.getDouble("low_mark", 0d); + double highLine = SP.getDouble("high_mark", 0d); //Start with updating the BG as it is unaffected by loop. // **** BG value **** @@ -969,7 +930,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, // open loop mode final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; - if (Config.APS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable) { + if (Config.APS && pump.getPumpDescription().isTempBasalCapable) { apsModeView.setVisibility(View.VISIBLE); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopenabled)); apsModeView.setTextColor(Color.BLACK); @@ -1007,7 +968,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, tempTargetView.setTextColor(Color.BLACK); tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground)); tempTargetView.setVisibility(View.VISIBLE); - tempTargetView.setText(Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units)); + tempTargetView.setText(Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units) + " " + DateUtil.untilString(tempTarget.end())); } else { tempTargetView.setTextColor(Color.WHITE); tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetDisabledBackground)); @@ -1082,15 +1043,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final ExtendedBolus extendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); String extendedBolusText = ""; - if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) { - extendedBolusText = extendedBolus.toString(); - } if (extendedBolusView != null) { // must not exists in all layouts if (shorttextmode) { if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) { extendedBolusText = DecimalFormatter.to2Decimal(extendedBolus.absoluteRate()) + "U/h"; - } else { - extendedBolusText = ""; } extendedBolusView.setText(extendedBolusText); extendedBolusView.setOnClickListener(new View.OnClickListener() { @@ -1101,8 +1057,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, }); } else { + if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) { + extendedBolusText = extendedBolus.toString(); + } extendedBolusView.setText(extendedBolusText); } + if (extendedBolusText.equals("")) + extendedBolusView.setVisibility(View.GONE); + else + extendedBolusView.setVisibility(View.VISIBLE); } activeProfileView.setText(MainApp.getConfigBuilder().getProfileName()); @@ -1251,7 +1214,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } // ****** GRAPH ******* - //log.debug("updateGUI checkpoint 1"); // allign to hours Calendar calendar = Calendar.getInstance(); @@ -1280,464 +1242,82 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, endTime = toTime; } - LineGraphSeries basalsLineSeries = null; - LineGraphSeries absoluteBasalsLineSeries = null; - LineGraphSeries baseBasalsSeries = null; - LineGraphSeries tempBasalsSeries = null; - AreaGraphSeries areaSeries; - LineGraphSeries seriesNow, seriesNow2; - - // **** TEMP BASALS graph **** - Double maxBasalValueFound = 0d; long now = System.currentTimeMillis(); - if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { - List baseBasalArray = new ArrayList<>(); - List tempBasalArray = new ArrayList<>(); - List basalLineArray = new ArrayList<>(); - List absoluteBasalLineArray = new ArrayList<>(); - double lastLineBasal = 0; - double lastAbsoluteLineBasal = 0; - double lastBaseBasal = 0; - double lastTempBasal = 0; - for (long time = fromTime; time < now; time += 60 * 1000L) { - BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); - double baseBasalValue = basalData.basal; - double absoluteLineValue = baseBasalValue; - double tempBasalValue = 0; - double basal = 0d; - if (basalData.isTempBasalRunning) { - absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; - if (tempBasalValue != lastTempBasal) { - tempBasalArray.add(new DataPoint(time, lastTempBasal)); - tempBasalArray.add(new DataPoint(time, basal = tempBasalValue)); - } - if (lastBaseBasal != 0d) { - baseBasalArray.add(new DataPoint(time, lastBaseBasal)); - baseBasalArray.add(new DataPoint(time, 0d)); - lastBaseBasal = 0d; - } - } else { - if (baseBasalValue != lastBaseBasal) { - baseBasalArray.add(new DataPoint(time, lastBaseBasal)); - baseBasalArray.add(new DataPoint(time, basal = baseBasalValue)); - lastBaseBasal = baseBasalValue; - } - if (lastTempBasal != 0) { - tempBasalArray.add(new DataPoint(time, lastTempBasal)); - tempBasalArray.add(new DataPoint(time, 0d)); - } - } - if (baseBasalValue != lastLineBasal) { - basalLineArray.add(new DataPoint(time, lastLineBasal)); - basalLineArray.add(new DataPoint(time, baseBasalValue)); - } - if (absoluteLineValue != lastAbsoluteLineBasal) { - absoluteBasalLineArray.add(new DataPoint(time, lastAbsoluteLineBasal)); - absoluteBasalLineArray.add(new DataPoint(time, basal)); - } + // 2nd graph + // remove old data + iobGraph.getSeries().clear(); - lastAbsoluteLineBasal = absoluteLineValue; - lastLineBasal = baseBasalValue; - lastTempBasal = tempBasalValue; - maxBasalValueFound = Math.max(maxBasalValueFound, basal); - } - basalLineArray.add(new DataPoint(now, lastLineBasal)); - baseBasalArray.add(new DataPoint(now, lastBaseBasal)); - tempBasalArray.add(new DataPoint(now, lastTempBasal)); - absoluteBasalLineArray.add(new DataPoint(now, lastAbsoluteLineBasal)); + GraphData secondGraphData = new GraphData(); - DataPoint[] baseBasal = new DataPoint[baseBasalArray.size()]; - baseBasal = baseBasalArray.toArray(baseBasal); - baseBasalsSeries = new LineGraphSeries<>(baseBasal); - baseBasalsSeries.setDrawBackground(true); - baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); - baseBasalsSeries.setThickness(0); + boolean useIobForScale = false; + boolean useCobForScale = false; + boolean useDevForScale = false; + boolean useRatioForScale = false; - DataPoint[] tempBasal = new DataPoint[tempBasalArray.size()]; - tempBasal = tempBasalArray.toArray(tempBasal); - tempBasalsSeries = new LineGraphSeries<>(tempBasal); - tempBasalsSeries.setDrawBackground(true); - tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); - tempBasalsSeries.setThickness(0); - - DataPoint[] basalLine = new DataPoint[basalLineArray.size()]; - basalLine = basalLineArray.toArray(basalLine); - basalsLineSeries = new LineGraphSeries<>(basalLine); - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); - paint.setColor(MainApp.sResources.getColor(R.color.basal)); - basalsLineSeries.setCustomPaint(paint); - - DataPoint[] absoluteBasalLine = new DataPoint[absoluteBasalLineArray.size()]; - absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); - absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); - Paint absolutePaint = new Paint(); - absolutePaint.setStyle(Paint.Style.STROKE); - absolutePaint.setStrokeWidth(4); - absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); - absoluteBasalsLineSeries.setCustomPaint(absolutePaint); + if (showIobView.isChecked()) { + useIobForScale = true; + } else if (showCobView.isChecked()) { + useCobForScale = true; + } else if (showDeviationsView.isChecked()) { + useDevForScale = true; + } else if (showRatiosView.isChecked()) { + useRatioForScale = true; } - //log.debug("updateGUI checkpoint 2"); - - // **** IOB COB DEV graph **** - class DeviationDataPoint extends DataPoint { - public int color; - - public DeviationDataPoint(double x, double y, int color) { - super(x, y); - this.color = color; - } - } - FixedLineGraphSeries iobSeries; - FixedLineGraphSeries cobSeries; - BarGraphSeries devSeries; - LineGraphSeries ratioSeries; - Double maxIobValueFound = 0d; - Double maxCobValueFound = 0d; - Double maxDevValueFound = 0d; - Double maxRatioValueFound = 0d; + if (showIobView.isChecked()) + secondGraphData.addIob(iobGraph, fromTime, now, useIobForScale, 1d); + if (showCobView.isChecked()) + secondGraphData.addCob(iobGraph, fromTime, now, useCobForScale, useCobForScale ? 1d : 0.5d); + if (showDeviationsView.isChecked()) + secondGraphData.addDeviations(iobGraph, fromTime, now, useDevForScale, 1d); + if (showRatiosView.isChecked()) + secondGraphData.addRatio(iobGraph, fromTime, now, useRatioForScale, 1d); if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { - //Date start = new Date(); - List iobArray = new ArrayList<>(); - List cobArray = new ArrayList<>(); - List devArray = new ArrayList<>(); - List ratioArray = new ArrayList<>(); - double lastIob = 0; - int lastCob = 0; - for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) { - if (showIobView.isChecked()) { - double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; - if (Math.abs(lastIob - iob) > 0.02) { - if (Math.abs(lastIob - iob) > 0.2) - iobArray.add(new DataPoint(time, lastIob)); - iobArray.add(new DataPoint(time, iob)); - maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); - lastIob = iob; - } - } - if (showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { - AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); - if (autosensData != null && showCobView.isChecked()) { - int cob = (int) autosensData.cob; - if (cob != lastCob) { - if (autosensData.carbsFromBolus > 0) - cobArray.add(new DataPoint(time, lastCob)); - cobArray.add(new DataPoint(time, cob)); - maxCobValueFound = Math.max(maxCobValueFound, cob); - lastCob = cob; - } - } - if (autosensData != null && showDeviationsView.isChecked()) { - int color = Color.BLACK; // "=" - if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; - if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; - if (autosensData.pastSensitivity.equals("-")) color = Color.RED; - devArray.add(new DeviationDataPoint(time, autosensData.deviation, color)); - maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); - } - if (autosensData != null && showRatiosView.isChecked()) { - ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); - maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); - } - } - } - //Profiler.log(log, "IOB processed", start); - DataPoint[] iobData = new DataPoint[iobArray.size()]; - iobData = iobArray.toArray(iobData); - iobSeries = new FixedLineGraphSeries<>(iobData); - iobSeries.setDrawBackground(true); - iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% - iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); - iobSeries.setThickness(3); - - - Double maxByScale = null; - int graphsToShow = 0; - if (showIobView.isChecked()) { - if (maxByScale == null) maxByScale = maxIobValueFound; - graphsToShow++; - } - if (showCobView.isChecked()) { - if (maxByScale == null) maxByScale = maxCobValueFound; - graphsToShow++; - } - if (showDeviationsView.isChecked()) { - if (maxByScale == null) maxByScale = maxDevValueFound; - graphsToShow++; - } - if (showRatiosView.isChecked()) { - if (maxByScale == null) maxByScale = maxRatioValueFound; - graphsToShow++; - } - - if (graphsToShow > 1) { - if (!maxByScale.equals(maxCobValueFound)) { - List cobArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < cobArray.size(); ci++) { - cobArrayRescaled.add(new DataPoint(cobArray.get(ci).getX(), cobArray.get(ci).getY() * maxByScale / maxCobValueFound / 2)); - } - cobArray = cobArrayRescaled; - } - if (!maxByScale.equals(maxDevValueFound)) { - List devArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < devArray.size(); ci++) { - devArrayRescaled.add(new DeviationDataPoint(devArray.get(ci).getX(), devArray.get(ci).getY() * maxByScale / maxDevValueFound, devArray.get(ci).color)); - } - devArray = devArrayRescaled; - } - if (!maxByScale.equals(maxRatioValueFound)) { - List ratioArrayRescaled = new ArrayList<>(); - for (int ci = 0; ci < ratioArray.size(); ci++) { - ratioArrayRescaled.add(new DataPoint(ratioArray.get(ci).getX(), (ratioArray.get(ci).getY() - 1) * maxByScale / maxRatioValueFound)); - } - ratioArray = ratioArrayRescaled; - } - } - - // COB - DataPoint[] cobData = new DataPoint[cobArray.size()]; - cobData = cobArray.toArray(cobData); - cobSeries = new FixedLineGraphSeries<>(cobData); - cobSeries.setDrawBackground(true); - cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% - cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); - cobSeries.setThickness(3); - - // DEVIATIONS - DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; - devData = devArray.toArray(devData); - devSeries = new BarGraphSeries<>(devData); - devSeries.setValueDependentColor(new ValueDependentColor() { - @Override - public int get(DeviationDataPoint data) { - return data.color; - } - }); - - // RATIOS - DataPoint[] ratioData = new DataPoint[ratioArray.size()]; - ratioData = ratioArray.toArray(ratioData); - ratioSeries = new LineGraphSeries<>(ratioData); - ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); - ratioSeries.setThickness(3); - - iobGraph.getSeries().clear(); - - if (showIobView.isChecked() && iobData.length > 0) { - addSeriesWithoutInvalidate(iobSeries, iobGraph); - } - if (showCobView.isChecked() && cobData.length > 0) { - addSeriesWithoutInvalidate(cobSeries, iobGraph); - } - if (showDeviationsView.isChecked() && devData.length > 0) { - addSeriesWithoutInvalidate(devSeries, iobGraph); - } - if (showRatiosView.isChecked() && ratioData.length > 0) { - addSeriesWithoutInvalidate(ratioSeries, iobGraph); - } iobGraph.setVisibility(View.VISIBLE); } else { iobGraph.setVisibility(View.GONE); } - //log.debug("updateGUI checkpoint 3"); // remove old data from graph - bgGraph.getSecondScale().getSeries().clear(); bgGraph.getSeries().clear(); - //log.debug("updateGUI checkpoint 4"); - // **** Area **** - DoubleDataPoint[] areaDataPoints = new DoubleDataPoint[]{ - new DoubleDataPoint(fromTime, lowLine, highLine), - new DoubleDataPoint(endTime, lowLine, highLine) - }; - areaSeries = new AreaGraphSeries<>(areaDataPoints); - addSeriesWithoutInvalidate(areaSeries, bgGraph); - areaSeries.setColor(0); - areaSeries.setDrawBackground(true); - areaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + GraphData graphData = new GraphData(); + + // **** In range Area **** + graphData.addInRangeArea(bgGraph, fromTime, endTime, lowLine, highLine); + + // **** BG **** + if (showPrediction) + graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, (DetermineBasalResultAMA) finalLastRun.constraintsProcessed); + else + graphData.addBgReadings(bgGraph, fromTime, toTime, lowLine, highLine, null); // set manual x bounds to have nice steps - bgGraph.getViewport().setMaxX(endTime); - bgGraph.getViewport().setMinX(fromTime); - bgGraph.getViewport().setXAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); - bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - iobGraph.getViewport().setMaxX(endTime); - iobGraph.getViewport().setMinX(fromTime); - iobGraph.getViewport().setXAxisBoundsManual(true); - iobGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); - iobGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + graphData.formatAxis(bgGraph, fromTime, endTime); + secondGraphData.formatAxis(iobGraph, fromTime, endTime); - //log.debug("updateGUI checkpoint 5"); - // **** BG graph **** - List bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); - List bgListArray = new ArrayList<>(); - - if (bgReadingsArray.size() == 0) { - return; - } - - Iterator it = bgReadingsArray.iterator(); - Double maxBgValue = 0d; - while (it.hasNext()) { - BgReading bg = it.next(); - if (bg.value > maxBgValue) maxBgValue = bg.value; - bgListArray.add(bg); - } - if (showPrediction) { - DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed; - List predArray = amaResult.getPredictions(); - bgListArray.addAll(predArray); - } - - maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); - maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; - if (highLine > maxBgValue) maxBgValue = highLine; - Integer numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); - - DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; - bg = bgListArray.toArray(bg); - - if (bg.length > 0) { - addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(bg), bgGraph); - } - - //log.debug("updateGUI checkpoint 6"); // Treatments - List filteredTreatments = new ArrayList<>(); + graphData.addTreatments(bgGraph, fromTime, endTime); - List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); - - for (int tx = 0; tx < treatments.size(); tx++) { - Treatment t = treatments.get(tx); - if (t.getX() < fromTime || t.getX() > endTime) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - - //log.debug("updateGUI checkpoint 7"); - // ProfileSwitch - List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); - - for (int tx = 0; tx < profileSwitches.size(); tx++) { - DataPointWithLabelInterface t = profileSwitches.get(tx); - if (t.getX() < fromTime || t.getX() > endTime) continue; - filteredTreatments.add(t); - } - - //log.debug("updateGUI checkpoint 8"); - // Extended bolus - if (!pump.isFakingTempsByExtendedBoluses()) { - List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); - - for (int tx = 0; tx < extendedBoluses.size(); tx++) { - DataPointWithLabelInterface t = extendedBoluses.get(tx); - if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; - if (t.getDuration() == 0) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - } - - //log.debug("updateGUI checkpoint 9"); - // Careportal - List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); - - for (int tx = 0; tx < careportalEvents.size(); tx++) { - DataPointWithLabelInterface t = careportalEvents.get(tx); - if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; - t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); - filteredTreatments.add(t); - } - - DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; - treatmentsArray = filteredTreatments.toArray(treatmentsArray); - if (treatmentsArray.length > 0) { - addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(treatmentsArray), bgGraph); - } - //log.debug("updateGUI checkpoint 10"); - - // set manual y bounds to have nice steps - bgGraph.getViewport().setMaxY(maxBgValue); - bgGraph.getViewport().setMinY(0); - bgGraph.getViewport().setYAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); - - // set second scale + // add basal data if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { - bgGraph.getSecondScale().setMinY(0); - bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); - bgGraph.getSecondScale().addSeries(baseBasalsSeries); - bgGraph.getSecondScale().addSeries(tempBasalsSeries); - bgGraph.getSecondScale().addSeries(basalsLineSeries); - bgGraph.getSecondScale().addSeries(absoluteBasalsLineSeries); + graphData.addBasals(bgGraph, fromTime, now, lowLine / graphData.maxY / 1.2d); } - bgGraph.getSecondScale().setLabelFormatter(new LabelFormatter() { - @Override - public String formatLabel(double value, boolean isValueX) { - return ""; - } - @Override - public void setViewport(Viewport viewport) { - - } - }); - - //log.debug("updateGUI checkpoint 11"); // **** NOW line **** - DataPoint[] nowPoints = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxBgValue) - }; - addSeriesWithoutInvalidate(seriesNow = new LineGraphSeries<>(nowPoints), bgGraph); - seriesNow.setDrawDataPoints(false); - DataPoint[] nowPoints2 = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxIobValueFound) - }; - addSeriesWithoutInvalidate(seriesNow2 = new LineGraphSeries<>(nowPoints2), iobGraph); - seriesNow2.setDrawDataPoints(false); - //seriesNow.setThickness(1); - // custom paint to make a dotted line - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); - paint.setColor(Color.WHITE); - seriesNow.setCustomPaint(paint); - seriesNow2.setCustomPaint(paint); + graphData.addNowLine(bgGraph, now); + secondGraphData.addNowLine(iobGraph, now); + + // finaly enforce drawing of graphs bgGraph.onDataChanged(false, false); iobGraph.onDataChanged(false, false); Profiler.log(log, from, updateGUIStart); } - public double getNearestBg(long date, List bgReadingsArray) { - double bg = 0; - String units = MainApp.getConfigBuilder().getProfileUnits(); - for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { - BgReading reading = bgReadingsArray.get(r); - if (reading.date > date) continue; - bg = Profile.fromMgdlToUnits(reading.value, units); - break; - } - return bg; - } - - void addSeriesWithoutInvalidate(Series s, GraphView graph) { - s.onGraphViewAttached(graph); - graph.getSeries().add(s); - } - - //Notifications static class RecyclerViewAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java index 7eecbada25..57aa5a8054 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java @@ -13,6 +13,7 @@ import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore; import info.nightscout.utils.SP; /** diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java index 9d8435eaf1..af336cd74c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissBolusprogressIfRunning.java @@ -1,12 +1,13 @@ package info.nightscout.androidaps.plugins.Overview.events; import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.events.Event; /** * Created by adrian on 20/02/17. */ -public class EventDismissBolusprogressIfRunning { +public class EventDismissBolusprogressIfRunning extends Event { public final PumpEnactResult result; public EventDismissBolusprogressIfRunning(PumpEnactResult result) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java index f2414e2a4e..1fa71febbe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventDismissNotification.java @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 03.12.2016. */ -public class EventDismissNotification { +public class EventDismissNotification extends Event { public int id; public EventDismissNotification(int did) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java index 8a80019f3e..2a669d26d2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventNewNotification.java @@ -1,12 +1,13 @@ package info.nightscout.androidaps.plugins.Overview.events; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.events.Event; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; /** * Created by mike on 03.12.2016. */ -public class EventNewNotification { +public class EventNewNotification extends Event { public Notification notification; public EventNewNotification(Notification n) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java index 0882032362..e0fd53a1fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventOverviewBolusProgress.java @@ -4,8 +4,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.Event; -public class EventOverviewBolusProgress { +public class EventOverviewBolusProgress extends Event { private static Logger log = LoggerFactory.getLogger(EventOverviewBolusProgress.class); public String status = ""; public Treatment t = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java index 1a9923f606..b72c2548e2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventQuickWizardChange.java @@ -1,8 +1,10 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 20.10.2016. */ -public class EventQuickWizardChange { +public class EventQuickWizardChange extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java index 519341172d..49ccf9fbfb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java @@ -1,10 +1,12 @@ package info.nightscout.androidaps.plugins.Overview.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 02.07.2017. */ -public class EventSetWakeLock { +public class EventSetWakeLock extends Event { public boolean lock = false; public EventSetWakeLock(boolean val) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java new file mode 100644 index 0000000000..9171cd81e7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java @@ -0,0 +1,468 @@ +package info.nightscout.androidaps.plugins.Overview.graphData; + +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.Paint; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.ValueDependentColor; +import com.jjoe64.graphview.series.BarGraphSeries; +import com.jjoe64.graphview.series.DataPoint; +import com.jjoe64.graphview.series.LineGraphSeries; +import com.jjoe64.graphview.series.Series; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +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.CareportalEvent; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; +import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.ScaledDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 18.10.2017. + */ + +public class GraphData { + + public GraphData() { + units = MainApp.getConfigBuilder().getProfileUnits(); + } + + public double maxY = 0; + private List bgReadingsArray; + private String units; + + public void addBgReadings(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine, DetermineBasalResultAMA amaResult) { + double maxBgValue = 0d; + bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); + List bgListArray = new ArrayList<>(); + + if (bgReadingsArray.size() == 0) { + return; + } + + Iterator it = bgReadingsArray.iterator(); + while (it.hasNext()) { + BgReading bg = it.next(); + if (bg.value > maxBgValue) maxBgValue = bg.value; + bgListArray.add(bg); + } + if (amaResult != null) { + List predArray = amaResult.getPredictions(); + bgListArray.addAll(predArray); + } + + maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); + maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; + if (highLine > maxBgValue) maxBgValue = highLine; + int numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); + + DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; + bg = bgListArray.toArray(bg); + + if (bg.length > 0) { + addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(bg)); + } + + maxY = maxBgValue; + // set manual y bounds to have nice steps + bgGraph.getViewport().setMaxY(maxY); + bgGraph.getViewport().setMinY(0); + bgGraph.getViewport().setYAxisBoundsManual(true); + bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); + + } + + public void addInRangeArea(GraphView bgGraph, long fromTime, long toTime, double lowLine, double highLine) { + AreaGraphSeries inRangeAreaSeries; + + DoubleDataPoint[] inRangeAreaDataPoints = new DoubleDataPoint[]{ + new DoubleDataPoint(fromTime, lowLine, highLine), + new DoubleDataPoint(toTime, lowLine, highLine) + }; + inRangeAreaSeries = new AreaGraphSeries<>(inRangeAreaDataPoints); + addSeriesWithoutInvalidate(bgGraph, inRangeAreaSeries); + inRangeAreaSeries.setColor(0); + inRangeAreaSeries.setDrawBackground(true); + inRangeAreaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + } + + // scale in % of vertical size (like 0.3) + public void addBasals(GraphView bgGraph, long fromTime, long toTime, double scale) { + LineGraphSeries basalsLineSeries; + LineGraphSeries absoluteBasalsLineSeries; + LineGraphSeries baseBasalsSeries; + LineGraphSeries tempBasalsSeries; + + double maxBasalValueFound = 0d; + Scale basalScale = new Scale(); + + List baseBasalArray = new ArrayList<>(); + List tempBasalArray = new ArrayList<>(); + List basalLineArray = new ArrayList<>(); + List absoluteBasalLineArray = new ArrayList<>(); + double lastLineBasal = 0; + double lastAbsoluteLineBasal = 0; + double lastBaseBasal = 0; + double lastTempBasal = 0; + for (long time = fromTime; time < toTime; time += 60 * 1000L) { + BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); + double baseBasalValue = basalData.basal; + double absoluteLineValue = baseBasalValue; + double tempBasalValue = 0; + double basal = 0d; + if (basalData.isTempBasalRunning) { + absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; + if (tempBasalValue != lastTempBasal) { + tempBasalArray.add(new ScaledDataPoint(time, lastTempBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(time, basal = tempBasalValue, basalScale)); + } + if (lastBaseBasal != 0d) { + baseBasalArray.add(new ScaledDataPoint(time, lastBaseBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(time, 0d, basalScale)); + lastBaseBasal = 0d; + } + } else { + if (baseBasalValue != lastBaseBasal) { + baseBasalArray.add(new ScaledDataPoint(time, lastBaseBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(time, basal = baseBasalValue, basalScale)); + lastBaseBasal = baseBasalValue; + } + if (lastTempBasal != 0) { + tempBasalArray.add(new ScaledDataPoint(time, lastTempBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(time, 0d, basalScale)); + } + } + + if (baseBasalValue != lastLineBasal) { + basalLineArray.add(new ScaledDataPoint(time, lastLineBasal, basalScale)); + basalLineArray.add(new ScaledDataPoint(time, baseBasalValue, basalScale)); + } + if (absoluteLineValue != lastAbsoluteLineBasal) { + absoluteBasalLineArray.add(new ScaledDataPoint(time, lastAbsoluteLineBasal, basalScale)); + absoluteBasalLineArray.add(new ScaledDataPoint(time, basal, basalScale)); + } + + lastAbsoluteLineBasal = absoluteLineValue; + lastLineBasal = baseBasalValue; + lastTempBasal = tempBasalValue; + maxBasalValueFound = Math.max(maxBasalValueFound, basal); + } + + basalLineArray.add(new ScaledDataPoint(toTime, lastLineBasal, basalScale)); + baseBasalArray.add(new ScaledDataPoint(toTime, lastBaseBasal, basalScale)); + tempBasalArray.add(new ScaledDataPoint(toTime, lastTempBasal, basalScale)); + absoluteBasalLineArray.add(new ScaledDataPoint(toTime, lastAbsoluteLineBasal, basalScale)); + + ScaledDataPoint[] baseBasal = new ScaledDataPoint[baseBasalArray.size()]; + baseBasal = baseBasalArray.toArray(baseBasal); + baseBasalsSeries = new LineGraphSeries<>(baseBasal); + baseBasalsSeries.setDrawBackground(true); + baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); + baseBasalsSeries.setThickness(0); + + ScaledDataPoint[] tempBasal = new ScaledDataPoint[tempBasalArray.size()]; + tempBasal = tempBasalArray.toArray(tempBasal); + tempBasalsSeries = new LineGraphSeries<>(tempBasal); + tempBasalsSeries.setDrawBackground(true); + tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); + tempBasalsSeries.setThickness(0); + + ScaledDataPoint[] basalLine = new ScaledDataPoint[basalLineArray.size()]; + basalLine = basalLineArray.toArray(basalLine); + basalsLineSeries = new LineGraphSeries<>(basalLine); + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); + paint.setColor(MainApp.sResources.getColor(R.color.basal)); + basalsLineSeries.setCustomPaint(paint); + + ScaledDataPoint[] absoluteBasalLine = new ScaledDataPoint[absoluteBasalLineArray.size()]; + absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); + absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); + Paint absolutePaint = new Paint(); + absolutePaint.setStyle(Paint.Style.STROKE); + absolutePaint.setStrokeWidth(4); + absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); + absoluteBasalsLineSeries.setCustomPaint(absolutePaint); + + basalScale.setMultiplier(maxY * scale / maxBasalValueFound); + + addSeriesWithoutInvalidate(bgGraph, baseBasalsSeries); + addSeriesWithoutInvalidate(bgGraph, tempBasalsSeries); + addSeriesWithoutInvalidate(bgGraph, basalsLineSeries); + addSeriesWithoutInvalidate(bgGraph, absoluteBasalsLineSeries); + } + + public void addTreatments(GraphView bgGraph, long fromTime, long endTime) { + List filteredTreatments = new ArrayList<>(); + + List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); + + for (int tx = 0; tx < treatments.size(); tx++) { + Treatment t = treatments.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + + // ProfileSwitch + List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); + + for (int tx = 0; tx < profileSwitches.size(); tx++) { + DataPointWithLabelInterface t = profileSwitches.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + filteredTreatments.add(t); + } + + // Extended bolus + if (!ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) { + List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); + + for (int tx = 0; tx < extendedBoluses.size(); tx++) { + DataPointWithLabelInterface t = extendedBoluses.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + if (t.getDuration() == 0) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + } + + // Careportal + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); + + for (int tx = 0; tx < careportalEvents.size(); tx++) { + DataPointWithLabelInterface t = careportalEvents.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX())); + filteredTreatments.add(t); + } + + DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; + treatmentsArray = filteredTreatments.toArray(treatmentsArray); + if (treatmentsArray.length > 0) { + addSeriesWithoutInvalidate(bgGraph, new PointsWithLabelGraphSeries<>(treatmentsArray)); + } + } + + double getNearestBg(long date) { + double bg = 0; + for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { + BgReading reading = bgReadingsArray.get(r); + if (reading.date > date) continue; + bg = Profile.fromMgdlToUnits(reading.value, units); + break; + } + return bg; + } + + // scale in % of vertical size (like 0.3) + public void addIob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries iobSeries; + List iobArray = new ArrayList<>(); + Double maxIobValueFound = 0d; + double lastIob = 0; + Scale iobScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; + if (Math.abs(lastIob - iob) > 0.02) { + if (Math.abs(lastIob - iob) > 0.2) + iobArray.add(new ScaledDataPoint(time, lastIob, iobScale)); + iobArray.add(new ScaledDataPoint(time, iob, iobScale)); + maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); + lastIob = iob; + } + } + + ScaledDataPoint[] iobData = new ScaledDataPoint[iobArray.size()]; + iobData = iobArray.toArray(iobData); + iobSeries = new FixedLineGraphSeries<>(iobData); + iobSeries.setDrawBackground(true); + iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% + iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); + iobSeries.setThickness(3); + + if (useForScale) + maxY = maxIobValueFound; + + iobScale.setMultiplier(maxY * scale / maxIobValueFound); + + addSeriesWithoutInvalidate(graph, iobSeries); + } + + // scale in % of vertical size (like 0.3) + public void addCob(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + FixedLineGraphSeries cobSeries; + List cobArray = new ArrayList<>(); + Double maxCobValueFound = 0d; + int lastCob = 0; + Scale cobScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + int cob = (int) autosensData.cob; + if (cob != lastCob) { + if (autosensData.carbsFromBolus > 0) + cobArray.add(new ScaledDataPoint(time, lastCob, cobScale)); + cobArray.add(new ScaledDataPoint(time, cob, cobScale)); + maxCobValueFound = Math.max(maxCobValueFound, cob); + lastCob = cob; + } + } + } + + // COB + ScaledDataPoint[] cobData = new ScaledDataPoint[cobArray.size()]; + cobData = cobArray.toArray(cobData); + cobSeries = new FixedLineGraphSeries<>(cobData); + cobSeries.setDrawBackground(true); + cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% + cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); + cobSeries.setThickness(3); + + if (useForScale) + maxY = maxCobValueFound; + + cobScale.setMultiplier(maxY * scale / maxCobValueFound); + + addSeriesWithoutInvalidate(graph, cobSeries); + } + + // scale in % of vertical size (like 0.3) + public void addDeviations(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + class DeviationDataPoint extends ScaledDataPoint { + public int color; + + public DeviationDataPoint(double x, double y, int color, Scale scale) { + super(x, y, scale); + this.color = color; + } + } + + BarGraphSeries devSeries; + List devArray = new ArrayList<>(); + Double maxDevValueFound = 0d; + Scale devScale = new Scale(); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + int color = Color.BLACK; // "=" + if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; + if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; + if (autosensData.pastSensitivity.equals("-")) color = Color.RED; + devArray.add(new DeviationDataPoint(time, autosensData.deviation, color, devScale)); + maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); + } + } + + // DEVIATIONS + DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; + devData = devArray.toArray(devData); + devSeries = new BarGraphSeries<>(devData); + devSeries.setValueDependentColor(new ValueDependentColor() { + @Override + public int get(DeviationDataPoint data) { + return data.color; + } + }); + + if (useForScale) + maxY = maxDevValueFound; + + devScale.setMultiplier(maxY * scale / maxDevValueFound); + + addSeriesWithoutInvalidate(graph, devSeries); + } + + // scale in % of vertical size (like 0.3) + public void addRatio(GraphView graph, long fromTime, long toTime, boolean useForScale, double scale) { + LineGraphSeries ratioSeries; + List ratioArray = new ArrayList<>(); + Double maxRatioValueFound = 0d; + Scale ratioScale = new Scale(-1d); + + for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null) { + ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); + maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); + } + } + + // RATIOS + DataPoint[] ratioData = new DataPoint[ratioArray.size()]; + ratioData = ratioArray.toArray(ratioData); + ratioSeries = new LineGraphSeries<>(ratioData); + ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); + ratioSeries.setThickness(3); + + if (useForScale) + maxY = maxRatioValueFound; + + ratioScale.setMultiplier(maxY * scale / maxRatioValueFound); + + addSeriesWithoutInvalidate(graph, ratioSeries); + } + + // scale in % of vertical size (like 0.3) + public void addNowLine(GraphView graph, long now) { + LineGraphSeries seriesNow; + DataPoint[] nowPoints = new DataPoint[]{ + new DataPoint(now, 0), + new DataPoint(now, maxY) + }; + + seriesNow = new LineGraphSeries<>(nowPoints); + seriesNow.setDrawDataPoints(false); + // custom paint to make a dotted line + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); + paint.setColor(Color.WHITE); + seriesNow.setCustomPaint(paint); + + addSeriesWithoutInvalidate(graph, seriesNow); + } + + public void formatAxis(GraphView graph, long fromTime, long endTime) { + graph.getViewport().setMaxX(endTime); + graph.getViewport().setMinX(fromTime); + graph.getViewport().setXAxisBoundsManual(true); + graph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter("HH")); + graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + } + + private void addSeriesWithoutInvalidate(GraphView bgGraph, Series s) { + if (!s.isEmpty()) { + s.onGraphViewAttached(bgGraph); + bgGraph.getSeries().add(s); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java new file mode 100644 index 0000000000..4aa1271679 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/Scale.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +/** + * Created by mike on 18.10.2017. + */ + +public class Scale { + private double multiplier; + private double shift; + + public Scale() { + shift = 0; + } + + public Scale(double shift) { + this.shift = shift; + } + + public void setMultiplier(double value) { + this.multiplier = value; + } + + public double transform(double original) { + return original * multiplier + shift; + } + + public double getShift() { + return shift; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java new file mode 100644 index 0000000000..61f4102a30 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/ScaledDataPoint.java @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +import com.jjoe64.graphview.series.DataPointInterface; + +import java.io.Serializable; +import java.util.Date; + +/** + * Created by mike on 18.10.2017. + */ + +public class ScaledDataPoint implements DataPointInterface, Serializable { + private static final long serialVersionUID=1428263342645L; + + private double x; + private double y; + + private Scale scale; + + public ScaledDataPoint(double x, double y, Scale scale) { + this.x=x; + this.y=y; + this.scale = scale; + } + + public ScaledDataPoint(Date x, double y, Scale scale) { + this.x = x.getTime(); + this.y = y; + this.scale = scale; + } + + @Override + public double getX() { + return x; + } + + @Override + public double getY() { + return scale.transform(y); + } + + @Override + public String toString() { + return "["+x+"/"+y+"]"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java index 881e472a1d..323751e4c8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java @@ -15,7 +15,7 @@ public class TimeAsXAxisLabelFormatter extends DefaultLabelFormatter { protected final String mFormat; - public TimeAsXAxisLabelFormatter(Context context, String format) { + public TimeAsXAxisLabelFormatter(String format) { mFormat = format; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/DismissNotificationService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/DismissNotificationService.java new file mode 100644 index 0000000000..ad102bdc11 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/DismissNotificationService.java @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.plugins.Overview.notifications; + +import android.app.IntentService; +import android.app.PendingIntent; +import android.content.Intent; +import android.support.annotation.Nullable; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; + +public class DismissNotificationService extends IntentService { + + /** + * Creates an IntentService. Invoked by your subclass's constructor. + * + * @param name Used to name the worker thread, important only for debugging. + */ + public DismissNotificationService(String name) { + super(name); + } + + public DismissNotificationService(){ + super("DismissNotificationService"); + }; + + @Override + protected void onHandleIntent(@Nullable Intent intent) { + MainApp.bus().post(new EventDismissNotification(intent.getIntExtra("alertID", -1))); + } + + 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); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java similarity index 77% rename from app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java index a857153c73..160e14c98b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java @@ -1,5 +1,8 @@ -package info.nightscout.androidaps.plugins.Overview; +package info.nightscout.androidaps.plugins.Overview.notifications; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Date; @@ -11,15 +14,14 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus import info.nightscout.utils.SP; // Added by Rumen for debugging -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + /** * Created by mike on 03.12.2016. */ public class Notification { private static Logger log = LoggerFactory.getLogger(Notification.class); - + public static final int URGENT = 0; public static final int NORMAL = 1; public static final int LOW = 2; @@ -50,7 +52,9 @@ public class Notification { public static final int SHORT_DIA = 21; public static final int TOAST_ALARM = 22; public static final int WRONGBASALSTEP = 23; - public static final int BOLUS_DELIVERY_ERROR = 24; + public static final int WRONG_DRIVER = 24; + public static final int PUMP_UNREACHABLE = 26; + public static final int BG_READINGS_MISSED = 27; public int id; public Date date; @@ -61,9 +65,6 @@ public class Notification { public NSAlarm nsAlarm = null; public Integer soundId = null; - public Notification() { - } - public Notification(int id, Date date, String text, int level, Date validTo) { this.id = id; this.date = date; @@ -88,6 +89,27 @@ public class Notification { this.validTo = new Date(0); } + public Notification(int id) { + this.id = id; + this.date = new Date(); + this.validTo = new Date(0); + } + + public Notification text(String text) { + this.text = text; + return this; + } + + public Notification level(int level) { + this.level = level; + return this; + } + + public Notification sound(int soundId) { + this.soundId = soundId; + return this; + } + public Notification(NSAlarm nsAlarm) { this.date = new Date(); this.validTo = new Date(0); @@ -103,7 +125,7 @@ public class Notification { this.id = NSALARM; this.level = NORMAL; this.text = nsAlarm.getTile(); - if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata,false)) + if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) this.soundId = R.raw.alarm; break; case 2: @@ -121,8 +143,7 @@ public class Notification { return true; if (level == ANNOUNCEMENT) return true; - if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) - { + if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) { return true; } if (level == URGENT && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_urgent_staledata, false)) @@ -153,14 +174,14 @@ public class Notification { return true; return false; } - - static boolean isAlarmForStaleData(){ - if(SP.getLong("snoozedTo", 0L) != 0L){ - if(System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) { + + static boolean isAlarmForStaleData() { + if (SP.getLong("snoozedTo", 0L) != 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; } - } + } BgReading bgReading = MainApp.getDbHelper().lastBg(); if (bgReading == null) return false; @@ -168,20 +189,20 @@ public class Notification { int bgReadingAgoMin = (int) (bgReadingAgo / (1000 * 60)); // Added for testing //bgReadingAgoMin = 20; - log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin); + log.debug("bgReadingAgoMin value is:" + bgReadingAgoMin); Double threshold = NSSettingsStatus.getInstance().getThreshold("alarmTimeagoWarnMins"); - boolean openAPSEnabledAlerts = NSSettingsStatus.getInstance().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)){ + boolean openAPSEnabledAlerts = NSSettingsStatus.getInstance().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 - SP.putLong("snoozedTo", (long) (bgReading.date+(threshold*1000*60L))); - //log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds"); + } + //snoozing for threshold + SP.putLong("snoozedTo", (long) (bgReading.date + (threshold * 1000 * 60L))); + //log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds"); return false; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java similarity index 53% rename from app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java index 8c70d3eea6..ce18c32734 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationStore.java @@ -1,6 +1,14 @@ -package info.nightscout.androidaps.plugins.Overview; +package info.nightscout.androidaps.plugins.Overview.notifications; +import android.app.NotificationManager; +import android.content.Context; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.AudioAttributes; +import android.media.RingtoneManager; +import android.net.Uri; +import android.support.v4.app.NotificationCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,7 +16,6 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.Date; import java.util.List; import info.nightscout.androidaps.MainApp; @@ -26,6 +33,7 @@ public class NotificationStore { private static Logger log = LoggerFactory.getLogger(NotificationStore.class); public List store = new ArrayList(); public long snoozedUntil = 0L; + public NotificationStore() { } @@ -49,21 +57,50 @@ public class NotificationStore { return; } } - if (n.soundId != null) { - Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); - alarm.putExtra("soundid", n.soundId); - MainApp.instance().startService(alarm); - } store.add(n); + if (SP.getBoolean(MainApp.sResources.getString(R.string.key_raise_notifications_as_android_notifications), false)) { + raiseSystemNotification(n); + } else { + if (n.soundId != null) { + Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); + alarm.putExtra("soundid", n.soundId); + MainApp.instance().startService(alarm); + } + } + WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class); - if(wearPlugin!= null && wearPlugin.isEnabled()) { + if (wearPlugin != null && wearPlugin.isEnabled()) { wearPlugin.overviewNotification(n.id, "OverviewNotification:\n" + n.text); } Collections.sort(store, new NotificationComparator()); } + private void raiseSystemNotification(Notification n) { + Context context = MainApp.instance().getApplicationContext(); + NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.blueowl); + Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); + NotificationCompat.Builder notificationBuilder = + new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.ic_notification) + .setLargeIcon(largeIcon) + .setContentText(n.text) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setDeleteIntent(DismissNotificationService.deleteIntent(n.id)); + if (n.level == Notification.URGENT) { + notificationBuilder.setVibrate(new long[]{1000, 1000, 1000, 1000}) + .setContentTitle(MainApp.sResources.getString(R.string.urgent_alarm)) + .setSound(sound, AudioAttributes.USAGE_ALARM); + } else { + notificationBuilder.setVibrate(new long[]{0, 100, 50, 100, 50}) + .setContentTitle(MainApp.sResources.getString(R.string.info)) + ; + } + mgr.notify(n.id, notificationBuilder.build()); + } + public boolean remove(int id) { for (int i = 0; i < store.size(); i++) { if (get(i).id == id) { @@ -87,14 +124,14 @@ public class NotificationStore { } } } - - public void snoozeTo(long timeToSnooze){ - log.debug("Snoozing alarm until: "+timeToSnooze); + + public void snoozeTo(long timeToSnooze) { + log.debug("Snoozing alarm until: " + timeToSnooze); SP.putLong("snoozedTo", timeToSnooze); } - - public void unSnooze(){ - if(Notification.isAlarmForStaleData()){ + + public void unSnooze() { + if (Notification.isAlarmForStaleData()) { Notification notification = new Notification(Notification.NSALARM, MainApp.sResources.getString(R.string.nsalarm_staledata), Notification.URGENT); SP.putLong("snoozedTo", System.currentTimeMillis()); add(notification); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java index f0745afe94..dc67a1449d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java @@ -29,7 +29,7 @@ import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.DecimalFormatter; /** @@ -95,25 +95,28 @@ public class PersistentNotificationPlugin implements PluginBase { @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (getType() == type) { this.fragmentEnabled = fragmentEnabled; + enableDisableNotification(fragmentEnabled); checkBusRegistration(); - //updateNotification(); } - } - private void updateNotification() { - + private void enableDisableNotification(boolean fragmentEnabled) { if (!fragmentEnabled) { NotificationManager mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.cancel(ONGOING_NOTIFICATION_ID); + } else { + updateNotification(); + } + } + + private void updateNotification() { + if (!fragmentEnabled) { return; } - String line1 = ctx.getString(R.string.noprofile); if (MainApp.getConfigBuilder().getActiveProfileInterface() == null || MainApp.getConfigBuilder().getProfile() == null) @@ -136,8 +139,6 @@ public class PersistentNotificationPlugin implements PluginBase { } } - PumpInterface pump = MainApp.getConfigBuilder(); - if (MainApp.getConfigBuilder().isTempBasalInProgress()) { TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); line1 += " " + activeTemp.toStringShort(); @@ -154,7 +155,7 @@ public class PersistentNotificationPlugin implements PluginBase { + ctx.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; - String line3 = DecimalFormatter.to2Decimal(pump.getBaseBasalRate()) + " U/h"; + String line3 = DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h"; line3 += " - " + MainApp.getConfigBuilder().getProfileName(); @@ -191,11 +192,16 @@ public class PersistentNotificationPlugin implements PluginBase { private void checkBusRegistration() { if (fragmentEnabled) { - MainApp.bus().register(this); + try { + MainApp.bus().register(this); + } catch (IllegalArgumentException e) { + // already registered + } } else { try { MainApp.bus().unregister(this); - } catch (Exception e) { + } catch (IllegalArgumentException e) { + // already unregistered } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java index 53ceed17a8..74b400e1af 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java @@ -35,11 +35,11 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventProfileSwitchChange; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SafeParse; @@ -151,8 +151,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment { iceditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_icedit); isfeditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_isfedit); - PumpInterface pump = MainApp.getConfigBuilder(); - if (!pump.getPumpDescription().isTempBasalCapable) { + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) { layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout).setVisibility(View.GONE); } @@ -334,7 +333,8 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment { adb.setPositiveButton("MIGRATE", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { CircadianPercentageProfilePlugin.migrateToLP(); - } }); + } + }); adb.setNegativeButton("Cancel", null); adb.show(); } @@ -366,7 +366,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment { } private void customSnackbar(View view, final String Msg, Object snackbarCaller) { - if(mSnackBar!= null) mSnackBar.dismiss(); + if (mSnackBar != null) mSnackBar.dismiss(); this.snackbarCaller = snackbarCaller; if (timeshiftViewHint || percentageViewHint) { @@ -522,7 +522,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { + if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) { profileswitchButton.setVisibility(View.GONE); } else { profileswitchButton.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java index ea4f32e794..949e7d1cf3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java @@ -16,12 +16,10 @@ 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.ProfileStore; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; @@ -173,34 +171,33 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte String msg = ""; - if (!fragmentEnabled){ - msg+= "NO CPP!" + "\n"; + if (!fragmentEnabled) { + msg += "NO CPP!" + "\n"; } //check for validity if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { - msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n"; + msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n"; } if (timeshift < 0 || timeshift > 23) { - msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n"; + msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n"; } - if(!SP.getBoolean("syncprofiletopump", false)){ - msg+= MainApp.sResources.getString(R.string.syncprofiletopump_title) + " " + MainApp.sResources.getString(R.string.cpp_sync_setting_missing) + "\n"; + if (!SP.getBoolean("syncprofiletopump", false)) { + msg += MainApp.sResources.getString(R.string.syncprofiletopump_title) + " " + MainApp.sResources.getString(R.string.cpp_sync_setting_missing) + "\n"; } - final PumpInterface pump = MainApp.getConfigBuilder(); final Profile profile = MainApp.getConfigBuilder().getProfile(); - if (pump == null || profile == null || profile.getBasal() == null){ - msg+= MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n"; + if (profile == null || profile.getBasal() == null) { + msg += MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n"; } - if(!"".equals(msg)) { + if (!"".equals(msg)) { msg += MainApp.sResources.getString(R.string.cpp_valuesnotstored); return msg; } //store profile - this.timeshift= timeshift; - this.percentage = percentage; + this.timeshift = timeshift; + this.percentage = percentage; storeSettings(); @@ -218,7 +215,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte return msg; } - public static void migrateToLP(){ + public static void migrateToLP() { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean("LocalProfile" + "mmol", SP.getBoolean(SETTINGS_PREFIX + "mmol", false)); @@ -232,7 +229,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte JSONArray targetHigh = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d))); editor.putString("LocalProfile" + "targetlow", targetLow.toString()); editor.putString("LocalProfile" + "targethigh", targetHigh.toString()); - } catch (JSONException e) { + } catch (JSONException e) { e.printStackTrace(); } editor.commit(); @@ -247,19 +244,19 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte } - public static String getLPisf(){ + public static String getLPisf() { return getLPConversion("baseisf", 35d); } - public static String getLPic(){ + public static String getLPic() { return getLPConversion("baseic", 4); } - public static String getLPbasal(){ + public static String getLPbasal() { return getLPConversion("basebasal", 1); } - public static String getLPConversion(String type, double defaultValue){ + public static String getLPConversion(String type, double defaultValue) { try { JSONArray jsonArray = new JSONArray(); double last = -1d; @@ -269,10 +266,10 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte String time; DecimalFormat df = new DecimalFormat("00"); time = df.format(i) + ":00"; - if(last != value) { + if (last != value) { jsonArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", value)); } - last = value; + last = value; } return jsonArray.toString(); } catch (JSONException e) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java index 24965861df..8637b863fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java @@ -23,11 +23,11 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SafeParse; @@ -59,8 +59,8 @@ public class LocalProfileFragment extends SubscriberFragment { @Override public void run() { localProfilePlugin.storeSettings(); - if(basalView!=null){ - basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label)+ ": "+ getSumLabel()); + if (basalView != null) { + basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel()); } } }; @@ -91,12 +91,11 @@ public class LocalProfileFragment extends SubscriberFragment { mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol); icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", getPlugin().ic, null, 0.1d, new DecimalFormat("0.0"), save); isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", getPlugin().isf, null, 0.1d, new DecimalFormat("0.0"), save); - basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label)+ ": " + getSumLabel(), getPlugin().basal, null, 0.01d, new DecimalFormat("0.00"), save); - targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label)+ ":", getPlugin().targetLow, getPlugin().targetHigh, 0.1d, new DecimalFormat("0.0"), save); + basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), getPlugin().basal, null, 0.01d, new DecimalFormat("0.00"), save); + targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label) + ":", getPlugin().targetLow, getPlugin().targetHigh, 0.1d, new DecimalFormat("0.0"), save); profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch); - PumpInterface pump = MainApp.getConfigBuilder(); - if (!pump.getPumpDescription().isTempBasalCapable) { + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) { layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE); } @@ -148,7 +147,7 @@ public class LocalProfileFragment extends SubscriberFragment { @NonNull public String getSumLabel() { - return " ∑" + DecimalFormatter.to2Decimal(localProfilePlugin.getProfile().getDefaultProfile().baseBasalSum()) +"U"; + return " ∑" + DecimalFormatter.to2Decimal(localProfilePlugin.getProfile().getDefaultProfile().baseBasalSum()) + "U"; } @Subscribe @@ -163,7 +162,7 @@ public class LocalProfileFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { + if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) { profileswitchButton.setVisibility(View.GONE); } else { profileswitchButton.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java index e4fdabecf9..9efa4250bc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java @@ -18,9 +18,10 @@ import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.SP; /** @@ -76,7 +77,7 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { @Override public boolean isVisibleInTabs(int type) { - return type == PROFILE && (Config.NSCLIENT ||fragmentVisible); + return type == PROFILE && (Config.NSCLIENT || fragmentVisible); } @Override @@ -119,16 +120,19 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { profile = new ProfileStore(newProfile.getData()); storeNSProfile(); MainApp.bus().post(new EventNSProfileUpdateGUI()); - PumpInterface pump = MainApp.getConfigBuilder(); if (SP.getBoolean("syncprofiletopump", false)) { - if (pump.setNewBasalProfile(MainApp.getConfigBuilder().getProfile()) == PumpInterface.SUCCESS) { - SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); - if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { - smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); + ConfigBuilderPlugin.getCommandQueue().setProfile(MainApp.getConfigBuilder().getProfile(), new Callback() { + @Override + public void run() { + if (result.enacted) { + SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); + if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { + smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); + } + } } - } + }); } - } private static void storeNSProfile() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java index 7bb5df792f..d24c59e511 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.ProfileNS.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventNSProfileUpdateGUI { +public class EventNSProfileUpdateGUI extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java index 88057a68c1..47080e26db 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java @@ -18,14 +18,13 @@ import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.SafeParse; public class SimpleProfileFragment extends SubscriberFragment { @@ -56,8 +55,7 @@ public class SimpleProfileFragment extends SubscriberFragment { targethighView = (EditText) layout.findViewById(R.id.simpleprofile_targethigh); profileswitchButton = (Button) layout.findViewById(R.id.simpleprofile_profileswitch); - PumpInterface pump = MainApp.getConfigBuilder(); - if (!pump.getPumpDescription().isTempBasalCapable) { + if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable) { layout.findViewById(R.id.simpleprofile_basalrate).setVisibility(View.GONE); layout.findViewById(R.id.simpleprofile_basalrate_label).setVisibility(View.GONE); } @@ -156,7 +154,7 @@ public class SimpleProfileFragment extends SubscriberFragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { + if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended()) { profileswitchButton.setVisibility(View.GONE); } else { profileswitchButton.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java index d48013b0e6..8ac6bb306b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java @@ -6,8 +6,8 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerThread; import android.support.v4.app.FragmentManager; +import android.text.Spanned; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -27,10 +27,12 @@ import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRStatsActivity; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.queue.events.EventQueueChanged; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SetWarnColor; @@ -38,11 +40,14 @@ import info.nightscout.utils.SetWarnColor; public class DanaRFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(DanaRFragment.class); - private static Handler sHandler; - private static HandlerThread sHandlerThread; - private Handler loopHandler = new Handler(); - private Runnable refreshLoop = null; + private Runnable refreshLoop = new Runnable() { + @Override + public void run() { + updateGUI(); + loopHandler.postDelayed(refreshLoop, 60 * 1000L); + } + }; TextView lastConnectionView; TextView btConnectionView; @@ -58,6 +63,7 @@ public class DanaRFragment extends SubscriberFragment { TextView basalStepView; TextView bolusStepView; TextView serialNumberView; + TextView queueView; Button viewProfileButton; Button historyButton; Button statsButton; @@ -65,35 +71,19 @@ public class DanaRFragment extends SubscriberFragment { LinearLayout pumpStatusLayout; TextView pumpStatusView; - static Runnable connectRunnable = new Runnable() { - @Override - public void run() { - MainApp.getConfigBuilder().refreshDataFromPump("Connect request from GUI"); - } - }; - - public DanaRFragment() { - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(DanaRFragment.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (refreshLoop == null) { - refreshLoop = new Runnable() { - @Override - public void run() { - updateGUI(); - loopHandler.postDelayed(refreshLoop, 60 * 1000L); - } - }; - loopHandler.postDelayed(refreshLoop, 60 * 1000L); - } + loopHandler.postDelayed(refreshLoop, 60 * 1000L); + } + + @Override + public void onDestroy() { + super.onDestroy(); + loopHandler.removeCallbacks(refreshLoop); } @Override @@ -118,6 +108,7 @@ public class DanaRFragment extends SubscriberFragment { basalStepView = (TextView) view.findViewById(R.id.danar_basalstep); bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep); serialNumberView = (TextView) view.findViewById(R.id.danar_serialnumber); + queueView = (TextView) view.findViewById(R.id.danar_queue); pumpStatusView = (TextView) view.findViewById(R.id.overview_pumpstatus); pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder)); @@ -150,7 +141,7 @@ public class DanaRFragment extends SubscriberFragment { @Override public void onClick(View v) { log.debug("Clicked connect to pump"); - sHandler.post(connectRunnable); + ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null); } }); @@ -206,6 +197,11 @@ public class DanaRFragment extends SubscriberFragment { updateGUI(); } + @Subscribe + public void onStatusEvent(final EventQueueChanged s) { + updateGUI(); + } + // GUI functions @Override protected void updateGUI() { @@ -226,15 +222,15 @@ public class DanaRFragment extends SubscriberFragment { Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime(); double agoHours = agoMsec / 60d / 60d / 1000d; if (agoHours < 6) // max 6h back - lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); + lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); else lastBolusView.setText(""); } dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U"); SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d); - basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getBaseBasalRate()) + " U/h"); + basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h"); // DanaRPlugin, DanaRKoreanPlugin - if (MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { + if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) { if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { tempBasalView.setText(MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull()); } else { @@ -266,10 +262,17 @@ public class DanaRFragment extends SubscriberFragment { basalStepView.setText("" + pump.basalStep); bolusStepView.setText("" + pump.bolusStep); serialNumberView.setText("" + pump.serialNumber); - + if (queueView != null) { + Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus(); + if (status.toString().equals("")) { + queueView.setVisibility(View.GONE); + } else { + queueView.setVisibility(View.VISIBLE); + queueView.setText(status); + } + } } }); - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index f7e1c6b92f..167c430a6e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -38,7 +38,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; @@ -229,7 +229,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled; + return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled && pump.maxBasal > 0; } @Override @@ -245,27 +245,35 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C // Pump interface @Override - public int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -294,13 +302,6 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C return pump.lastConnection; } - @Override - public void refreshDataFromPump(String reason) { - if (!isConnected() && !isConnecting()) { - doConnect(reason); - } - } - @Override public double getBaseBasalRate() { return pump.currentBasal; @@ -349,9 +350,10 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min - if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - doConnect("setTempBasalAbsolute old data"); - } + //This should not be needed while using queue because connection should be done before calling this + //if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { + // connect("setTempBasalAbsolute old data"); + //} PumpEnactResult result = new PumpEnactResult(); @@ -414,7 +416,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C log.debug("setTempBasalAbsolute: currently running: " + running.toString()); if (running.percentRate == percentRate) { if (enforceNew) { - cancelTempBasal(true); + cancelTempBasal(true); } else { result.success = true; result.percent = percentRate; @@ -542,7 +544,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } result.enacted = false; result.success = false; - result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + result.comment = MainApp.instance().getString(R.string.tempbasaldeliveryerror); log.error("setTempBasalPercent: Failed to set temp basal"); return result; } @@ -653,7 +655,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } } - public static void doConnect(String from) { + @Override + public void connect(String from) { if (sExecutionService != null) { sExecutionService.connect(from); pumpDescription.basalStep = pump.basalStep; @@ -661,18 +664,31 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return sExecutionService != null && sExecutionService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return sExecutionService != null && sExecutionService.isConnecting(); } - public static void doDisconnect(String from) { + @Override + public void disconnect(String from) { if (sExecutionService != null) sExecutionService.disconnect(from); } + @Override + public void stopConnecting() { + if (sExecutionService != null) sExecutionService.stopConnecting(); + } + + @Override + public void getPumpStatus() { + if (sExecutionService != null) sExecutionService.getPumpStatus(); + } + @Override public JSONObject getJSONStatus() { if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { @@ -736,10 +752,15 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C */ @Override - public boolean loadHistory(byte type) { + public PumpEnactResult loadHistory(byte type) { return sExecutionService.loadHistory(type); } + @Override + public PumpEnactResult loadEvents() { + return null; // no history, not needed + } + /** * Constraint interface */ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java index fc7a9a2411..5ae732c66a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java @@ -21,6 +21,7 @@ import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; @@ -44,14 +45,7 @@ public class ProfileViewDialog extends DialogFragment { private Button refreshButton; - Handler mHandler; - static HandlerThread mHandlerThread; - public ProfileViewDialog() { - mHandlerThread = new HandlerThread(ProfileViewDialog.class.getSimpleName()); - mHandlerThread.start(); - - mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -72,18 +66,7 @@ public class ProfileViewDialog extends DialogFragment { refreshButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mHandler.post(new Runnable() { - @Override - public void run() { - DanaRPump.getInstance().lastSettingsRead = new Date(0); - if (MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP)) - DanaRPlugin.doConnect("ProfileViewDialog"); - if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP)) - DanaRKoreanPlugin.doConnect("ProfileViewDialog"); - if (MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP)) - DanaRv2Plugin.doConnect("ProfileViewDialog"); - } - }); + ConfigBuilderPlugin.getCommandQueue().readStatus("ProfileViewDialog", null); dismiss(); } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java index 0612b9e1c3..62052486a8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java @@ -38,11 +38,13 @@ import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.ToastUtils; @@ -150,25 +152,19 @@ public class DanaRHistoryActivity extends Activity { reloadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - final PumpInterface pump = MainApp.getConfigBuilder().getActivePump(); - if (pump.isBusy()) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); - return; - } - mHandler.post(new Runnable() { + final TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + syncButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + } + }); + clearCardView(); + ConfigBuilderPlugin.getCommandQueue().loadHistory(selected.type, new Callback() { @Override public void run() { - TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); - runOnUiThread(new Runnable() { - @Override - public void run() { - reloadButton.setVisibility(View.GONE); - syncButton.setVisibility(View.GONE); - statusView.setVisibility(View.VISIBLE); - } - }); - clearCardView(); - ((DanaRInterface)pump).loadHistory(selected.type); loadDataFromDB(selected.type); runOnUiThread(new Runnable() { @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java index 5240005dc0..5facf015d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java @@ -40,24 +40,17 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.interfaces.DanaRInterface; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; -import info.nightscout.utils.ToastUtils; public class DanaRStatsActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); - private boolean mBounded; - - private Handler mHandler; - private static HandlerThread mHandlerThread; - TextView statusView, statsMessage, totalBaseBasal2; EditText totalBaseBasal; Button reloadButton; @@ -72,9 +65,6 @@ public class DanaRStatsActivity extends Activity { public DanaRStatsActivity() { super(); - mHandlerThread = new HandlerThread(DanaRStatsActivity.class.getSimpleName()); - mHandlerThread.start(); - this.mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -233,24 +223,18 @@ public class DanaRStatsActivity extends Activity { reloadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); - if (pump.isBusy()) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); - return; - } - mHandler.post(new Runnable() { + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + statsMessage.setVisibility(View.VISIBLE); + statsMessage.setText(getString(R.string.danar_stats_warning_Message)); + } + }); + ConfigBuilderPlugin.getCommandQueue().loadHistory(RecordTypes.RECORD_TYPE_DAILY, new Callback() { @Override public void run() { - runOnUiThread(new Runnable() { - @Override - public void run() { - reloadButton.setVisibility(View.GONE); - statusView.setVisibility(View.VISIBLE); - statsMessage.setVisibility(View.VISIBLE); - statsMessage.setText(getString(R.string.danar_stats_warning_Message)); - } - }); - ((DanaRInterface) pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY); loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); runOnUiThread(new Runnable() { @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java index c05029caff..3f0c306940 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java @@ -31,8 +31,7 @@ public class MsgCheckValue extends MessageBase { pump.protocol = intFromBuff(bytes, 1, 1); pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.EXPORT_MODEL) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model"); + MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); log.debug("Wrong model selected"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java index b39929db5b..83bd9dc77d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java @@ -7,7 +7,7 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java index dfd5788ec9..17f90a1ba7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java @@ -8,12 +8,14 @@ import java.util.Date; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.utils.ToastUtils; public class MsgInitConnStatusTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime.class); @@ -25,8 +27,9 @@ public class MsgInitConnStatusTime extends MessageBase { @Override public void handleMessage(byte[] bytes) { if (bytes.length - 10 > 7) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model"); + Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.sResources.getString(R.string.pumpdrivercorrected), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to Korean DanaR"); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); @@ -41,7 +44,8 @@ public class MsgInitConnStatusTime extends MessageBase { } MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshOverview("MsgInitConnStatusTime")); + MainApp.bus().post(new EventRefreshGui()); + ConfigBuilderPlugin.getCommandQueue().readStatus("PumpDriverChange", null); // force new connection return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java index dea2734a3e..01c80bc255 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; public class MsgSetBasalProfile extends MessageBase { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java index 32cd3745d8..1c79080093 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java @@ -1,14 +1,12 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; -import com.j256.ormlite.stmt.query.Not; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; public class MsgSetSingleBasalProfile extends MessageBase { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java index 727b6cd7fb..2d54d4f4a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java index 8217b51432..9e3af48fb2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.PumpDanaR.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 03.08.2016. */ -public class EventDanaRBolusStart { +public class EventDanaRBolusStart extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java index a04f27f2d6..55b0ab0998 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.PumpDanaR.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 08.07.2016. */ -public class EventDanaRNewStatus { +public class EventDanaRNewStatus extends Event { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java index b64cf22748..4e3f28de9d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java @@ -1,9 +1,11 @@ package info.nightscout.androidaps.plugins.PumpDanaR.events; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 20.07.2016. */ -public class EventDanaRSyncStatus { +public class EventDanaRSyncStatus extends Event { public String message; public EventDanaRSyncStatus() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java index 1ef5349f25..b3cc11cf2f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java @@ -10,7 +10,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.IBinder; -import android.os.PowerManager; import android.os.SystemClock; import com.squareup.otto.Subscribe; @@ -27,13 +26,14 @@ 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.PumpEnactResult; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -79,8 +79,9 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; @@ -94,14 +95,12 @@ public class DanaRExecutionService extends Service { private BluetoothSocket mRfcommSocket; private BluetoothDevice mBTDevice; - private PowerManager.WakeLock mWakeLock; private IBinder mBinder = new LocalBinder(); private DanaRPump danaRPump = DanaRPump.getInstance(); private Treatment bolusingTreatment = null; private static Boolean connectionInProgress = false; - private static final Object connectionLock = new Object(); private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); @@ -125,9 +124,6 @@ public class DanaRExecutionService extends Service { public DanaRExecutionService() { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); - - PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRExecutionService"); } public class LocalBinder extends Binder { @@ -189,35 +185,28 @@ public class DanaRExecutionService extends Service { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } - while (isConnected() || isConnecting()) { - if (Config.logDanaBTComm) - log.debug("already connected/connecting from: " + from); - waitMsec(3000); - } - final long maxConnectionTime = 5 * 60 * 1000L; // 5 min - synchronized (connectionLock) { - //log.debug("entering connection while loop"); - connectionInProgress = true; - mWakeLock.acquire(); - getBTSocketForSelectedPump(); - if (mRfcommSocket == null || mBTDevice == null) - return; // Device not found - long startTime = System.currentTimeMillis(); - while (!isConnected() && startTime + maxConnectionTime >= System.currentTimeMillis()) { - long secondsElapsed = (System.currentTimeMillis() - startTime) / 1000L; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); - if (Config.logDanaBTComm) - log.debug("connect waiting " + secondsElapsed + "sec from: " + from); + + if (connectionInProgress) + return; + + new Thread(new Runnable() { + @Override + public void run() { + connectionInProgress = true; + getBTSocketForSelectedPump(); + if (mRfcommSocket == null || mBTDevice == null) { + connectionInProgress = false; + return; // Device not found + } + try { mRfcommSocket.connect(); } catch (IOException e) { //log.error("Unhandled exception", e); if (e.getMessage().contains("socket closed")) { log.error("Unhandled exception", e); - break; } } - waitMsec(1000); if (isConnected()) { if (mSerialIOThread != null) { @@ -225,23 +214,16 @@ public class DanaRExecutionService extends Service { } mSerialIOThread = new SerialIOThread(mRfcommSocket); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); - if (!getPumpStatus()) { - mSerialIOThread.disconnect("getPumpStatus failed"); - waitMsec(3000); - if (!MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP)) - return; - getBTSocketForSelectedPump(); - startTime = System.currentTimeMillis(); - } } + + connectionInProgress = false; } - if (!isConnected()) { - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); - log.error("Pump connection timed out"); - } - connectionInProgress = false; - mWakeLock.release(); - } + }).start(); + } + + public void stopConnecting() { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("stopConnecting"); } private void getBTSocketForSelectedPump() { @@ -276,7 +258,7 @@ public class DanaRExecutionService extends Service { mSerialIOThread.disconnect("EventPreferenceChange"); } - private boolean getPumpStatus() { + public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); MsgStatus statusMsg = new MsgStatus(); @@ -288,7 +270,7 @@ public class DanaRExecutionService extends Service { if (danaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { - return false; + return; } } @@ -300,28 +282,6 @@ public class DanaRExecutionService extends Service { mSerialIOThread.sendMessage(exStatusMsg); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); - if (!statusMsg.received) { - mSerialIOThread.sendMessage(statusMsg); - } - if (!statusBasicMsg.received) { - mSerialIOThread.sendMessage(statusBasicMsg); - } - if (!tempStatusMsg.received) { - // Load of status of current basal rate failed, give one more try - mSerialIOThread.sendMessage(tempStatusMsg); - } - if (!exStatusMsg.received) { - // Load of status of current extended bolus failed, give one more try - mSerialIOThread.sendMessage(exStatusMsg); - } - - // Check we have really current status of pump - if (!statusMsg.received || !statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) { - waitMsec(10 * 1000); - log.debug("getPumpStatus failed"); - return false; - } - Date now = new Date(); if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); @@ -352,7 +312,7 @@ public class DanaRExecutionService extends Service { MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); - if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) { + if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); @@ -361,11 +321,9 @@ public class DanaRExecutionService extends Service { } catch (Exception e) { log.error("Unhandled exception", e); } - return true; } public boolean tempBasal(int percent, int durationInHours) { - connect("tempBasal"); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); @@ -380,7 +338,6 @@ public class DanaRExecutionService extends Service { } public boolean tempBasalStop() { - connect("tempBasalStop"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); @@ -390,7 +347,6 @@ public class DanaRExecutionService extends Service { } public boolean extendedBolus(double insulin, int durationInHalfHours) { - connect("extendedBolus"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); @@ -400,7 +356,6 @@ public class DanaRExecutionService extends Service { } public boolean extendedBolusStop() { - connect("extendedBolusStop"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); @@ -409,7 +364,7 @@ public class DanaRExecutionService extends Service { return true; } - public boolean bolus(double amount, int carbs, Treatment t) { + public boolean bolus(double amount, int carbs, final Treatment t) { bolusingTreatment = t; int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); MessageBase start; @@ -419,7 +374,6 @@ public class DanaRExecutionService extends Service { start = new MsgBolusStartWithSpeed(amount, preferencesSpeed); MsgBolusStop stop = new MsgBolusStop(amount, t); - connect("bolus"); if (!isConnected()) return false; if (carbs > 0) { @@ -437,7 +391,7 @@ public class DanaRExecutionService extends Service { } while (!stop.stopped && !start.failed) { waitMsec(100); - if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); @@ -475,16 +429,27 @@ public class DanaRExecutionService extends Service { MainApp.bus().post(bolusingEvent); SystemClock.sleep(1000); } - connect("bolusingInterrupted"); - getPumpStatus(); - if (danaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old - t.insulin = danaRPump.lastBolusAmount; - log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount); - } else { - log.debug("Bolus amount in history too old: " + danaRPump.lastBolusTime.toLocaleString()); + + final Object o = new Object(); + ConfigBuilderPlugin.getCommandQueue().readStatus("bolusingInterrupted", new Callback() { + @Override + public void run() { + if (danaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old + t.insulin = danaRPump.lastBolusAmount; + log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount); + } else { + log.debug("Bolus amount in history too old: " + danaRPump.lastBolusTime.toLocaleString()); + } + o.notify(); + } + }); + try { + o.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); } } else { - getPumpStatus(); + ConfigBuilderPlugin.getCommandQueue().readStatus("bolusOK", null); } return true; } @@ -506,16 +471,15 @@ public class DanaRExecutionService extends Service { } public boolean carbsEntry(int amount) { - connect("carbsEntry"); if (!isConnected()) return false; MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount); mSerialIOThread.sendMessage(msg); return true; } - public boolean loadHistory(byte type) { - connect("loadHistory"); - if (!isConnected()) return false; + public PumpEnactResult loadHistory(byte type) { + PumpEnactResult result = new PumpEnactResult(); + if (!isConnected()) return result; MessageBase msg = null; switch (type) { case RecordTypes.RECORD_TYPE_ALARM: @@ -555,11 +519,12 @@ public class DanaRExecutionService extends Service { } waitMsec(200); mSerialIOThread.sendMessage(new MsgPCCommStop()); - return true; + result.success = true; + result.comment = "OK"; + return result; } public boolean updateBasalsInPump(final Profile profile) { - connect("updateBasalsInPump"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); double[] basal = DanaRPump.buildDanaRProfileRecord(profile); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index cda438aded..32c9f209ef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -38,7 +38,7 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; @@ -61,9 +61,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf return DanaRFragment.class.getName(); } - private boolean fragmentPumpEnabled = false; - private boolean fragmentProfileEnabled = false; - private boolean fragmentPumpVisible = true; + private static boolean fragmentPumpEnabled = false; + private static boolean fragmentProfileEnabled = false; + private static boolean fragmentPumpVisible = true; private static DanaRKoreanExecutionService sExecutionService; @@ -201,11 +201,11 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PluginBase.PROFILE) - this.fragmentProfileEnabled = fragmentEnabled; + fragmentProfileEnabled = fragmentEnabled; else if (type == PluginBase.PUMP) - this.fragmentPumpEnabled = fragmentEnabled; + fragmentPumpEnabled = fragmentEnabled; // if pump profile was enabled need to switch to another too - if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) { + if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) { setFragmentEnabled(PluginBase.PROFILE, false); setFragmentVisible(PluginBase.PROFILE, false); NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); @@ -216,7 +216,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf @Override public void setFragmentVisible(int type, boolean fragmentVisible) { if (type == PluginBase.PUMP) - this.fragmentPumpVisible = fragmentVisible; + fragmentPumpVisible = fragmentVisible; } @Override @@ -231,7 +231,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled; + return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled; } @Override @@ -247,27 +247,35 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf // Pump interface @Override - public int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -296,13 +304,6 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf return pump.lastConnection; } - @Override - public void refreshDataFromPump(String reason) { - if (!isConnected() && !isConnecting()) { - doConnect(reason); - } - } - @Override public double getBaseBasalRate() { return pump.currentBasal; @@ -315,8 +316,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { Treatment t = new Treatment(); boolean connectionOK = false; - if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) - connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; @@ -352,9 +352,10 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min - if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - doConnect("setTempBasalAbsolute old data"); - } + //This should not be needed while using queue because connection should be done before calling this + //if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { + // connect("setTempBasalAbsolute old data"); + //} PumpEnactResult result = new PumpEnactResult(); @@ -393,9 +394,12 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); - if (percentRate > 200) { - percentRate = 200; + if (percentRate > getPumpDescription().maxTempPercent) { + percentRate = getPumpDescription().maxTempPercent; } + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Calculated percent rate: " + percentRate); + // If extended in progress if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (Config.logPumpActions) @@ -409,7 +413,10 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf // Check if some temp is already in progress if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { // Correct basal already set ? - if (MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).percentRate == percentRate) { + TemporaryBasal running = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: currently running: " + running.toString()); + if (running.percentRate == percentRate) { if (enforceNew) { cancelTempBasal(true); } else { @@ -450,7 +457,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf Double extendedRateToSet = absoluteRate - getBaseBasalRate(); extendedRateToSet = configBuilderPlugin.applyBasalConstraints(extendedRateToSet); // needs to be rounded to 0.1 - extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of 30 min + extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of halfhours // What is current rate of extended bolusing in u/h? if (Config.logPumpActions) { @@ -650,7 +657,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } } - public static void doConnect(String from) { + @Override + public void connect(String from) { if (sExecutionService != null) { sExecutionService.connect(from); pumpDescription.basalStep = pump.basalStep; @@ -658,18 +666,31 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return sExecutionService != null && sExecutionService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return sExecutionService != null && sExecutionService.isConnecting(); } - public static void doDisconnect(String from) { + @Override + public void disconnect(String from) { if (sExecutionService != null) sExecutionService.disconnect(from); } + @Override + public void stopConnecting() { + if (sExecutionService != null) sExecutionService.stopConnecting(); + } + + @Override + public void getPumpStatus() { + if (sExecutionService != null) sExecutionService.getPumpStatus(); + } + @Override public JSONObject getJSONStatus() { if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { @@ -733,10 +754,15 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf */ @Override - public boolean loadHistory(byte type) { + public PumpEnactResult loadHistory(byte type) { return sExecutionService.loadHistory(type); } + @Override + public PumpEnactResult loadEvents() { + return null; // no history, not needed + } + /** * Constraint interface */ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java index 7536bd278c..684fa30997 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java @@ -32,8 +32,7 @@ public class MsgCheckValue_k extends MessageBase { pump.protocol = intFromBuff(bytes, 1, 1); pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.DOMESTIC_MODEL) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); + DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java index 26462987d9..82beecc5e9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java index 2e6d6234f0..bf105b8db0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java @@ -8,7 +8,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java index f54b8edb30..641dce79f3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java @@ -8,13 +8,15 @@ import java.util.Date; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.utils.ToastUtils; public class MsgInitConnStatusTime_k extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime_k.class); @@ -27,8 +29,9 @@ public class MsgInitConnStatusTime_k extends MessageBase { public void handleMessage(byte[] bytes) { if (bytes.length - 10 < 10) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); + Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.sResources.getString(R.string.pumpdrivercorrected), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to export DanaR"); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false); @@ -37,13 +40,14 @@ public class MsgInitConnStatusTime_k extends MessageBase { DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized //If profile coming from pump, switch it as well - if(MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)){ + if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)) { (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); } MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshOverview("MsgInitConnStatusTime_k")); + MainApp.bus().post(new EventRefreshGui()); + ConfigBuilderPlugin.getCommandQueue().readStatus("PumpDriverChange", null); // force new connection return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java index f77c03e337..9d656e47e5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java @@ -10,7 +10,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.IBinder; -import android.os.PowerManager; import android.os.SystemClock; import com.squareup.otto.Subscribe; @@ -27,13 +26,15 @@ 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.PumpEnactResult; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; @@ -70,11 +71,12 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue_k; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k; import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; @@ -88,14 +90,12 @@ public class DanaRKoreanExecutionService extends Service { private BluetoothSocket mRfcommSocket; private BluetoothDevice mBTDevice; - private PowerManager.WakeLock mWakeLock; private IBinder mBinder = new LocalBinder(); private DanaRPump danaRPump = DanaRPump.getInstance(); private Treatment bolusingTreatment = null; private static Boolean connectionInProgress = false; - private static final Object connectionLock = new Object(); private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); @@ -119,9 +119,6 @@ public class DanaRKoreanExecutionService extends Service { public DanaRKoreanExecutionService() { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); - - PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRKoreanExecutionService"); } public class LocalBinder extends Binder { @@ -183,35 +180,28 @@ public class DanaRKoreanExecutionService extends Service { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } - while (isConnected() || isConnecting()) { - if (Config.logDanaBTComm) - log.debug("already connected/connecting from: " + from); - waitMsec(3000); - } - final long maxConnectionTime = 5 * 60 * 1000L; // 5 min - synchronized (connectionLock) { - //log.debug("entering connection while loop"); - connectionInProgress = true; - mWakeLock.acquire(); - getBTSocketForSelectedPump(); - if (mRfcommSocket == null || mBTDevice == null) - return; // Device not found - long startTime = System.currentTimeMillis(); - while (!isConnected() && startTime + maxConnectionTime >= System.currentTimeMillis()) { - long secondsElapsed = (System.currentTimeMillis() - startTime) / 1000L; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); - if (Config.logDanaBTComm) - log.debug("connect waiting " + secondsElapsed + "sec from: " + from); + + if (connectionInProgress) + return; + + new Thread(new Runnable() { + @Override + public void run() { + connectionInProgress = true; + getBTSocketForSelectedPump(); + if (mRfcommSocket == null || mBTDevice == null) { + connectionInProgress = false; + return; // Device not found + } + try { mRfcommSocket.connect(); } catch (IOException e) { //log.error("Unhandled exception", e); if (e.getMessage().contains("socket closed")) { log.error("Unhandled exception", e); - break; } } - waitMsec(1000); if (isConnected()) { if (mSerialIOThread != null) { @@ -219,23 +209,16 @@ public class DanaRKoreanExecutionService extends Service { } mSerialIOThread = new SerialIOThread(mRfcommSocket); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); - if (!getPumpStatus()) { - mSerialIOThread.disconnect("getPumpStatus failed"); - waitMsec(3000); - if (!MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP)) - return; - getBTSocketForSelectedPump(); - startTime = System.currentTimeMillis(); - } } + + connectionInProgress = false; } - if (!isConnected()) { - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); - log.error("Pump connection timed out"); - } - connectionInProgress = false; - mWakeLock.release(); - } + }).start(); + } + + public void stopConnecting() { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("stopConnecting"); } private void getBTSocketForSelectedPump() { @@ -270,7 +253,7 @@ public class DanaRKoreanExecutionService extends Service { mSerialIOThread.disconnect("EventPreferenceChange"); } - private boolean getPumpStatus() { + public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); //MsgStatus_k statusMsg = new MsgStatus_k(); @@ -282,7 +265,7 @@ public class DanaRKoreanExecutionService extends Service { if (danaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { - return false; + return; } } @@ -294,28 +277,6 @@ public class DanaRKoreanExecutionService extends Service { mSerialIOThread.sendMessage(exStatusMsg); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); -// if (!statusMsg.received) { -// mSerialIOThread.sendMessage(statusMsg); -// } - if (!statusBasicMsg.received) { - mSerialIOThread.sendMessage(statusBasicMsg); - } - if (!tempStatusMsg.received) { - // Load of status of current basal rate failed, give one more try - mSerialIOThread.sendMessage(tempStatusMsg); - } - if (!exStatusMsg.received) { - // Load of status of current extended bolus failed, give one more try - mSerialIOThread.sendMessage(exStatusMsg); - } - - // Check we have really current status of pump - if (/*!statusMsg.received || */!statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) { - waitMsec(10 * 1000); - log.debug("getPumpStatus failed"); - return false; - } - Date now = new Date(); if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); @@ -343,7 +304,7 @@ public class DanaRKoreanExecutionService extends Service { MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); NSUpload.uploadDeviceStatus(); - if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) { + if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) { log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits); Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); @@ -352,11 +313,10 @@ public class DanaRKoreanExecutionService extends Service { } catch (Exception e) { log.error("Unhandled exception", e); } - return true; + return; } public boolean tempBasal(int percent, int durationInHours) { - connect("tempBasal"); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); @@ -371,7 +331,6 @@ public class DanaRKoreanExecutionService extends Service { } public boolean tempBasalStop() { - connect("tempBasalStop"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); @@ -381,7 +340,6 @@ public class DanaRKoreanExecutionService extends Service { } public boolean extendedBolus(double insulin, int durationInHalfHours) { - connect("extendedBolus"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); @@ -391,7 +349,6 @@ public class DanaRKoreanExecutionService extends Service { } public boolean extendedBolusStop() { - connect("extendedBolusStop"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); @@ -400,12 +357,11 @@ public class DanaRKoreanExecutionService extends Service { return true; } - public boolean bolus(double amount, int carbs, Treatment t) { + public boolean bolus(double amount, int carbs, final Treatment t) { bolusingTreatment = t; MsgBolusStart start = new MsgBolusStart(amount); MsgBolusStop stop = new MsgBolusStop(amount, t); - connect("bolus"); if (!isConnected()) return false; if (carbs > 0) { @@ -413,6 +369,7 @@ public class DanaRKoreanExecutionService extends Service { } MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables + long bolusStart = System.currentTimeMillis(); if (!stop.stopped) { mSerialIOThread.sendMessage(start); @@ -422,15 +379,56 @@ public class DanaRKoreanExecutionService extends Service { } while (!stop.stopped && !start.failed) { waitMsec(100); - if ((System.currentTimeMillis() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); } } waitMsec(300); + + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + bolusingEvent.t = t; + bolusingEvent.percent = 99; + bolusingTreatment = null; - getPumpStatus(); + + int speed = 12; + + // try to find real amount if bolusing was interrupted or comm failed + if (t.insulin != amount) { + disconnect("bolusingInterrupted"); + long bolusDurationInMSec = (long) (amount * speed * 1000); + long expectedEnd = bolusStart + bolusDurationInMSec + 3000; + + while (System.currentTimeMillis() < expectedEnd) { + long waitTime = expectedEnd - System.currentTimeMillis(); + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.waitingforestimatedbolusend), waitTime / 1000); + MainApp.bus().post(bolusingEvent); + SystemClock.sleep(1000); + } + + final Object o = new Object(); + ConfigBuilderPlugin.getCommandQueue().readStatus("bolusingInterrupted", new Callback() { + @Override + public void run() { + if (danaRPump.lastBolusTime.getTime() > System.currentTimeMillis() - 60 * 1000L) { // last bolus max 1 min old + t.insulin = danaRPump.lastBolusAmount; + log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount); + } else { + log.debug("Bolus amount in history too old: " + danaRPump.lastBolusTime.toLocaleString()); + } + o.notify(); + } + }); + try { + o.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + ConfigBuilderPlugin.getCommandQueue().readStatus("bolusOK", null); + } return true; } @@ -451,16 +449,15 @@ public class DanaRKoreanExecutionService extends Service { } public boolean carbsEntry(int amount) { - connect("carbsEntry"); if (!isConnected()) return false; MsgSetCarbsEntry msg = new MsgSetCarbsEntry(System.currentTimeMillis(), amount); mSerialIOThread.sendMessage(msg); return true; } - public boolean loadHistory(byte type) { - connect("loadHistory"); - if (!isConnected()) return false; + public PumpEnactResult loadHistory(byte type) { + PumpEnactResult result = new PumpEnactResult(); + if (!isConnected()) return result; MessageBase msg = null; switch (type) { case RecordTypes.RECORD_TYPE_ALARM: @@ -500,11 +497,12 @@ public class DanaRKoreanExecutionService extends Service { } waitMsec(200); mSerialIOThread.sendMessage(new MsgPCCommStop()); - return true; + result.success = true; + result.comment = "OK"; + return result; } public boolean updateBasalsInPump(final Profile profile) { - connect("updateBasalsInPump"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); double[] basal = DanaRPump.buildDanaRProfileRecord(profile); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java index 916213c270..3a57eaf298 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java @@ -20,6 +20,8 @@ import java.util.Objects; import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.ProfileStore; @@ -27,7 +29,7 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; @@ -36,16 +38,12 @@ import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; -import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSDeviceChange; import info.nightscout.androidaps.plugins.PumpDanaRS.services.DanaRSService; import info.nightscout.utils.DateUtil; @@ -219,60 +217,54 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, mDeviceName = SP.getString(R.string.key_danars_name, ""); } - public static void connectIfNotConnected(String from) { - if (!isConnected()) - connect(from); - } - - public static void connect(String from) { + @Override + public void connect(String from) { log.debug("RS connect from: " + from); if (danaRSService != null && !mDeviceAddress.equals("") && !mDeviceName.equals("")) { final Object o = new Object(); danaRSService.connect(from, mDeviceAddress, o); - synchronized (o) { - try { - o.wait(20000); - } catch (InterruptedException e) { - log.error("InterruptedException " + e); - } - } pumpDescription.basalStep = pump.basalStep; pumpDescription.bolusStep = pump.bolusStep; - if (isConnected()) - log.debug("RS connected: " + from); - else { - MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.connectiontimedout))); - danaRSService.stopConnecting(); - log.debug("RS connect failed from: " + from); - } } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return danaRSService != null && danaRSService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return danaRSService != null && danaRSService.isConnecting(); } - public static void disconnect(String from) { + @Override + public void disconnect(String from) { if (danaRSService != null) danaRSService.disconnect(from); } - public static void sendMessage(DanaRS_Packet message) { - if (danaRSService != null) danaRSService.sendMessage(message); + @Override + public void stopConnecting() { + if (danaRSService != null) danaRSService.stopConnecting(); + } + + @Override + public void getPumpStatus() { + if (danaRSService != null) + danaRSService.getPumpStatus(); } // DanaR interface @Override - public boolean loadHistory(byte type) { - connectIfNotConnected("loadHistory"); - danaRSService.loadHistory(type); - disconnect("LoadHistory"); - return true; + public PumpEnactResult loadHistory(byte type) { + return danaRSService.loadHistory(type); + } + + @Override + public PumpEnactResult loadEvents() { + return danaRSService.loadEvents(); } // Constraints interface @@ -368,7 +360,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0; + return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0; } @Override @@ -383,30 +375,35 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, } @Override - public synchronized int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (danaRSService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } - connectIfNotConnected("updateBasalsInPump"); if (!danaRSService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - disconnect("SetNewBasalProfile"); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - disconnect("SetNewBasalProfile"); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -435,16 +432,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, return pump.lastConnection; } - @Override - public synchronized void refreshDataFromPump(String reason) { - log.debug("Refreshing data from pump"); - if (!isConnected() && !isConnecting()) { - connect(reason); - disconnect("RefreshDataFromPump"); - } else - log.debug("Already connecting ..."); - } - @Override public double getBaseBasalRate() { return pump.currentBasal; @@ -482,7 +469,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, Treatment t = new Treatment(); boolean connectionOK = false; - connectIfNotConnected("bolus"); if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000 + 1000, t); // +1000 to make the record different PumpEnactResult result = new PumpEnactResult(); @@ -492,7 +478,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); if (Config.logPumpActions) log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered); - disconnect("DeliverTreatment"); return result; } else { PumpEnactResult result = new PumpEnactResult(); @@ -518,9 +503,11 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min - if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - connect("setTempBasalAbsolute old data"); - } + + //This should not be needed while using queue because connection should be done before calling this + //if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { + // connect("setTempBasalAbsolute old data"); + //} PumpEnactResult result = new PumpEnactResult(); @@ -607,7 +594,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, } if (percent > getPumpDescription().maxTempPercent) percent = getPumpDescription().maxTempPercent; - TemporaryBasal runningTB = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); + TemporaryBasal runningTB = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); if (runningTB != null && runningTB.percentRate == percent) { result.enacted = false; result.success = true; @@ -622,7 +609,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, return result; } int durationInHours = Math.max(durationInMinutes / 60, 1); - connectIfNotConnected("tempbasal"); boolean connectionOK = danaRSService.tempBasal(percent, durationInHours); if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { result.enacted = true; @@ -635,7 +621,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: OK"); - disconnect("setTempBasalPercent"); return result; } result.enacted = false; @@ -647,7 +632,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, public synchronized PumpEnactResult setHighTempBasalPercent(Integer percent) { PumpEnactResult result = new PumpEnactResult(); - connectIfNotConnected("hightempbasal"); boolean connectionOK = danaRSService.highTempBasal(percent); if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { result.enacted = true; @@ -659,7 +643,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.isPercent = true; if (Config.logPumpActions) log.debug("setHighTempBasalPercent: OK"); - disconnect("setHighTempBasalPercent"); return result; } result.enacted = false; @@ -690,7 +673,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); return result; } - connectIfNotConnected("extendedBolus"); boolean connectionOK = danaRSService.extendedBolus(insulin, durationInHalfHours); if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { result.enacted = true; @@ -703,7 +685,6 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, result.isPercent = false; if (Config.logPumpActions) log.debug("setExtendedBolus: OK"); - disconnect("setExtendedBolus"); return result; } result.enacted = false; @@ -716,13 +697,11 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, @Override public synchronized PumpEnactResult cancelTempBasal(boolean force) { PumpEnactResult result = new PumpEnactResult(); - TemporaryBasal runningTB = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); + TemporaryBasal runningTB = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); if (runningTB != null) { - connectIfNotConnected("tempBasalStop"); danaRSService.tempBasalStop(); result.enacted = true; result.isTempCancel = true; - disconnect("cancelTempBasal"); } if (!pump.isTempBasalInProgress) { result.success = true; @@ -745,11 +724,9 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, PumpEnactResult result = new PumpEnactResult(); ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); if (runningEB != null) { - connectIfNotConnected("extendedBolusStop"); danaRSService.extendedBolusStop(); result.enacted = true; result.isTempCancel = true; - disconnect("extendedBolusStop"); } if (!pump.isExtendedInProgress) { result.success = true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java index 8e58dc2cb5..c11b75764c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java @@ -30,8 +30,8 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { private int min = 0; private int sec = 0; - public boolean done; - private int totalCount; + public static boolean done; + private static int totalCount; public static long lastEventTimeLoaded = 0; @@ -77,6 +77,7 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet { // Last record if (recordCode == (byte) 0xFF) { done = true; + log.debug("Last record received"); return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java index efc87d3834..048912a23d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java @@ -7,7 +7,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java index 61296f42ed..eb4af6b25f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java @@ -8,7 +8,7 @@ import com.cozmo.danar.util.BleCommandUtil; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java index 922b7886f2..6166f7b0fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java @@ -33,14 +33,14 @@ public class DanaRS_Packet_Bolus_Get_Step_Bolus_Information extends DanaRS_Packe dataSize = 2; pump.initialBolusAmount = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d; - Date lastBolusTime = new Date(); // it doesn't provide day only hour+min, workaround: expecting today + pump.lastBolusTime = new Date(); // it doesn't provide day only hour+min, workaround: expecting today dataIndex += dataSize; dataSize = 1; - lastBolusTime.setHours(byteArrayToInt(getBytes(data, dataIndex, dataSize))); + pump.lastBolusTime.setHours(byteArrayToInt(getBytes(data, dataIndex, dataSize))); dataIndex += dataSize; dataSize = 1; - lastBolusTime.setMinutes(byteArrayToInt(getBytes(data, dataIndex, dataSize))); + pump.lastBolusTime.setMinutes(byteArrayToInt(getBytes(data, dataIndex, dataSize))); dataIndex += dataSize; dataSize = 2; @@ -58,7 +58,7 @@ public class DanaRS_Packet_Bolus_Get_Step_Bolus_Information extends DanaRS_Packe log.debug("Result: " + error); log.debug("BolusType: " + bolusType); log.debug("Initial bolus amount: " + pump.initialBolusAmount + " U"); - log.debug("Last bolus time: " + lastBolusTime.toLocaleString()); + log.debug("Last bolus time: " + pump.lastBolusTime.toLocaleString()); log.debug("Last bolus amount: " + pump.lastBolusAmount); log.debug("Max bolus: " + pump.maxBolus + " U"); log.debug("Bolus step: " + pump.bolusStep + " U"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java index c38439d7eb..4818f4481d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java @@ -6,11 +6,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class DanaRS_Packet_General_Get_Pump_Check extends DanaRS_Packet { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java index 42f077887d..f8d18a4d22 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java @@ -10,8 +10,6 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; -import android.os.Handler; -import android.os.HandlerThread; import android.os.SystemClock; import com.cozmo.danar.util.BleCommandUtil; @@ -25,7 +23,6 @@ import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -33,7 +30,6 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingHelperActivity; -import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingProgressDialog; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRSMessageHashTable; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet; import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPacket; @@ -62,27 +58,12 @@ public class BLEComm { return instance; } - private Object mConfirmConnect = null; - private final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture scheduledDisconnection = null; private DanaRS_Packet processsedMessage = null; private ArrayList mSendQueue = new ArrayList<>(); - // Variables for connection progress (elapsed time) - private Handler sHandler; - private HandlerThread sHandlerThread; - private long connectionStartTime = 0; - private final Runnable updateProgress = new Runnable() { - @Override - public void run() { - long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); - sHandler.postDelayed(updateProgress, 1000); - } - }; - private BluetoothManager mBluetoothManager = null; private BluetoothAdapter mBluetoothAdapter = null; private BluetoothDevice mBluetoothDevice = null; @@ -101,12 +82,6 @@ public class BLEComm { BLEComm(DanaRSService service) { this.service = service; initialize(); - - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(PairingProgressDialog.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } } private boolean initialize() { @@ -138,7 +113,6 @@ public class BLEComm { } public boolean connect(String from, String address, Object confirmConnect) { - mConfirmConnect = confirmConnect; BluetoothManager tBluetoothManager = ((BluetoothManager) MainApp.instance().getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE)); if (tBluetoothManager == null) { return false; @@ -160,9 +134,6 @@ public class BLEComm { return false; } - connectionStartTime = System.currentTimeMillis(); - - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING)); isConnecting = true; BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); @@ -171,10 +142,9 @@ public class BLEComm { return false; } - sHandler.post(updateProgress); + log.debug("Trying to create a new connection."); mBluetoothGatt = device.connectGatt(service.getApplicationContext(), false, mGattCallback); setCharacteristicNotification(getUARTReadBTGattChar(), true); - log.debug("Trying to create a new connection."); mBluetoothDevice = device; mBluetoothDeviceAddress = address; mBluetoothDeviceName = device.getName(); @@ -183,7 +153,6 @@ public class BLEComm { public void stopConnecting() { isConnecting = false; - sHandler.removeCallbacks(updateProgress); // just to be sure } public void disconnect(String from) { @@ -234,7 +203,7 @@ public class BLEComm { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { close(); isConnected = false; - sHandler.removeCallbacks(updateProgress); // just to be sure + isConnecting = false; MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); log.debug("Device was disconnected " + gatt.getDevice().getName());//Device was disconnected } @@ -242,14 +211,9 @@ public class BLEComm { public void onServicesDiscovered(BluetoothGatt gatt, int status) { log.debug("onServicesDiscovered"); - - isConnecting = false; - if (status == BluetoothGatt.GATT_SUCCESS) { findCharacteristic(); } - // stop sending connection progress - sHandler.removeCallbacks(updateProgress); SendPumpCheck(); // 1st message sent to pump after connect } @@ -516,18 +480,11 @@ public class BLEComm { pass = pass ^ 3463; DanaRPump.getInstance().rs_password = Integer.toHexString(pass); log.debug("Pump user password: " + Integer.toHexString(pass)); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED)); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED)); isConnected = true; isConnecting = false; - service.getPumpStatus(); - scheduleDisconnection(); - if (mConfirmConnect != null) { - synchronized (mConfirmConnect) { - mConfirmConnect.notify(); - mConfirmConnect = null; - } - } + log.debug("RS connected and status read"); break; } break; @@ -557,7 +514,6 @@ public class BLEComm { } else { log.error("Unknown message received " + DanaRS_Packet.toHexString(inputBuffer)); } - scheduleDisconnection(); break; } } catch (Exception e) { @@ -652,7 +608,6 @@ public class BLEComm { if (!message.isReceived()) { log.warn("Reply not received " + message.getFriendlyName()); } - scheduleDisconnection(); } private void SendPairingRequest() { @@ -681,22 +636,4 @@ public class BLEComm { writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes); } - public void scheduleDisconnection() { - - class DisconnectRunnable implements Runnable { - public void run() { - disconnect("scheduleDisconnection"); - scheduledDisconnection = null; - } - } - // prepare task for execution in 30 sec - // cancel waiting task to prevent sending multiple disconnections - if (scheduledDisconnection != null) - scheduledDisconnection.cancel(false); - Runnable task = new DisconnectRunnable(); - final int sec = 30; - scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS); - log.debug("Disconnection scheduled"); - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java index 399254f84b..e5ad663bae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java @@ -1,11 +1,9 @@ package info.nightscout.androidaps.plugins.PumpDanaRS.services; import android.app.Service; -import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; -import android.os.PowerManager; import android.os.SystemClock; import com.squareup.otto.Subscribe; @@ -20,11 +18,13 @@ 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.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -69,6 +69,7 @@ import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_D import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_Delivery_Rate_Display; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Get_Pump_Time; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_Pump_Time; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; @@ -77,7 +78,6 @@ public class DanaRSService extends Service { private BLEComm bleComm = BLEComm.getInstance(this); - private PowerManager.WakeLock mWakeLock; private IBinder mBinder = new LocalBinder(); private DanaRPump danaRPump = DanaRPump.getInstance(); @@ -92,10 +92,6 @@ public class DanaRSService extends Service { // Ignore } MainApp.bus().register(this); - - PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DanaRSService.class.getSimpleName()); - } public boolean isConnected() { @@ -122,7 +118,7 @@ public class DanaRSService extends Service { bleComm.sendMessage(message); } - protected boolean getPumpStatus() { + public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); @@ -130,7 +126,7 @@ public class DanaRSService extends Service { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus))); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State()); MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); - bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus + bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus, bolusStep, maxBolus MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus))); bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State()); @@ -141,7 +137,6 @@ public class DanaRSService extends Service { bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Profile_Number()); bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Bolus_Option()); // isExtendedEnabled - bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // bolusStep, maxBolus bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate()); // basal profile, basalStep, maxBasal bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Calculation_Information()); // target bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_CIR_CF_Array()); @@ -173,10 +168,10 @@ public class DanaRSService extends Service { } catch (Exception e) { log.error("Unhandled exception", e); } - return true; + log.debug("Pump status loaded"); } - public boolean loadEvents() { + public PumpEnactResult loadEvents() { DanaRS_Packet_APS_History_Events msg; if (lastHistoryFetched == 0) { msg = new DanaRS_Packet_APS_History_Events(0); @@ -190,7 +185,8 @@ public class DanaRSService extends Service { SystemClock.sleep(100); } lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded; - return true; + log.debug("Events loaded"); + return new PumpEnactResult().success(true); } @@ -232,7 +228,7 @@ public class DanaRSService extends Service { } } - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); bolusingEvent.t = t; bolusingEvent.percent = 99; @@ -257,14 +253,16 @@ public class DanaRSService extends Service { MainApp.bus().post(bolusingEvent); SystemClock.sleep(1000); } - if (!(isConnected())) - DanaRSPlugin.getPlugin().connect("loadEvents"); - loadEvents(); - // reread bolus status - MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); - bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus - bolusingEvent.percent = 100; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.disconnecting))); + ConfigBuilderPlugin.getCommandQueue().loadEvents(new Callback() { + @Override + public void run() { + // reread bolus status + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); + bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus + bolusingEvent.percent = 100; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.disconnecting))); + } + }); return true; } @@ -359,8 +357,9 @@ public class DanaRSService extends Service { return true; } - public boolean loadHistory(byte type) { - if (!isConnected()) return false; + public PumpEnactResult loadHistory(byte type) { + PumpEnactResult result = new PumpEnactResult(); + if (!isConnected()) return result; DanaRS_Packet_History_ msg = null; switch (type) { case RecordTypes.RECORD_TYPE_ALARM: @@ -401,7 +400,9 @@ public class DanaRSService extends Service { SystemClock.sleep(200); bleComm.sendMessage(new DanaRS_Packet_General_Set_History_Upload_Mode(0)); } - return true; + result.success = true; + result.comment = "OK"; + return result; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java index f2ad2fd659..0c3ac39860 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -38,7 +38,7 @@ import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; @@ -61,9 +61,9 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, return DanaRFragment.class.getName(); } - private boolean fragmentPumpEnabled = false; - private boolean fragmentProfileEnabled = false; - private boolean fragmentPumpVisible = false; + private static boolean fragmentPumpEnabled = false; + private static boolean fragmentProfileEnabled = false; + private static boolean fragmentPumpVisible = true; private static DanaRv2ExecutionService sExecutionService; @@ -186,11 +186,11 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PluginBase.PROFILE) - this.fragmentProfileEnabled = fragmentEnabled; + fragmentProfileEnabled = fragmentEnabled; else if (type == PluginBase.PUMP) - this.fragmentPumpEnabled = fragmentEnabled; + fragmentPumpEnabled = fragmentEnabled; // if pump profile was enabled need to switch to another too - if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) { + if (type == PluginBase.PUMP && !fragmentEnabled && fragmentProfileEnabled) { setFragmentEnabled(PluginBase.PROFILE, false); setFragmentVisible(PluginBase.PROFILE, false); NSProfilePlugin.getPlugin().setFragmentEnabled(PluginBase.PROFILE, true); @@ -201,7 +201,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, @Override public void setFragmentVisible(int type, boolean fragmentVisible) { if (type == PluginBase.PUMP) - this.fragmentPumpVisible = fragmentVisible; + fragmentPumpVisible = fragmentVisible; } @Override @@ -216,7 +216,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, @Override public boolean isInitialized() { - return pump.lastConnection.getTime() > 0; + return pump.lastConnection.getTime() > 0 && pump.maxBasal > 0; } @Override @@ -232,27 +232,35 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, // Pump interface @Override - public int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -281,13 +289,6 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, return pump.lastConnection; } - @Override - public void refreshDataFromPump(String reason) { - if (!isConnected() && !isConnecting()) { - doConnect(reason); - } - } - @Override public double getBaseBasalRate() { return pump.currentBasal; @@ -360,9 +361,10 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min - if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - doConnect("setTempBasalAbsolute old data"); - } + //This should not be needed while using queue because connection should be done before calling this + //if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { + // connect("setTempBasalAbsolute old data"); + //} PumpEnactResult result = new PumpEnactResult(); @@ -397,7 +399,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, if (percentRate > 500) // Special high temp 500/15min percentRate = 500; // Check if some temp is already in progress - if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { // Correct basal already set ? if (MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()).percentRate == percentRate) { if (!enforceNew) { @@ -514,6 +516,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, // needs to be rounded int durationInHalfHours = Math.max(durationInMinutes / 30, 1); insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); + PumpEnactResult result = new PumpEnactResult(); ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) { @@ -597,7 +600,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, } } - public static void doConnect(String from) { + @Override + public void connect(String from) { if (sExecutionService != null) { sExecutionService.connect(from); pumpDescription.basalStep = pump.basalStep; @@ -605,18 +609,31 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return sExecutionService != null && sExecutionService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return sExecutionService != null && sExecutionService.isConnecting(); } - public static void doDisconnect(String from) { + @Override + public void disconnect(String from) { if (sExecutionService != null) sExecutionService.disconnect(from); } + @Override + public void stopConnecting() { + if (sExecutionService != null) sExecutionService.stopConnecting(); + } + + @Override + public void getPumpStatus() { + if (sExecutionService != null) sExecutionService.getPumpStatus(); + } + @Override public JSONObject getJSONStatus() { if (pump.lastConnection.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { @@ -680,10 +697,15 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, */ @Override - public boolean loadHistory(byte type) { + public PumpEnactResult loadHistory(byte type) { return sExecutionService.loadHistory(type); } + @Override + public PumpEnactResult loadEvents() { + return sExecutionService.loadEvents(); + } + /** * Constraint interface */ @@ -787,7 +809,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, if (pump.lastBolusTime.getTime() != 0) { ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; } - if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { ret += "Temp: " + MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n"; } if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { @@ -801,7 +823,6 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; } - // TODO: daily total constraint } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java index d7b37a4b0f..9869ef0895 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java @@ -3,17 +3,21 @@ package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Date; + import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; -import info.nightscout.utils.ToastUtils; /** * Created by mike on 30.06.2016. @@ -36,14 +40,32 @@ public class MsgCheckValue_v2 extends MessageBase { pump.protocol = intFromBuff(bytes, 1, 1); pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.EXPORT_MODEL) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - DanaRv2Plugin.doDisconnect("Wrong Model"); - log.debug("Wrong model selected"); + Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.sResources.getString(R.string.pumpdrivercorrected), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + MainApp.getSpecificPlugin(DanaRPlugin.class).disconnect("Wrong Model"); + log.debug("Wrong model selected. Switching to Korean DanaR"); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false); + DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized + + //If profile coming from pump, switch it as well + if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){ + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + } + + MainApp.getConfigBuilder().storeSettings(); + MainApp.bus().post(new EventRefreshGui()); + ConfigBuilderPlugin.getCommandQueue().readStatus("PumpDriverChange", null); // force new connection + return; } if (pump.protocol != 2) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - DanaRKoreanPlugin.doDisconnect("Wrong Model"); + Notification notification = new Notification(Notification.WRONG_DRIVER, MainApp.sResources.getString(R.string.pumpdrivercorrected), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to non APS DanaR"); (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PUMP, false); (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentVisible(PluginBase.PUMP, false); @@ -57,7 +79,8 @@ public class MsgCheckValue_v2 extends MessageBase { } MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshOverview("MsgCheckValue_v2")); + MainApp.bus().post(new EventRefreshGui()); + ConfigBuilderPlugin.getCommandQueue().readStatus("PumpDriverChange", null); // force new connection return; } if (Config.logDanaMessageDetail) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java index 6eabb668fb..664ff3743a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -10,7 +10,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.IBinder; -import android.os.PowerManager; import android.os.SystemClock; import com.squareup.otto.Subscribe; @@ -27,14 +26,15 @@ 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.PumpEnactResult; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -48,6 +48,7 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetHistoryEntry_v2 import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgCheckValue_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusBolusExtended_v2; import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusTempBasal_v2; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; @@ -61,14 +62,12 @@ public class DanaRv2ExecutionService extends Service { private BluetoothSocket mRfcommSocket; private BluetoothDevice mBTDevice; - private PowerManager.WakeLock mWakeLock; private IBinder mBinder = new LocalBinder(); private DanaRPump danaRPump; private Treatment bolusingTreatment = null; private static Boolean connectionInProgress = false; - private static final Object connectionLock = new Object(); private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); @@ -95,9 +94,6 @@ public class DanaRv2ExecutionService extends Service { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); danaRPump = DanaRPump.getInstance(); - - PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRv2ExecutionService"); } public class LocalBinder extends Binder { @@ -159,35 +155,28 @@ public class DanaRv2ExecutionService extends Service { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } - while (isConnected() || isConnecting()) { - if (Config.logDanaBTComm) - log.debug("already connected/connecting from: " + from); - waitMsec(3000); - } - final long maxConnectionTime = 5 * 60 * 1000L; // 5 min - synchronized (connectionLock) { - //log.debug("entering connection while loop"); - connectionInProgress = true; - mWakeLock.acquire(); - getBTSocketForSelectedPump(); - if (mRfcommSocket == null || mBTDevice == null) - return; // Device not found - long startTime = System.currentTimeMillis(); - while (!isConnected() && startTime + maxConnectionTime >= System.currentTimeMillis()) { - long secondsElapsed = (System.currentTimeMillis() - startTime) / 1000L; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); - if (Config.logDanaBTComm) - log.debug("connect waiting " + secondsElapsed + "sec from: " + from); + + if (connectionInProgress) + return; + + new Thread(new Runnable() { + @Override + public void run() { + connectionInProgress = true; + getBTSocketForSelectedPump(); + if (mRfcommSocket == null || mBTDevice == null) { + connectionInProgress = false; + return; // Device not found + } + try { mRfcommSocket.connect(); } catch (IOException e) { //log.error("Unhandled exception", e); if (e.getMessage().contains("socket closed")) { log.error("Unhandled exception", e); - break; } } - waitMsec(1000); if (isConnected()) { if (mSerialIOThread != null) { @@ -195,23 +184,16 @@ public class DanaRv2ExecutionService extends Service { } mSerialIOThread = new SerialIOThread(mRfcommSocket); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); - if (!getPumpStatus()) { - mSerialIOThread.disconnect("getPumpStatus failed"); - waitMsec(3000); - if (!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP)) - return; - getBTSocketForSelectedPump(); - startTime = System.currentTimeMillis(); - } } + + connectionInProgress = false; } - if (!isConnected()) { - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); - log.error("Pump connection timed out"); - } - connectionInProgress = false; - mWakeLock.release(); - } + }).start(); + } + + public void stopConnecting() { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("stopConnecting"); } private void getBTSocketForSelectedPump() { @@ -246,7 +228,7 @@ public class DanaRv2ExecutionService extends Service { mSerialIOThread.disconnect("EventPreferenceChange"); } - private boolean getPumpStatus() { + public void getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); MsgStatus statusMsg = new MsgStatus(); @@ -258,7 +240,7 @@ public class DanaRv2ExecutionService extends Service { if (danaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { - return false; + return; } } @@ -270,28 +252,6 @@ public class DanaRv2ExecutionService extends Service { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus))); mSerialIOThread.sendMessage(exStatusMsg); - if (!statusMsg.received) { - mSerialIOThread.sendMessage(statusMsg); - } - if (!statusBasicMsg.received) { - mSerialIOThread.sendMessage(statusBasicMsg); - } - if (!tempStatusMsg.received) { - // Load of status of current basal rate failed, give one more try - mSerialIOThread.sendMessage(tempStatusMsg); - } - if (!exStatusMsg.received) { - // Load of status of current extended bolus failed, give one more try - mSerialIOThread.sendMessage(exStatusMsg); - } - - // Check we have really current status of pump - if (!statusMsg.received || !statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) { - waitMsec(10 * 1000); - log.debug("getPumpStatus failed"); - return false; - } - Date now = new Date(); if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings))); @@ -333,11 +293,10 @@ public class DanaRv2ExecutionService extends Service { } catch (Exception e) { log.error("Unhandled exception", e); } - return true; + return; } public boolean tempBasal(int percent, int durationInHours) { - connect("tempBasal"); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); @@ -353,7 +312,6 @@ public class DanaRv2ExecutionService extends Service { } public boolean highTempBasal(int percent) { - connect("highTempBasal"); if (!isConnected()) return false; if (danaRPump.isTempBasalInProgress) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); @@ -369,7 +327,6 @@ public class DanaRv2ExecutionService extends Service { } public boolean tempBasalStop() { - connect("tempBasalStop"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); @@ -380,7 +337,6 @@ public class DanaRv2ExecutionService extends Service { } public boolean extendedBolus(double insulin, int durationInHalfHours) { - connect("extendedBolus"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); @@ -391,7 +347,6 @@ public class DanaRv2ExecutionService extends Service { } public boolean extendedBolusStop() { - connect("extendedBolusStop"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingextendedbolus))); mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); @@ -401,7 +356,7 @@ public class DanaRv2ExecutionService extends Service { return true; } - public boolean bolus(final double amount, int carbs, long carbtime, Treatment t) { + public boolean bolus(final double amount, int carbs, long carbtime, final Treatment t) { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.startingbolus))); bolusingTreatment = t; final int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0); @@ -412,7 +367,6 @@ public class DanaRv2ExecutionService extends Service { start = new MsgBolusStartWithSpeed(amount, preferencesSpeed); MsgBolusStop stop = new MsgBolusStop(amount, t); - connect("bolus"); if (!isConnected()) return false; if (carbs > 0) { @@ -435,7 +389,7 @@ public class DanaRv2ExecutionService extends Service { } while (!stop.stopped && !start.failed) { waitMsec(100); - if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + if ((System.currentTimeMillis() - progress.lastReceive) > 15 * 1000L) { // if i didn't receive status for more than 15 sec expecting broken comm stop.stopped = true; stop.forced = true; log.debug("Communication stopped"); @@ -443,7 +397,7 @@ public class DanaRv2ExecutionService extends Service { } } - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); bolusingEvent.t = t; bolusingEvent.percent = 99; @@ -468,16 +422,18 @@ public class DanaRv2ExecutionService extends Service { MainApp.bus().post(bolusingEvent); SystemClock.sleep(1000); } - if (!(isConnected())) - connect("loadEvents"); - loadEvents(); - // load last bolus status - MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); - mSerialIOThread.sendMessage(new MsgStatus()); - bolusingEvent.percent = 100; - MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.disconnecting))); + ConfigBuilderPlugin.getCommandQueue().loadEvents(new Callback() { + @Override + public void run() { + // load last bolus status + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus))); + mSerialIOThread.sendMessage(new MsgStatus()); + bolusingEvent.percent = 100; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.disconnecting))); + } + }); return true; -} + } public void bolusStop() { if (Config.logDanaBTComm) @@ -496,7 +452,6 @@ public class DanaRv2ExecutionService extends Service { } public boolean carbsEntry(int amount, long time) { - connect("carbsEntry"); if (!isConnected()) return false; MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount); mSerialIOThread.sendMessage(msg); @@ -506,9 +461,9 @@ public class DanaRv2ExecutionService extends Service { return true; } - public boolean loadHistory(byte type) { - connect("loadHistory"); - if (!isConnected()) return false; + public PumpEnactResult loadHistory(byte type) { + PumpEnactResult result = new PumpEnactResult(); + if (!isConnected()) return result; MessageBase msg = null; switch (type) { case RecordTypes.RECORD_TYPE_ALARM: @@ -548,11 +503,14 @@ public class DanaRv2ExecutionService extends Service { } waitMsec(200); mSerialIOThread.sendMessage(new MsgPCCommStop()); - return true; + result.success = true; + result.comment = "OK"; + return result; } - public boolean loadEvents() { - if (!isConnected()) return false; + public PumpEnactResult loadEvents() { + if (!isConnected()) + return new PumpEnactResult().success(false); waitMsec(300); MsgHistoryEvents_v2 msg; if (lastHistoryFetched == 0) { @@ -568,11 +526,10 @@ public class DanaRv2ExecutionService extends Service { } waitMsec(200); lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded; - return true; + return new PumpEnactResult().success(true); } public boolean updateBasalsInPump(final Profile profile) { - connect("updateBasalsInPump"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); double[] basal = DanaRPump.buildDanaRProfileRecord(profile); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java index da4ea8157d..fd5d2bd270 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java @@ -130,9 +130,37 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public int setNewBasalProfile(Profile profile) { + public boolean isConnected() { + return true; + } + + @Override + public boolean isConnecting() { + return false; + } + + @Override + public void connect(String reason) { + } + + @Override + public void disconnect(String reason) { + } + + @Override + public void stopConnecting() { + } + + @Override + public void getPumpStatus() { + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); - return SUCCESS; + PumpEnactResult result = new PumpEnactResult(); + result.success = true; + return result; } @Override @@ -145,11 +173,6 @@ public class MDIPlugin implements PluginBase, PumpInterface { return new Date(); } - @Override - public void refreshDataFromPump(String reason) { - // do nothing - } - @Override public double getBaseBasalRate() { return 0d; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java index 3590af80fe..ebaf2b19dd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java @@ -52,7 +52,7 @@ public class VirtualPumpFragment extends SubscriberFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { try { - View view = inflater.inflate(R.layout.vitualpump_fragment, container, false); + View view = inflater.inflate(R.layout.virtualpump_fragment, container, false); basaBasalRateView = (TextView) view.findViewById(R.id.virtualpump_basabasalrate); tempBasalView = (TextView) view.findViewById(R.id.virtualpump_tempbasal); extendedBolusView = (TextView) view.findViewById(R.id.virtualpump_extendedbolus); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 2e3be7ab95..4853847e5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -185,10 +185,41 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } @Override - public int setNewBasalProfile(Profile profile) { - // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); + public boolean isConnected() { + return true; + } + + @Override + public boolean isConnecting() { + return false; + } + + @Override + public void connect(String reason) { + if (!BuildConfig.NSCLIENTOLNY) + NSUpload.uploadDeviceStatus(); lastDataTime = new Date(); - return SUCCESS; + } + + @Override + public void disconnect(String reason) { + } + + @Override + public void stopConnecting() { + } + + @Override + public void getPumpStatus() { + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { + lastDataTime = new Date(); + // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); + PumpEnactResult result = new PumpEnactResult(); + result.success = true; + return result; } @Override @@ -201,13 +232,6 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { return lastDataTime; } - @Override - public void refreshDataFromPump(String reason) { - if (!BuildConfig.NSCLIENTOLNY) - NSUpload.uploadDeviceStatus(); - lastDataTime = new Date(); - } - @Override public double getBaseBasalRate() { Profile profile = MainApp.getConfigBuilder().getProfile(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java index 110e0f4a56..e035ea3aba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.PumpVirtual.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventVirtualPumpUpdateGui { +public class EventVirtualPumpUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index 9fdb0152d0..b7b9d879b1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -25,22 +25,21 @@ import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; @@ -225,7 +224,7 @@ public class SmsCommunicatorPlugin implements PluginBase { } } - private void processSms(Sms receivedSms) { + private void processSms(final Sms receivedSms) { if (!isEnabled(PluginBase.GENERAL)) { log.debug("Ignoring SMS. Plugin disabled."); return; @@ -287,11 +286,15 @@ public class SmsCommunicatorPlugin implements PluginBase { LoopPlugin loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) { loopPlugin.setFragmentEnabled(PluginBase.LOOP, false); - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); - MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_STOP")); - reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled) + " " + - MainApp.sResources.getString(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { + @Override + public void run() { + MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_STOP")); + String reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled) + " " + + MainApp.sResources.getString(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + }); } receivedSms.processed = true; Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Stop")); @@ -435,7 +438,7 @@ public class SmsCommunicatorPlugin implements PluginBase { if (System.currentTimeMillis() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) { reply = MainApp.sResources.getString(R.string.smscommunicator_remotebolusnotallowed); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else if (MainApp.getConfigBuilder().isSuspended()) { + } else if (ConfigBuilderPlugin.getActivePump().isSuspended()) { reply = MainApp.sResources.getString(R.string.pumpsuspended); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } else if (splited.length > 1) { @@ -476,64 +479,61 @@ public class SmsCommunicatorPlugin implements PluginBase { if (bolusWaitingForConfirmation != null && !bolusWaitingForConfirmation.processed && bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - bolusWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { bolusWaitingForConfirmation.processed = true; - PumpInterface pumpInterface = MainApp.getConfigBuilder(); - if (pumpInterface != null) { - danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = bolusWaitingForConfirmation.bolusRequested; - detailedBolusInfo.source = Source.USER; - PumpEnactResult result = pumpInterface.deliverTreatment(detailedBolusInfo); - if (result.success) { - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered); - if (danaRPlugin != null) - reply += "\n" + danaRPlugin.shortStatus(true); - lastRemoteBolusTime = new Date(); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_bolusfailed); - if (danaRPlugin != null) - reply += "\n" + danaRPlugin.shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = bolusWaitingForConfirmation.bolusRequested; + detailedBolusInfo.source = Source.USER; + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { + @Override + public void run() { + DanaRPlugin danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); + if (result.success) { + String reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered); + if (danaRPlugin != null) + reply += "\n" + danaRPlugin.shortStatus(true); + lastRemoteBolusTime = new Date(); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else { + String reply = MainApp.sResources.getString(R.string.smscommunicator_bolusfailed); + if (danaRPlugin != null) + reply += "\n" + danaRPlugin.shortStatus(true); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } } - } + }); } else if (tempBasalWaitingForConfirmation != null && !tempBasalWaitingForConfirmation.processed && tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - tempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { tempBasalWaitingForConfirmation.processed = true; - PumpInterface pumpInterface = MainApp.getConfigBuilder(); - if (pumpInterface != null) { - danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, true); - if (result.success) { - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); - if (danaRPlugin != null) - reply += "\n" + danaRPlugin.shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed); - if (danaRPlugin != null) - reply += "\n" + danaRPlugin.shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + ConfigBuilderPlugin.getCommandQueue().tempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, true, new Callback() { + @Override + public void run() { + if (result.success) { + String reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else { + String reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } } - } + }); } else if (cancelTempBasalWaitingForConfirmation != null && !cancelTempBasalWaitingForConfirmation.processed && cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - cancelTempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { cancelTempBasalWaitingForConfirmation.processed = true; - PumpInterface pumpInterface = MainApp.getConfigBuilder(); - if (pumpInterface != null) { - danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.cancelTempBasal(true); - if (result.success) { - reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled); - if (danaRPlugin != null) - reply += "\n" + danaRPlugin.shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcancelfailed); - if (danaRPlugin != null) - reply += "\n" + danaRPlugin.shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { + @Override + public void run() { + if (result.success) { + String reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else { + String reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcancelfailed); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } } - } + }); } else if (calibrationWaitingForConfirmation != null && !calibrationWaitingForConfirmation.processed && calibrationWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - calibrationWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { calibrationWaitingForConfirmation.processed = true; @@ -548,14 +548,24 @@ public class SmsCommunicatorPlugin implements PluginBase { } else if (suspendWaitingForConfirmation != null && !suspendWaitingForConfirmation.processed && suspendWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - suspendWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { suspendWaitingForConfirmation.processed = true; - final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000); - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); - NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); - MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); - reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " + - MainApp.sResources.getString(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() { + @Override + public void run() { + if (result.success) { + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); + activeloop.suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000); + NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); + MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); + String reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " + + MainApp.sResources.getString(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else { + String reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcancelfailed); + reply += "\n" + ConfigBuilderPlugin.getActivePump().shortStatus(true); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + } + }); } else { sendSMS(new Sms(receivedSms.phoneNumber, MainApp.sResources.getString(R.string.smscommunicator_unknowncommand), new Date())); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java index 2b890fb59c..dfaebb3942 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java @@ -2,10 +2,12 @@ package info.nightscout.androidaps.plugins.SmsCommunicator.events; import android.os.Bundle; +import info.nightscout.androidaps.events.Event; + /** * Created by mike on 13.07.2016. */ -public class EventNewSMS { +public class EventNewSMS extends Event { public Bundle bundle; public EventNewSMS(Bundle bundle) { this.bundle = bundle; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java index 7c1d480e72..02956a5d67 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventSmsCommunicatorUpdateGui.java @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.SmsCommunicator.events; +import info.nightscout.androidaps.events.EventUpdateGui; + /** * Created by mike on 05.08.2016. */ -public class EventSmsCommunicatorUpdateGui { +public class EventSmsCommunicatorUpdateGui extends EventUpdateGui { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java index 2c0372bd2d..6fcbcfe951 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java @@ -9,19 +9,23 @@ import android.view.ViewGroup; import android.widget.TextView; import com.crashlytics.android.Crashlytics; +import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventExtendedBolusChange; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment; import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTemporaryBasalsFragment; -public class TreatmentsFragment extends Fragment implements View.OnClickListener { +public class TreatmentsFragment extends SubscriberFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(TreatmentsFragment.class); TextView treatmentsTab; @@ -102,4 +106,19 @@ public class TreatmentsFragment extends Fragment implements View.OnClickListener profileSwitchTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); selected.setBackgroundColor(MainApp.sResources.getColor(R.color.tabBgColorSelected)); } + + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + updateGUI(); + } + + @Override + protected void updateGUI() { + if (ConfigBuilderPlugin.getActivePump().getPumpDescription().isExtendedBolusCapable + || MainApp.getConfigBuilder().getExtendedBolusesFromHistory().size() > 0) { + extendedBolusesTab.setVisibility(View.VISIBLE); + } else { + extendedBolusesTab.setVisibility(View.GONE); + } + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java index d7c9d1eafe..6466591a87 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java @@ -15,10 +15,10 @@ 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.Intervals; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.data.Intervals; import info.nightscout.androidaps.data.NonOverlappingIntervals; import info.nightscout.androidaps.data.OverlappingIntervals; import info.nightscout.androidaps.data.Profile; @@ -33,8 +33,8 @@ import info.nightscout.androidaps.events.EventReloadTempBasalData; import info.nightscout.androidaps.events.EventReloadTreatmentData; import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.utils.SP; @@ -200,8 +200,8 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { if (!t.isSMB) { // instead of dividing the DIA that only worked on the bilinear curves, // multiply the time the treatment is seen active. - long timeSinceTreatment = time - t.date; - long snoozeTime = t.date + (long)(timeSinceTreatment * SP.getDouble("openapsama_bolussnooze_dia_divisor", 2.0)); + long timeSinceTreatment = time - t.date; + long snoozeTime = t.date + (long) (timeSinceTreatment * SP.getDouble("openapsama_bolussnooze_dia_divisor", 2.0)); Iob bIOB = t.iobCalc(snoozeTime, dia); total.bolussnooze += bIOB.iobContrib; } else { @@ -210,7 +210,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { } } - if (!MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) + if (!ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) synchronized (extendedBoluses) { for (Integer pos = 0; pos < extendedBoluses.size(); pos++) { ExtendedBolus e = extendedBoluses.get(pos); @@ -329,7 +329,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { total.plus(calc); } } - if (MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { + if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) { IobTotal totalExt = new IobTotal(time); synchronized (extendedBoluses) { for (Integer pos = 0; pos < extendedBoluses.size(); pos++) { @@ -361,7 +361,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { if (tb != null) return tb; ExtendedBolus eb = getExtendedBolusFromHistory(time); - if (eb != null && MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) + if (eb != null && ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) return new TemporaryBasal(eb); return null; } @@ -384,18 +384,16 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { @Override public double getTempBasalAbsoluteRateHistory() { - PumpInterface pump = MainApp.getConfigBuilder(); - TemporaryBasal tb = getTempBasalFromHistory(System.currentTimeMillis()); if (tb != null) { - if (tb.isFakeExtended){ - double baseRate = pump.getBaseBasalRate(); + if (tb.isFakeExtended) { + double baseRate = ConfigBuilderPlugin.getActivePump().getBaseBasalRate(); double tempRate = baseRate + tb.netExtendedRate; return tempRate; } else if (tb.isAbsolute) { return tb.absoluteRate; } else { - double baseRate = pump.getBaseBasalRate(); + double baseRate = ConfigBuilderPlugin.getActivePump().getBaseBasalRate(); double tempRate = baseRate * (tb.percentRate / 100d); return tempRate; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java index a7b90775f1..6511cedbdf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java @@ -13,13 +13,12 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; -import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.db.DatabaseHelper; @@ -33,15 +32,16 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.queue.Callback; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -173,8 +173,8 @@ public class ActionStringHandler { } else if ("loop".equals(act[1])) { rTitle += " LOOP"; rMessage = "TARGETS:\n" + getTargetsStatus(); - rMessage += "\n\n" + getLoopStatus(); - rMessage += "\n\nOAPS RESULT:\n" + getOAPSResultStatus(); + rMessage += "\n\n" + getLoopStatus(); + rMessage += "\n\nOAPS RESULT:\n" + getOAPSResultStatus(); } } else if ("wizard".equals(act[0])) { @@ -236,15 +236,15 @@ public class ActionStringHandler { rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulingFromBolusIOB) + "U"; if (useBasalIOB) rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulingFromBasalsIOB) + "U"; - if(percentage != 100){ - rMessage += "\nPercentage: " +format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"; + if (percentage != 100) { + rMessage += "\nPercentage: " + format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"; } lastBolusWizard = bolusWizard; - } else if("opencpp".equals(act[0])){ + } else if ("opencpp".equals(act[0])) { ProfileSwitch activeProfileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); - if(activeProfileSwitch==null){ + if (activeProfileSwitch == null) { sendError("No active profile switch!"); return; } else { @@ -254,30 +254,30 @@ public class ActionStringHandler { rAction = "opencpp" + " " + activeProfileSwitch.percentage + " " + activeProfileSwitch.timeshift; } - } else if("cppset".equals(act[0])){ + } else if ("cppset".equals(act[0])) { ProfileSwitch activeProfileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis()); - if(activeProfileSwitch==null){ + if (activeProfileSwitch == null) { sendError("No active profile switch!"); return; } else { // read CPP values - rMessage = "CPP:" + "\n\n"+ - "Timeshift: " + act[1] + "\n" + - "Percentage: " + act[2] + "%"; + rMessage = "CPP:" + "\n\n" + + "Timeshift: " + act[1] + "\n" + + "Percentage: " + act[2] + "%"; rAction = actionstring; } - } else if("tddstats".equals(act[0])){ + } else if ("tddstats".equals(act[0])) { Object activePump = MainApp.getConfigBuilder().getActivePump(); PumpInterface dana = MainApp.getSpecificPlugin(DanaRPlugin.class); PumpInterface danaV2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class); PumpInterface danaKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); - if((dana == null || dana != activePump) && + if ((dana == null || dana != activePump) && (danaV2 == null || danaV2 != activePump) && (danaKorean == null || danaKorean != activePump) - ){ + ) { sendError("Pump does not support TDDs!"); return; } else { @@ -285,7 +285,7 @@ public class ActionStringHandler { List dummies = new LinkedList(); List historyList = getTDDList(dummies); - if(isOldData(historyList)){ + if (isOldData(historyList)) { rTitle = "TDD"; rAction = "statusmessage"; rMessage = "OLD DATA - "; @@ -300,10 +300,10 @@ public class ActionStringHandler { handler.post(new Runnable() { @Override public void run() { - ((DanaRInterface)pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY); + ((DanaRInterface) pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY); List dummies = new LinkedList(); List historyList = getTDDList(dummies); - if(isOldData(historyList)){ + if (isOldData(historyList)) { sendStatusmessage("TDD", "TDD: Still old data! Cannot load from pump."); } else { sendStatusmessage("TDD", generateTDDMessage(historyList, dummies)); @@ -319,8 +319,7 @@ public class ActionStringHandler { } } - } - else return; + } else return; // send result @@ -333,14 +332,14 @@ public class ActionStringHandler { ProfileInterface activeProfile = MainApp.getConfigBuilder().getActiveProfileInterface(); - if(activeProfile == null){ + if (activeProfile == null) { return "No profile loaded :("; } DateFormat df = new SimpleDateFormat("dd.MM."); String message = ""; - double refTDD = activeProfile.getProfile().getDefaultProfile().baseBasalSum()*2; + double refTDD = activeProfile.getProfile().getDefaultProfile().baseBasalSum() * 2; int i = 0; double sum = 0d; @@ -364,15 +363,15 @@ public class ActionStringHandler { i++; } message += "weighted:\n"; - message += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (DecimalFormatter.to0Decimal(100*weighted03/refTDD) + "%") + "\n"; - message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (DecimalFormatter.to0Decimal(100*weighted05/refTDD) + "%") + "\n"; - message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (DecimalFormatter.to0Decimal(100*weighted07/refTDD) + "%") + "\n"; + message += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (DecimalFormatter.to0Decimal(100 * weighted03 / refTDD) + "%") + "\n"; + message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (DecimalFormatter.to0Decimal(100 * weighted05 / refTDD) + "%") + "\n"; + message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (DecimalFormatter.to0Decimal(100 * weighted07 / refTDD) + "%") + "\n"; message += "\n"; PumpInterface pump = MainApp.getConfigBuilder().getActivePump(); if (pump != null && pump instanceof DanaRPlugin) { double tdd = DanaRPump.getInstance().dailyTotalUnits; - message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%") + "\n"; + message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n"; message += "\n"; } @@ -380,7 +379,7 @@ public class ActionStringHandler { Collections.reverse(historyList); for (DanaRHistoryRecord record : historyList) { double tdd = record.recordDailyBolus + record.recordDailyBasal; - message += df.format(new Date(record.recordDate)) + " " + DecimalFormatter.to2Decimal(tdd) +"U " + (DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%") + (dummies.contains(record)?"x":"") +"\n"; + message += df.format(new Date(record.recordDate)) + " " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + (dummies.contains(record) ? "x" : "") + "\n"; } return message; } @@ -398,17 +397,17 @@ public class ActionStringHandler { historyList = historyList.subList(0, Math.min(10, historyList.size())); //fill single gaps - List dummies = (returnDummies!=null)?returnDummies:(new LinkedList()); + List dummies = (returnDummies != null) ? returnDummies : (new LinkedList()); DateFormat df = new SimpleDateFormat("dd.MM."); - for(int i = 0; i < historyList.size()-1; i++){ + for (int i = 0; i < historyList.size() - 1; i++) { DanaRHistoryRecord elem1 = historyList.get(i); - DanaRHistoryRecord elem2 = historyList.get(i+1); + DanaRHistoryRecord elem2 = historyList.get(i + 1); - if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25*60*60*1000)))){ + if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25 * 60 * 60 * 1000)))) { DanaRHistoryRecord dummy = new DanaRHistoryRecord(); - dummy.recordDate = elem1.recordDate - 24*60*60*1000; - dummy.recordDailyBasal = elem1.recordDailyBasal/2; - dummy.recordDailyBolus = elem1.recordDailyBolus/2; + dummy.recordDate = elem1.recordDate - 24 * 60 * 60 * 1000; + dummy.recordDailyBasal = elem1.recordDailyBasal / 2; + dummy.recordDailyBolus = elem1.recordDailyBolus / 2; dummies.add(dummy); elem1.recordDailyBasal /= 2; elem1.recordDailyBolus /= 2; @@ -418,7 +417,7 @@ public class ActionStringHandler { Collections.sort(historyList, new Comparator() { @Override public int compare(DanaRHistoryRecord lhs, DanaRHistoryRecord rhs) { - return (int) (rhs.recordDate-lhs.recordDate); + return (int) (rhs.recordDate - lhs.recordDate); } }); return historyList; @@ -426,7 +425,7 @@ public class ActionStringHandler { @NonNull private static String getPumpStatus() { - return MainApp.getConfigBuilder().shortStatus(false); + return ConfigBuilderPlugin.getActivePump().shortStatus(false); } @NonNull @@ -505,12 +504,12 @@ public class ActionStringHandler { } if (!result.changeRequested) { - ret += MainApp.sResources.getString(R.string.nochangerequested) + "\n"; + ret += MainApp.sResources.getString(R.string.nochangerequested) + "\n"; } else if (result.rate == 0 && result.duration == 0) { - ret += MainApp.sResources.getString(R.string.canceltemp)+ "\n"; + ret += MainApp.sResources.getString(R.string.canceltemp) + "\n"; } else { ret += MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(result.rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(result.rate / MainApp.getConfigBuilder().getBaseBasalRate() * 100) + "%)\n" + + "(" + DecimalFormatter.to2Decimal(result.rate / ConfigBuilderPlugin.getActivePump().getBaseBasalRate() * 100) + "%)\n" + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(result.duration) + " min\n"; } ret += "\n" + MainApp.sResources.getString(R.string.reason) + ": " + result.reason; @@ -565,7 +564,7 @@ public class ActionStringHandler { int timeshift = SafeParse.stringToInt(act[1]); int percentage = SafeParse.stringToInt(act[2]); setCPP(timeshift, percentage); - } else if ("dismissoverviewnotification".equals(act[0])){ + } else if ("dismissoverviewnotification".equals(act[0])) { MainApp.bus().post(new EventDismissNotification(SafeParse.stringToInt(act[1]))); } lastBolusWizard = null; @@ -578,21 +577,20 @@ public class ActionStringHandler { //check for validity if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { - msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n"; + msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n"; } if (timeshift < 0 || timeshift > 23) { - msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n"; + msg += String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n"; } - if(!SP.getBoolean("syncprofiletopump", false)){ - msg+= MainApp.sResources.getString(R.string.syncprofiletopump_title) + " " + MainApp.sResources.getString(R.string.cpp_sync_setting_missing) + "\n"; + if (!SP.getBoolean("syncprofiletopump", false)) { + msg += MainApp.sResources.getString(R.string.syncprofiletopump_title) + " " + MainApp.sResources.getString(R.string.cpp_sync_setting_missing) + "\n"; } - final PumpInterface pump = MainApp.getConfigBuilder(); final Profile profile = MainApp.getConfigBuilder().getProfile(); - if (pump == null || profile == null || profile.getBasal() == null){ - msg+= MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n"; + if (profile == null || profile.getBasal() == null) { + msg += MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n"; } - if(!"".equals(msg)) { + if (!"".equals(msg)) { msg += MainApp.sResources.getString(R.string.cpp_valuesnotstored); String rTitle = "STATUS"; String rAction = "statusmessage"; @@ -627,16 +625,13 @@ public class ActionStringHandler { } private static void doFillBolus(final Double amount) { - //if(1==1)return; - Handler handler = new Handler(handlerThread.getLooper()); - handler.post(new Runnable() { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = amount; + detailedBolusInfo.isValid = false; + detailedBolusInfo.source = Source.USER; + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { @Override public void run() { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = amount; - detailedBolusInfo.isValid = false; - detailedBolusInfo.source = Source.USER; - PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(detailedBolusInfo); if (!result.success) { sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + "\n" + @@ -647,16 +642,13 @@ public class ActionStringHandler { } private static void doBolus(final Double amount, final Integer carbs) { - //if(1==1)return; - Handler handler = new Handler(handlerThread.getLooper()); - handler.post(new Runnable() { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = amount; + detailedBolusInfo.carbs = carbs; + detailedBolusInfo.source = Source.USER; + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { @Override public void run() { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = amount; - detailedBolusInfo.carbs = carbs; - detailedBolusInfo.source = Source.USER; - PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(detailedBolusInfo); if (!result.success) { sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + "\n" + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java index 85bce9658e..f787d00512 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java @@ -35,10 +35,10 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; @@ -192,8 +192,7 @@ public class WatchUpdaterService extends WearableListenerService implements } private void cancelBolus() { - PumpInterface pump = MainApp.getConfigBuilder(); - pump.stopBolusDelivering(); + ConfigBuilderPlugin.getActivePump().stopBolusDelivering(); } private void sendData() { @@ -572,7 +571,7 @@ public class WatchUpdaterService extends WearableListenerService implements private void sendPreferences() { if (googleApiClient.isConnected()) { - boolean wearcontrol = SP.getBoolean("wearcontrol",false); + boolean wearcontrol = SP.getBoolean("wearcontrol", false); PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH); //unique content diff --git a/app/src/main/java/info/nightscout/androidaps/queue/Callback.java b/app/src/main/java/info/nightscout/androidaps/queue/Callback.java new file mode 100644 index 0000000000..8ea5132290 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/Callback.java @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; + +/** + * Created by mike on 09.11.2017. + */ +public abstract class Callback implements Runnable { + public PumpEnactResult result; + + public Callback result(PumpEnactResult result) { + this.result = result; + return this; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java new file mode 100644 index 0000000000..2b085007e3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -0,0 +1,409 @@ +package info.nightscout.androidaps.queue; + +import android.content.Intent; +import android.support.v7.app.AppCompatActivity; +import android.text.Html; +import android.text.Spanned; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.events.EventBolusRequested; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.queue.commands.Command; +import info.nightscout.androidaps.queue.commands.CommandBolus; +import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus; +import info.nightscout.androidaps.queue.commands.CommandCancelTempBasal; +import info.nightscout.androidaps.queue.commands.CommandExtendedBolus; +import info.nightscout.androidaps.queue.commands.CommandLoadEvents; +import info.nightscout.androidaps.queue.commands.CommandLoadHistory; +import info.nightscout.androidaps.queue.commands.CommandReadStatus; +import info.nightscout.androidaps.queue.commands.CommandSetProfile; +import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute; +import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent; + +/** + * Created by mike on 08.11.2017. + * + * DATA FLOW: + * --------- + * + * (request) - > ConfigBuilder.getCommandQueue().bolus(...) + * + * app no longer waits for result but passes Callback + * + * request is added to queue, if another request of the same type already exists in queue, it's removed prior adding + * but if request of the same type is currently executed (probably important only for bolus which is running long time), new request is declined + * new QueueThread is created and started if current if finished + * CommandReadStatus is added automatically before command if queue is empty + * + * biggest change is we don't need exec pump commands in Handler because it's finished immediately + * command queueing if not realized by stacking in different Handlers and threads anymore but by internal queue with better control + * + * QueueThread calls ConfigBuilder#connect which is passed to getActivePump().connect + * connect should be executed on background and return immediately. afterwards isConnecting() is expected to be true + * + * while isConnecting() == true GUI is updated by posting connection progress + * + * if connect is successful: isConnected() becomes true, isConnecting() becomes false + * CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish). + * callback with result is called after finish automatically + * if connect failed: isConnected() becomes false, isConnecting() becomes false + * connect() is called again + * + * when queue is empty, disconnect is called + * + */ + +public class CommandQueue { + private static Logger log = LoggerFactory.getLogger(CommandQueue.class); + + private LinkedList queue = new LinkedList<>(); + private Command performing; + + private QueueThread thread = null; + + private PumpEnactResult executingNowError() { + PumpEnactResult result = new PumpEnactResult(); + result.success = false; + result.enacted = false; + result.comment = MainApp.sResources.getString(R.string.executingrightnow); + return result; + } + + public boolean isRunning(Command.CommandType type) { + if (performing != null && performing.commandType == type) + return true; + return false; + } + + private synchronized void removeAll(Command.CommandType type) { + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i).commandType == type) { + queue.remove(i); + } + } + } + + private synchronized void add(Command command) { + // inject reading of status when adding first command to the queue + if (queue.size() == 0 && command.commandType != Command.CommandType.READSTATUS) + queue.add(new CommandReadStatus("Queue", null)); + queue.add(command); + } + + synchronized void pickup() { + performing = queue.poll(); + } + + synchronized void clear() { + performing = null; + for (int i = 0; i < queue.size(); i++) { + queue.get(i).cancel(); + } + + queue.clear(); + } + + public int size() { + return queue.size(); + } + + public Command performing() { + return performing; + } + + public void resetPerforming() { + performing = null; + } + + // After new command added to the queue + // start thread again if not already running + private void notifyAboutNewCommand() { + if (thread == null || thread.getState() == Thread.State.TERMINATED) { + thread = new QueueThread(this); + thread.start(); + } + } + + // returns true if command is queued + public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { + if (isRunning(Command.CommandType.BOLUS)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluses + removeAll(Command.CommandType.BOLUS); + + // add new command to queue + add(new CommandBolus(detailedBolusInfo, callback)); + + notifyAboutNewCommand(); + + // Notify Wear about upcoming bolus + MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); + + // Bring up bolus progress dialog + detailedBolusInfo.insulin = MainApp.getConfigBuilder().applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.carbs = MainApp.getConfigBuilder().applyCarbsConstraints((int) detailedBolusInfo.carbs); + + BolusProgressDialog bolusProgressDialog = null; + if (detailedBolusInfo.context != null) { + bolusProgressDialog = new BolusProgressDialog(); + bolusProgressDialog.setInsulin(detailedBolusInfo.insulin); + bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress"); + } else { + Intent i = new Intent(); + i.putExtra("insulin", detailedBolusInfo.insulin); + i.setClass(MainApp.instance(), BolusProgressHelperActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + + return true; + } + + // returns true if command is queued + public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) { + if (isRunning(Command.CommandType.TEMPBASAL)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.TEMPBASAL); + + Double rateAfterConstraints = MainApp.getConfigBuilder().applyBasalConstraints(absoluteRate); + + // add new command to queue + add(new CommandTempBasalAbsolute(rateAfterConstraints, durationInMinutes, enforceNew, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean tempBasalPercent(int percent, int durationInMinutes, Callback callback) { + if (isRunning(Command.CommandType.TEMPBASAL)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.TEMPBASAL); + + Integer percentAfterConstraints = MainApp.getConfigBuilder().applyBasalConstraints(percent); + + // add new command to queue + add(new CommandTempBasalPercent(percentAfterConstraints, durationInMinutes, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean extendedBolus(double insulin, int durationInMinutes, Callback callback) { + if (isRunning(Command.CommandType.EXTENDEDBOLUS)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + Double rateAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); + + // remove all unfinished + removeAll(Command.CommandType.EXTENDEDBOLUS); + + // add new command to queue + add(new CommandExtendedBolus(rateAfterConstraints, durationInMinutes, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean cancelTempBasal(boolean enforceNew, Callback callback) { + if (isRunning(Command.CommandType.TEMPBASAL)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.TEMPBASAL); + + // add new command to queue + add(new CommandCancelTempBasal(enforceNew, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean cancelExtended(Callback callback) { + if (isRunning(Command.CommandType.EXTENDEDBOLUS)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.EXTENDEDBOLUS); + + // add new command to queue + add(new CommandCancelExtendedBolus(callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean setProfile(Profile profile, Callback callback) { + if (isRunning(Command.CommandType.BASALPROFILE)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // Compare with pump limits + Profile.BasalValue[] basalValues = profile.getBasalValues(); + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + + for (int index = 0; index < basalValues.length; index++) { + if (basalValues[index].value < pump.getPumpDescription().basalMinimumRate) { + Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.sResources.getString(R.string.basalvaluebelowminimum), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + if (callback != null) + callback.result(new PumpEnactResult().success(false).comment(MainApp.sResources.getString(R.string.basalvaluebelowminimum))).run(); + return false; + } + } + + MainApp.bus().post(new EventDismissNotification(Notification.BASAL_VALUE_BELOW_MINIMUM)); + + if (isThisProfileSet(profile)) { + log.debug("Correct profile already set"); + if (callback != null) + callback.result(new PumpEnactResult().success(true).enacted(false)).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.BASALPROFILE); + + // add new command to queue + add(new CommandSetProfile(profile, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean readStatus(String reason, Callback callback) { + if (isRunning(Command.CommandType.READSTATUS)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.READSTATUS); + + // add new command to queue + add(new CommandReadStatus(reason, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean loadHistory(byte type, Callback callback) { + if (isRunning(Command.CommandType.LOADHISTORY)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.LOADHISTORY); + + // add new command to queue + add(new CommandLoadHistory(type, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean loadEvents(Callback callback) { + if (isRunning(Command.CommandType.LOADEVENTS)) { + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished + removeAll(Command.CommandType.LOADEVENTS); + + // add new command to queue + add(new CommandLoadEvents(callback)); + + notifyAboutNewCommand(); + + return true; + } + + public Spanned spannedStatus() { + String s = ""; + int line = 0; + if (performing != null) { + s += "" + performing.status() + ""; + line++; + } + for (int i = 0; i < queue.size(); i++) { + if (line != 0) + s += "
"; + s += queue.get(i).status(); + line++; + } + return Html.fromHtml(s); + } + + public boolean isThisProfileSet(Profile profile) { + PumpInterface activePump = ConfigBuilderPlugin.getActivePump(); + if (activePump != null) { + boolean result = activePump.isThisProfileSet(profile); + if (!result) { + log.debug("Current profile: " + MainApp.getConfigBuilder().getProfile().getData().toString()); + log.debug("New profile: " + profile.getData().toString()); + } + return result; + } else return true; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java new file mode 100644 index 0000000000..36b43d2181 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -0,0 +1,104 @@ +package info.nightscout.androidaps.queue; + +import android.content.Context; +import android.os.PowerManager; +import android.os.SystemClock; + +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.PumpEnactResult; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; +import info.nightscout.androidaps.queue.events.EventQueueChanged; + +/** + * Created by mike on 09.11.2017. + */ + +public class QueueThread extends Thread { + private static Logger log = LoggerFactory.getLogger(QueueThread.class); + + CommandQueue queue; + + private long connectionStartTime = 0; + + private PowerManager.WakeLock mWakeLock; + + public QueueThread(CommandQueue queue) { + super(QueueThread.class.toString()); + + this.queue = queue; + PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "QueueThread"); + } + + @Override + public final void run() { + mWakeLock.acquire(); + MainApp.bus().post(new EventQueueChanged()); + connectionStartTime = System.currentTimeMillis(); + + try { + while (true) { + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + log.debug("Looping ..."); + long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; + if (pump.isConnecting()) { + log.debug("State: connecting"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + SystemClock.sleep(1000); + continue; + } + + if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) { + log.debug("State: timed out"); + MainApp.bus().post(new EventDismissBolusprogressIfRunning(new PumpEnactResult())); + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.connectiontimedout))); + pump.stopConnecting(); + queue.clear(); + return; + } + + if (!pump.isConnected()) { + log.debug("State: connect"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + pump.connect("Connection needed"); + SystemClock.sleep(1000); + continue; + } + + if (queue.performing() == null) { + // Pickup 1st command and set performing variable + if (queue.size() > 0) { + log.debug("State: performing"); + queue.pickup(); + MainApp.bus().post(new EventQueueChanged()); + queue.performing().execute(); + queue.resetPerforming(); + MainApp.bus().post(new EventQueueChanged()); + SystemClock.sleep(100); + continue; + } + } + + if (queue.size() == 0 && queue.performing() == null) { + log.debug("State: queue empty. disconnect"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + pump.disconnect("Queue empty"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + return; + } + } + } finally { + mWakeLock.release(); + } + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java new file mode 100644 index 0000000000..4624e2385f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ +public abstract class Command { + public enum CommandType { + BOLUS, + TEMPBASAL, + EXTENDEDBOLUS, + BASALPROFILE, + READSTATUS, + LOADHISTORY, // so far only Dana specific + LOADEVENTS // so far only Dana specific + } + + public CommandType commandType; + protected Callback callback; + + public abstract void execute(); + + public abstract String status(); + + public void cancel() { + PumpEnactResult result = new PumpEnactResult(); + result.success = false; + result.comment = MainApp.sResources.getString(R.string.connectiontimedout); + if (callback != null) + callback.result(result).run(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java new file mode 100644 index 0000000000..278fd7681b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandBolus.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.utils.DecimalFormatter; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandBolus extends Command { + DetailedBolusInfo detailedBolusInfo; + + public CommandBolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { + commandType = CommandType.BOLUS; + this.detailedBolusInfo = detailedBolusInfo; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().deliverTreatment(detailedBolusInfo); + + BolusProgressDialog.bolusEnded = true; + MainApp.bus().post(new EventDismissBolusprogressIfRunning(r)); + + if (callback != null) + callback.result(r).run(); + } + + public String status() { + return "BOLUS " + DecimalFormatter.to1Decimal(detailedBolusInfo.insulin) + "U"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java new file mode 100644 index 0000000000..536c2d876c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelExtendedBolus.java @@ -0,0 +1,37 @@ +package info.nightscout.androidaps.queue.commands; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandCancelExtendedBolus extends Command { + private static Logger log = LoggerFactory.getLogger(CommandCancelExtendedBolus.class); + + public CommandCancelExtendedBolus(Callback callback) { + commandType = CommandType.EXTENDEDBOLUS; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().cancelExtendedBolus(); + if (Config.logCongigBuilderActions) + log.debug("cancelExtendedBolus success: " + r.success + " enacted: " + r.enacted); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "CANCEL EXTENDEDBOLUS"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java new file mode 100644 index 0000000000..d2496c871a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandCancelTempBasal.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandCancelTempBasal extends Command { + boolean enforceNew; + + public CommandCancelTempBasal(boolean enforceNew, Callback callback) { + commandType = CommandType.TEMPBASAL; + this.enforceNew = enforceNew; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().cancelTempBasal(enforceNew); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "CANCEL TEMPBASAL"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java new file mode 100644 index 0000000000..0641d9139d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandExtendedBolus.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.queue.commands; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandExtendedBolus extends Command { + private static Logger log = LoggerFactory.getLogger(CommandExtendedBolus.class); + + private double insulin; + private int durationInMinutes; + + public CommandExtendedBolus(double insulin, int durationInMinutes, Callback callback) { + commandType = CommandType.EXTENDEDBOLUS; + this.insulin = insulin; + this.durationInMinutes = durationInMinutes; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setExtendedBolus(insulin, durationInMinutes); + if (Config.logCongigBuilderActions) + log.debug("setExtendedBolus rate: " + insulin + " durationInMinutes: " + durationInMinutes + " success: " + r.success + " enacted: " + r.enacted); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "EXTENDEDBOLUS " + insulin + " U " + durationInMinutes + " min"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java new file mode 100644 index 0000000000..2d6bc5b5fc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadEvents.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.DanaRInterface; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 10.11.2017. + */ + +public class CommandLoadEvents extends Command { + public CommandLoadEvents(Callback callback) { + commandType = CommandType.LOADEVENTS; + this.callback = callback; + } + + @Override + public void execute() { + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + if (pump instanceof DanaRInterface) { + DanaRInterface danaPump = (DanaRInterface) pump; + PumpEnactResult r = danaPump.loadEvents(); + if (callback != null) + callback.result(r).run(); + } + } + + @Override + public String status() { + return "LOADEVENTS"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java new file mode 100644 index 0000000000..16e9a18048 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandLoadHistory.java @@ -0,0 +1,38 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.DanaRInterface; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.androidaps.queue.commands.Command; + +/** + * Created by mike on 10.11.2017. + */ + +public class CommandLoadHistory extends Command { + byte type; + + public CommandLoadHistory(byte type, Callback callback) { + commandType = CommandType.LOADHISTORY; + this.type = type; + this.callback = callback; + } + + @Override + public void execute() { + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + if (pump instanceof DanaRInterface) { + DanaRInterface danaPump = (DanaRInterface) pump; + PumpEnactResult r = danaPump.loadHistory(type); + if (callback != null) + callback.result(r).run(); + } + } + + @Override + public String status() { + return "LOADHISTORY " + type; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java new file mode 100644 index 0000000000..d573cc44be --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandReadStatus extends Command { + String reason; + + public CommandReadStatus(String reason, Callback callback) { + commandType = CommandType.READSTATUS; + this.reason = reason; + this.callback = callback; + } + + @Override + public void execute() { + ConfigBuilderPlugin.getActivePump().getPumpStatus(); + if (callback != null) + callback.result(null).run(); + } + + @Override + public String status() { + return "READSTATUS"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java new file mode 100644 index 0000000000..fe236fa55f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.queue.commands; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandSetProfile extends Command { + Profile profile; + + public CommandSetProfile(Profile profile, Callback callback) { + commandType = CommandType.BASALPROFILE; + this.profile = profile; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setNewBasalProfile(profile); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "SETPROFILE"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java new file mode 100644 index 0000000000..28dc728174 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalAbsolute.java @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.queue.commands; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandTempBasalAbsolute extends Command { + private static Logger log = LoggerFactory.getLogger(CommandTempBasalAbsolute.class); + + int durationInMinutes; + double absoluteRate; + boolean enforceNew; + + public CommandTempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) { + commandType = CommandType.TEMPBASAL; + this.absoluteRate = absoluteRate; + this.durationInMinutes = durationInMinutes; + this.enforceNew = enforceNew; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalAbsolute(absoluteRate, durationInMinutes, enforceNew); + if (Config.logCongigBuilderActions) + log.debug("setTempBasalAbsolute rate: " + absoluteRate + " durationInMinutes: " + durationInMinutes + " success: " + r.success + " enacted: " + r.enacted); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "TEMPBASAL " + absoluteRate + " U/h " + durationInMinutes + " min"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java new file mode 100644 index 0000000000..663a20380d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandTempBasalPercent.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.queue.commands; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.queue.Callback; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandTempBasalPercent extends Command { + private static Logger log = LoggerFactory.getLogger(CommandTempBasalPercent.class); + + int durationInMinutes; + int percent; + + public CommandTempBasalPercent(int percent, int durationInMinutes, Callback callback) { + commandType = CommandType.TEMPBASAL; + this.percent = percent; + this.durationInMinutes = durationInMinutes; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalPercent(percent, durationInMinutes); + if (Config.logCongigBuilderActions) + log.debug("setTempBasalPercent percent: " + percent + " durationInMinutes: " + durationInMinutes + " success: " + r.success + " enacted: " + r.enacted); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "TEMPBASAL " + percent + "% " + durationInMinutes + " min"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.java b/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.java new file mode 100644 index 0000000000..b0a53afd13 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/events/EventQueueChanged.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.queue.events; + +/** + * Created by mike on 11.11.2017. + */ + +public class EventQueueChanged { +} diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java index e3c77d0122..828f2c5bed 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java @@ -9,9 +9,7 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.os.PowerManager; -import android.preference.PreferenceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,11 +18,31 @@ import java.util.Date; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.utils.SP; public class KeepAliveReceiver extends BroadcastReceiver { private static Logger log = LoggerFactory.getLogger(KeepAliveReceiver.class); + public static final long STATUS_UPDATE_FREQUENCY = 15 * 60 * 1000L; + + // TODO consider moving this into an Alarms plugin that works offline and can be configured + // (e.g. override silent mode at night only) + + private static int missedReadingsThreshold() { + return SP.getInt(MainApp.sResources.getString(R.string.key_missed_bg_readings_threshold), 30) * 60 * 1000; + } + + private static int pumpUnreachableThreshold() { + return SP.getInt(MainApp.sResources.getString(R.string.key_pump_unreachable_threshold), 30) * 60 * 1000; + } + @Override public void onReceive(Context context, Intent rIntent) { @@ -32,52 +50,61 @@ public class KeepAliveReceiver extends BroadcastReceiver { PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, ""); wl.acquire(); - - final PumpInterface pump = MainApp.getConfigBuilder(); - final Profile profile = MainApp.getConfigBuilder().getProfile(); - if (pump != null && profile != null && profile.getBasal() != null) { - boolean isBasalOutdated = false; - boolean isStatusOutdated = false; - - Date lastConnection = pump.lastDataTime(); - if (lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) - isStatusOutdated = true; - if (Math.abs(profile.getBasal() - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep) - isBasalOutdated = true; - - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - if (SP.getBoolean("syncprofiletopump", false) && !pump.isThisProfileSet(profile)) { - Thread t = new Thread(new Runnable() { - @Override - public void run() { - pump.setNewBasalProfile(profile); - } - }); - t.start(); - } else if (isStatusOutdated && !pump.isBusy()) { - Thread t = new Thread(new Runnable() { - @Override - public void run() { - pump.refreshDataFromPump("KeepAlive. Status outdated."); - } - }); - t.start(); - } else if (isBasalOutdated && !pump.isBusy()) { - Thread t = new Thread(new Runnable() { - @Override - public void run() { - pump.refreshDataFromPump("KeepAlive. Basal outdated."); - } - }); - t.start(); - } - } + shortenSnoozeInterval(); + checkBg(); + checkPump(); log.debug("KeepAlive received"); wl.release(); } + private void checkBg() { + BgReading bgReading = DatabaseHelper.lastBg(); + if (SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_missed_bg_readings_alert), false) + && bgReading != null && bgReading.date + missedReadingsThreshold() < System.currentTimeMillis() + && SP.getLong("nextMissedReadingsAlarm", 0l) < System.currentTimeMillis()) { + Notification n = new Notification(Notification.BG_READINGS_MISSED, MainApp.sResources.getString(R.string.missed_bg_readings), Notification.URGENT); + n.soundId = R.raw.alarm; + SP.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + missedReadingsThreshold()); + MainApp.bus().post(new EventNewNotification(n)); + } + } + + private void checkPump() { + final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + final Profile profile = MainApp.getConfigBuilder().getProfile(); + if (pump != null && profile != null && profile.getBasal() != null) { + Date lastConnection = pump.lastDataTime(); + boolean isStatusOutdated = lastConnection.getTime() + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis(); + boolean isBasalOutdated = Math.abs(profile.getBasal() - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep; + + boolean alarmTimeoutExpired = lastConnection.getTime() + pumpUnreachableThreshold() < System.currentTimeMillis(); + boolean nextAlarmOccurrenceReached = SP.getLong("nextPumpDisconnectedAlarm", 0l) < System.currentTimeMillis(); + + if (SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_pump_unreachable_alert), true) + && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !ConfigBuilderPlugin.getActiveLoop().isDisconnected()) { + Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.sResources.getString(R.string.pump_unreachable), Notification.URGENT); + n.soundId = R.raw.alarm; + SP.putLong("nextPumpDisconnectedAlarm", System.currentTimeMillis() + pumpUnreachableThreshold()); + MainApp.bus().post(new EventNewNotification(n)); + } + + if (SP.getBoolean("syncprofiletopump", false) && !pump.isThisProfileSet(profile)) { + MainApp.getConfigBuilder().getCommandQueue().setProfile(profile, null); + } else if (isStatusOutdated && !pump.isBusy()) { + MainApp.getConfigBuilder().getCommandQueue().readStatus("KeepAlive. Status outdated.", null); + } else if (isBasalOutdated && !pump.isBusy()) { + MainApp.getConfigBuilder().getCommandQueue().readStatus("KeepAlive. Basal outdated.", null); + } + } + } + + //called by MainApp at first app start public void setAlarm(Context context) { + + shortenSnoozeInterval(); + presnoozeAlarms(); + AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent i = new Intent(context, KeepAliveReceiver.class); PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0); @@ -89,10 +116,33 @@ public class KeepAliveReceiver extends BroadcastReceiver { am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), Constants.keepAliveMsecs, pi); } + /*Presnoozes the alarms with 5 minutes if no snooze exists. + * Call only at startup! + */ + public void presnoozeAlarms() { + if (SP.getLong("nextMissedReadingsAlarm", 0l) < System.currentTimeMillis()) { + SP.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + 5 * 60 * 1000); + } + if (SP.getLong("nextPumpDisconnectedAlarm", 0l) < System.currentTimeMillis()) { + SP.putLong("nextPumpDisconnectedAlarm", System.currentTimeMillis() + 5 * 60 * 1000); + } + } + public void cancelAlarm(Context context) { Intent intent = new Intent(context, KeepAliveReceiver.class); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(sender); } + + static void shortenSnoozeInterval() { + //shortens alarm times in case of setting changes or future data + long nextMissedReadingsAlarm = SP.getLong("nextMissedReadingsAlarm", 0L); + nextMissedReadingsAlarm = Math.min(System.currentTimeMillis() + missedReadingsThreshold(), nextMissedReadingsAlarm); + SP.putLong("nextMissedReadingsAlarm", nextMissedReadingsAlarm); + + long nextPumpDisconnectedAlarm = SP.getLong("nextPumpDisconnectedAlarm", 0L); + nextPumpDisconnectedAlarm = Math.min(System.currentTimeMillis() + pumpUnreachableThreshold(), nextPumpDisconnectedAlarm); + SP.putLong("nextPumpDisconnectedAlarm", nextPumpDisconnectedAlarm); + } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java index c4a9fa89b7..95bb5e17b3 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java @@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSAlarm; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; diff --git a/app/src/main/java/info/nightscout/utils/BolusWizard.java b/app/src/main/java/info/nightscout/utils/BolusWizard.java index ec5c0ec02b..a97ed233ff 100644 --- a/app/src/main/java/info/nightscout/utils/BolusWizard.java +++ b/app/src/main/java/info/nightscout/utils/BolusWizard.java @@ -6,6 +6,7 @@ import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; /** * Created by mike on 11.10.2016. @@ -124,7 +125,7 @@ public class BolusWizard { calculatedTotalInsulin = 0d; } - double bolusStep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; + double bolusStep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep; calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep); return calculatedTotalInsulin; diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/utils/DateUtil.java index 3e32557adb..d2f35e0c99 100644 --- a/app/src/main/java/info/nightscout/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/utils/DateUtil.java @@ -27,8 +27,8 @@ public class DateUtil { /** * The date format in iso. */ - private static String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ss'Z'"; - private static String FORMAT_DATE_ISO_MSEC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + private static String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ssZ"; + private static String FORMAT_DATE_ISO_MSEC = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; /** * Takes in an ISO date string of the following format: @@ -146,4 +146,20 @@ public class DateUtil { } -} \ No newline at end of file + public static String timeFrameString(long timeInMillis){ + long remainingTimeMinutes = timeInMillis/(1000*60); + long remainingTimeHours = remainingTimeMinutes/60; + remainingTimeMinutes = remainingTimeMinutes%60; + return "(" + ((remainingTimeHours >0)?(remainingTimeHours + "h "):"") + remainingTimeMinutes + "')"; + } + + public static String sinceString(long timestamp){ + return timeFrameString(System.currentTimeMillis()-timestamp); + } + + public static String untilString(long timestamp){ + return timeFrameString(timestamp- System.currentTimeMillis()); + } + + +} diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index 98ce8632ff..215bd732e7 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -23,6 +23,7 @@ import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.DeviceStatus; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; @@ -220,7 +221,7 @@ public class NSUpload { log.debug("OpenAPS data too old to upload"); } deviceStatus.device = "openaps://" + Build.MANUFACTURER + " " + Build.MODEL; - JSONObject pumpstatus = MainApp.getConfigBuilder().getJSONStatus(); + JSONObject pumpstatus = ConfigBuilderPlugin.getActivePump().getJSONStatus(); if (pumpstatus != null) { deviceStatus.pump = pumpstatus; } @@ -404,4 +405,23 @@ public class NSUpload { DbLogger.dbAdd(intent, data.toString()); } } + + public static void removeFoodFromNS(String _id) { + try { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbRemove"); + bundle.putString("collection", "food"); + bundle.putString("_id", _id); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbRemove(intent, _id); + } catch (Exception e) { + log.error("Unhandled exception", e); + } + + } + } diff --git a/app/src/main/java/info/nightscout/utils/ToastUtils.java b/app/src/main/java/info/nightscout/utils/ToastUtils.java index 4e1e4ac4ed..4ad07a4885 100644 --- a/app/src/main/java/info/nightscout/utils/ToastUtils.java +++ b/app/src/main/java/info/nightscout/utils/ToastUtils.java @@ -7,7 +7,7 @@ import android.os.Looper; import android.widget.Toast; import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; diff --git a/app/src/main/res/layout/danar_fragment.xml b/app/src/main/res/layout/danar_fragment.xml index 29c9398a04..ac48032690 100644 --- a/app/src/main/res/layout/danar_fragment.xml +++ b/app/src/main/res/layout/danar_fragment.xml @@ -124,6 +124,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/food_item.xml b/app/src/main/res/layout/food_item.xml new file mode 100644 index 0000000000..d4efc403a3 --- /dev/null +++ b/app/src/main/res/layout/food_item.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/overview_error_dialog.xml b/app/src/main/res/layout/overview_error_dialog.xml new file mode 100644 index 0000000000..e32007ad68 --- /dev/null +++ b/app/src/main/res/layout/overview_error_dialog.xml @@ -0,0 +1,24 @@ + + + + +