diff --git a/app/build.gradle b/app/build.gradle
index 77d1bde228..fe4517d78e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -44,12 +44,12 @@ def generateGitBuild = { ->
stringBuilder.append('NoGitSystemAvailable')
}
stringBuilder.append('-')
- stringBuilder.append((new Date()).format('yyyy.MM.dd'))
+ stringBuilder.append((new Date()).format('yyyy.MM.dd-HH:mm'))
stringBuilder.append('"')
return stringBuilder.toString()
}
-tasks.matching {it instanceof Test}.all {
+tasks.matching { it instanceof Test }.all {
testLogging.events = ["failed", "skipped", "started"]
testLogging.exceptionFormat = "full"
}
@@ -63,7 +63,7 @@ android {
targetSdkVersion 25
multiDexEnabled true
versionCode 1500
- version "1.60e-dev"
+ version "2.0a-dev"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -89,7 +89,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
- testCoverageEnabled (project.hasProperty('coverage') ? true : false)
+ testCoverageEnabled(project.hasProperty('coverage') ? true : false)
}
}
productFlavors {
@@ -99,7 +99,8 @@ android {
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
- appIcon: "@mipmap/blueowl"
+ appIcon: "@mipmap/ic_launcher",
+ appIconRound: "@mipmap/ic_launcher_round"
]
buildConfigField "boolean", "APS", "true"
buildConfigField "boolean", "PUMPDRIVERS", "true"
@@ -112,7 +113,8 @@ android {
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
- appIcon: "@mipmap/blueowl"
+ appIcon: "@mipmap/blueowl",
+ appIconRound: "@null"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "true"
@@ -125,7 +127,8 @@ android {
resValue "string", "app_name", "NSClient"
versionName version + "-nsclient"
manifestPlaceholders = [
- appIcon: "@mipmap/yellowowl"
+ appIcon: "@mipmap/yellowowl",
+ appIconRound: "@null"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
@@ -138,7 +141,8 @@ android {
resValue "string", "app_name", "NSClient"
versionName version + "-nsclient"
manifestPlaceholders = [
- appIcon: "@mipmap/yellowowl"
+ appIcon: "@mipmap/yellowowl",
+ appIconRound: "@null"
]
buildConfigField "boolean", "APS", "false"
buildConfigField "boolean", "PUMPDRIVERS", "false"
@@ -156,7 +160,7 @@ android {
unitTests.returnDefaultValues = true
unitTests.includeAndroidResources = true
}
- }
+}
allprojects {
repositories {
@@ -242,7 +246,7 @@ dependencies {
}
task unzip(type: Copy) {
- def zipPath = configurations.libs.find {it.name.startsWith("danars") }
+ def zipPath = configurations.libs.find { it.name.startsWith("danars") }
def zipFile = file(zipPath)
def outputDir = file("${buildDir}/unpacked/dist")
diff --git a/app/libs/sightparser-release.aar b/app/libs/sightparser-release.aar
index 302b9e836d..1f0c16ee34 100644
Binary files a/app/libs/sightparser-release.aar and b/app/libs/sightparser-release.aar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ca4bff0dd5..bcc1e93abd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -30,13 +30,13 @@
android:name=".MainApp"
android:allowBackup="true"
android:icon="${appIcon}"
+ android:roundIcon="${appIconRound}"
android:label="@string/app_name"
android:supportsRtl="true"
- android:theme="@style/AppTheme">
+ android:theme="@style/AppTheme.NoActionBar">
-
@@ -49,16 +49,19 @@
android:theme="@style/Theme.AppCompat.Translucent" />
+
+
+
@@ -70,6 +73,7 @@
android:enabled="true"
android:exported="true">
+
@@ -80,6 +84,8 @@
+
+
@@ -140,7 +146,7 @@
+ android:exported="true" />
@@ -158,12 +164,22 @@
android:exported="true" />
+ android:exported="false" />
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/OpenAPSSMB/determine-basal.js b/app/src/main/assets/OpenAPSSMB/determine-basal.js
index 84bd684cf6..c2db0f270b 100644
--- a/app/src/main/assets/OpenAPSSMB/determine-basal.js
+++ b/app/src/main/assets/OpenAPSSMB/determine-basal.js
@@ -406,8 +406,8 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
} else {
console.error("SMB disabled (no enableSMB preferences active)");
}
- // enable UAM (if enabled in preferences) if SMB is enabled
- var enableUAM=(profile.enableUAM && enableSMB);
+ // enable UAM (if enabled in preferences)
+ var enableUAM=(profile.enableUAM);
//console.error(meal_data);
@@ -942,10 +942,10 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
var durationReq = round(60*worstCaseInsulinReq / profile.current_basal);
if (durationReq < 0) {
durationReq = 0;
- // don't set a temp longer than 120 minutes
+ // don't set an SMB zero temp longer than 60 minutess
} else {
durationReq = round(durationReq/30)*30;
- durationReq = Math.min(120,Math.max(0,durationReq));
+ durationReq = Math.min(60,Math.max(0,durationReq));
}
//console.error(durationReq);
//rT.reason += "insulinReq " + insulinReq + "; "
diff --git a/app/src/main/assets/logback.xml b/app/src/main/assets/logback.xml
index d6facdb7dd..a09a312301 100644
--- a/app/src/main/assets/logback.xml
+++ b/app/src/main/assets/logback.xml
@@ -1,36 +1,39 @@
-
-
-
- ${EXT_FILES_DIR}/AndroidAPS.log
-
+
+
+
+ ${EXT_FILES_DIR}/AndroidAPS.log
+
- ${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip
+ ${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip
+
-
+ 5MB120
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level [%class:%line]: %msg%n
-
-
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level [%class{0}.%M\(\):%line]: %msg%n
+
+
-
- %logger{0}
-
-
- [%thread] %-5level [%class:%line]: %msg%n
-
-
-
-
-
-
-
-
+
+ %logger{0}
+
+
+ [%thread] [%class{0}.%M\(\):%line]: %msg%n
+
+
+
+
+
+
+
+
diff --git a/app/src/main/blueowl-web.png b/app/src/main/blueowl-web.png
new file mode 100644
index 0000000000..22339763e2
Binary files /dev/null and b/app/src/main/blueowl-web.png differ
diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png
new file mode 100644
index 0000000000..22339763e2
Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ
diff --git a/app/src/main/ic_launcher_round-web.png b/app/src/main/ic_launcher_round-web.png
new file mode 100644
index 0000000000..22339763e2
Binary files /dev/null and b/app/src/main/ic_launcher_round-web.png differ
diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java
index 56fd2b6de9..a66d4e77f1 100644
--- a/app/src/main/java/info/nightscout/androidaps/Constants.java
+++ b/app/src/main/java/info/nightscout/androidaps/Constants.java
@@ -12,7 +12,7 @@ public class Constants {
public static final double MMOLL_TO_MGDL = 18; // 18.0182;
public static final double MGDL_TO_MMOLL = 1 / MMOLL_TO_MGDL;
- public static final double defaultDIA = 3d;
+ public static final double defaultDIA = 5d;
public static final Double REALLYHIGHBASALRATE = 1111111d;
public static final Integer REALLYHIGHPERCENTBASALRATE = 1111111;
diff --git a/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java b/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java
index c308cd2efe..636db14086 100644
--- a/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/HistoryBrowseActivity.java
@@ -176,13 +176,19 @@ public class HistoryBrowseActivity extends AppCompatActivity {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- updateGUI("EventAutosensCalculationFinished");
+ synchronized (HistoryBrowseActivity.this) {
+ updateGUI("EventAutosensCalculationFinished");
+ }
}
});
}
}
void updateGUI(String from) {
+
+ if (noProfile == null || buttonDate == null || buttonZoom == null || bgGraph == null || iobGraph == null || seekBar == null)
+ return;
+
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
final Profile profile = MainApp.getConfigBuilder().getProfile();
diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
index 9a80c61904..8a19a05f4d 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
@@ -1,35 +1,34 @@
package info.nightscout.androidaps;
-import android.Manifest;
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.os.PowerManager;
-import android.provider.Settings;
+import android.support.annotation.Nullable;
+import android.support.design.widget.NavigationView;
+import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.PopupMenu;
+import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
-import android.view.MenuInflater;
+import android.util.TypedValue;
+import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
-import android.widget.ImageButton;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.joanzapata.iconify.Iconify;
@@ -47,67 +46,128 @@ import info.nightscout.androidaps.events.EventRefreshGui;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin;
-import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
-import info.nightscout.androidaps.tabs.SlidingTabLayout;
+import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.TabPageAdapter;
+import info.nightscout.utils.AndroidPermission;
import info.nightscout.utils.ImportExportPrefs;
import info.nightscout.utils.LocaleHelper;
import info.nightscout.utils.LogDialog;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.PasswordProtection;
import info.nightscout.utils.SP;
-import info.nightscout.utils.ToastUtils;
-public class MainActivity extends AppCompatActivity implements View.OnClickListener {
+public class MainActivity extends AppCompatActivity {
private static Logger log = LoggerFactory.getLogger(MainActivity.class);
- static final int CASE_STORAGE = 0x1;
- static final int CASE_SMS = 0x2;
- static final int CASE_LOCATION = 0x3;
-
- private boolean askForSMS = false;
- private boolean askForLocation = true;
-
- ImageButton menuButton;
-
protected PowerManager.WakeLock mWakeLock;
+ private ActionBarDrawerToggle actionBarDrawerToggle;
+
+ private MenuItem pluginPreferencesMenuItem;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Iconify.with(new FontAwesomeModule());
- LocaleHelper.onCreate(this, "en");
- setContentView(R.layout.activity_main);
- menuButton = (ImageButton) findViewById(R.id.overview_menuButton);
- menuButton.setOnClickListener(this);
- checkEula();
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
- askForPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE);
- }
- askForBatteryOptimizationPermission();
- doMigrations();
if (Config.logFunctionCalls)
log.debug("onCreate");
- onStatusEvent(new EventSetWakeLock(SP.getBoolean("lockscreen", false)));
+ Iconify.with(new FontAwesomeModule());
+ LocaleHelper.onCreate(this, "en");
+
+ setContentView(R.layout.activity_main);
+ setSupportActionBar(findViewById(R.id.toolbar));
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeButtonEnabled(true);
+
+ DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
+ actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.open_navigation, R.string.close_navigation);
+ drawerLayout.addDrawerListener(actionBarDrawerToggle);
+ actionBarDrawerToggle.syncState();
+
+ // initialize screen wake lock
+ onEventPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
+
+ doMigrations();
registerBus();
- setUpTabs(false);
+ setupTabs();
+ setupViews(false);
+
+ final ViewPager viewPager = findViewById(R.id.pager);
+ viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ checkPluginPreferences(viewPager);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+ });
+ }
+
+ private void checkPluginPreferences(ViewPager viewPager) {
+ if (pluginPreferencesMenuItem == null) return;
+ if (((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem()).getPreferencesId() != -1)
+ pluginPreferencesMenuItem.setEnabled(true);
+ else pluginPreferencesMenuItem.setEnabled(false);
+ }
+
+ @Override
+ public void onPostCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
+ super.onPostCreate(savedInstanceState, persistentState);
+ actionBarDrawerToggle.syncState();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) {
+ Intent intent = new Intent(this, SetupWizardActivity.class);
+ startActivity(intent);
+ } else {
+ checkEula();
+ }
+
+ AndroidPermission.notifyForStoragePermission(this);
+ AndroidPermission.notifyForBatteryOptimizationPermission(this);
+ if (BuildConfig.APS || BuildConfig.PUMPCONTROL) {
+ AndroidPermission.notifyForLocationPermissions(this);
+ AndroidPermission.notifyForSMSPermissions(this);
+ }
+
+ MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mWakeLock != null)
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ super.onDestroy();
}
@Subscribe
- public void onStatusEvent(final EventSetWakeLock ev) {
- final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- if (ev.lock) {
- mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AAPS");
- if (!mWakeLock.isHeld())
- mWakeLock.acquire();
- } else {
- if (mWakeLock != null && mWakeLock.isHeld())
- mWakeLock.release();
+ public void onEventPreferenceChange(final EventPreferenceChange ev) {
+ if (ev.isChanged(R.string.key_keep_screen_on)) {
+ boolean keepScreenOn = SP.getBoolean(R.string.key_keep_screen_on, false);
+ final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ if (keepScreenOn) {
+ mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AAPS");
+ if (!mWakeLock.isHeld())
+ mWakeLock.acquire();
+ } else {
+ if (mWakeLock != null && mWakeLock.isHeld())
+ mWakeLock.release();
+ }
}
}
@@ -115,39 +175,75 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
public void onStatusEvent(final EventRefreshGui ev) {
String lang = SP.getString("language", "en");
LocaleHelper.setLocale(getApplicationContext(), lang);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (ev.recreate) {
- recreate();
- } else {
- try { // activity may be destroyed
- setUpTabs(true);
- } catch (IllegalStateException e) {
- log.error("Unhandled exception", e);
- }
+ runOnUiThread(() -> {
+ if (ev.recreate) {
+ recreate();
+ } else {
+ try { // activity may be destroyed
+ setupTabs();
+ setupViews(true);
+ } catch (IllegalStateException e) {
+ log.error("Unhandled exception", e);
}
-
- boolean lockScreen = BuildConfig.NSCLIENTOLNY && SP.getBoolean("lockscreen", false);
- if (lockScreen)
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- else
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
+
+ boolean keepScreenOn = BuildConfig.NSCLIENTOLNY && SP.getBoolean(R.string.key_keep_screen_on, false);
+ if (keepScreenOn)
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ else
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
});
}
- private void setUpTabs(boolean switchToLast) {
+ private void setupViews(boolean switchToLast) {
TabPageAdapter pageAdapter = new TabPageAdapter(getSupportFragmentManager(), this);
+ NavigationView navigationView = findViewById(R.id.navigation_view);
+ navigationView.setNavigationItemSelectedListener(menuItem -> {
+ return true;
+ });
+ Menu menu = navigationView.getMenu();
+ menu.clear();
for (PluginBase p : MainApp.getPluginsList()) {
pageAdapter.registerNewFragment(p);
+ if (p.hasFragment() && !p.isFragmentVisible() && p.isEnabled(p.pluginDescription.getType()) && !p.pluginDescription.neverVisible) {
+ MenuItem menuItem = menu.add(p.getName());
+ menuItem.setCheckable(true);
+ menuItem.setOnMenuItemClickListener(item -> {
+ Intent intent = new Intent(this, SingleFragmentActivity.class);
+ intent.putExtra("plugin", MainApp.getPluginsList().indexOf(p));
+ startActivity(intent);
+ ((DrawerLayout) findViewById(R.id.drawer_layout)).closeDrawers();
+ return true;
+ });
+ }
}
- ViewPager mPager = (ViewPager) findViewById(R.id.pager);
+ ViewPager mPager = findViewById(R.id.pager);
mPager.setAdapter(pageAdapter);
- SlidingTabLayout mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
- mTabs.setViewPager(mPager);
if (switchToLast)
mPager.setCurrentItem(pageAdapter.getCount() - 1, false);
+ checkPluginPreferences(mPager);
+ }
+
+ private void setupTabs() {
+ ViewPager viewPager = findViewById(R.id.pager);
+ TabLayout normalTabs = findViewById(R.id.tabs_normal);
+ normalTabs.setupWithViewPager(viewPager, true);
+ TabLayout compactTabs = findViewById(R.id.tabs_compact);
+ compactTabs.setupWithViewPager(viewPager, true);
+ Toolbar toolbar = findViewById(R.id.toolbar);
+ if (SP.getBoolean("short_tabtitles", false)) {
+ normalTabs.setVisibility(View.GONE);
+ compactTabs.setVisibility(View.VISIBLE);
+ toolbar.setLayoutParams(new LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT, (int) getResources().getDimension(R.dimen.compact_height)));
+ } else {
+ normalTabs.setVisibility(View.VISIBLE);
+ compactTabs.setVisibility(View.GONE);
+ TypedValue typedValue = new TypedValue();
+ if (getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
+ toolbar.setLayoutParams(new LinearLayout.LayoutParams(Toolbar.LayoutParams.MATCH_PARENT,
+ TypedValue.complexToDimensionPixelSize(typedValue.data, getResources().getDisplayMetrics())));
+ }
+ }
}
private void registerBus() {
@@ -205,120 +301,22 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
}
}
- //check for sms permission if enable in prefernces
- @Subscribe
- public void onStatusEvent(final EventPreferenceChange ev) {
- if (ev.isChanged(R.string.key_smscommunicator_remotecommandsallowed)) {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
- synchronized (this) {
- if (SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)) {
- setAskForSMS();
- }
- }
- }
- }
- }
-
- private synchronized void setAskForSMS() {
- askForSMS = true;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- askForSMSPermissions();
- askForLocationPermissions();
- MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN));
- }
-
- @Override
- public void onDestroy() {
- if (mWakeLock != null)
- if (mWakeLock.isHeld())
- mWakeLock.release();
- super.onDestroy();
- }
-
- private void askForBatteryOptimizationPermission() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- final String packageName = getPackageName();
-
- final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- if (!pm.isIgnoringBatteryOptimizations(packageName)) {
- log.debug("Requesting ignore battery optimization");
-
- OKDialog.show(this, MainApp.gs(R.string.pleaseallowpermission), String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), new Runnable() {
-
- @Override
- public void run() {
- try {
- final Intent intent = new Intent();
-
- // ignoring battery optimizations required for constant connection
- intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
- intent.setData(Uri.parse("package:" + packageName));
- startActivity(intent);
-
- } catch (ActivityNotFoundException e) {
- final String msg = MainApp.gs(R.string.batteryoptimalizationerror);
- ToastUtils.showToastInUiThread(getApplicationContext(), msg);
- log.error(msg);
- }
- }
- });
- }
- }
- }
-
- private synchronized void askForSMSPermissions() {
- if (askForSMS) { //only when settings were changed an MainActivity resumes.
- askForSMS = false;
- if (SP.getBoolean(R.string.smscommunicator_remotecommandsallowed, false)) {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
- askForPermission(new String[]{Manifest.permission.RECEIVE_SMS,
- Manifest.permission.SEND_SMS,
- Manifest.permission.RECEIVE_MMS}, CASE_SMS);
- }
- }
- }
- }
-
- private synchronized void askForLocationPermissions() {
- if (askForLocation) { //only when settings were changed an MainActivity resumes.
- askForLocation = false;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- askForPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION}, CASE_LOCATION);
- }
- }
- }
-
- private void askForPermission(String[] permission, Integer requestCode) {
- boolean test = false;
- for (int i = 0; i < permission.length; i++) {
- test = test || (ContextCompat.checkSelfPermission(this, permission[i]) != PackageManager.PERMISSION_GRANTED);
- }
- if (test) {
- ActivityCompat.requestPermissions(this, permission, requestCode);
- }
- }
-
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (permissions.length != 0) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
switch (requestCode) {
- case CASE_STORAGE:
+ case AndroidPermission.CASE_STORAGE:
//show dialog after permission is granted
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setMessage(R.string.alert_dialog_storage_permission_text);
alert.setPositiveButton(R.string.ok, null);
alert.show();
break;
- case CASE_LOCATION:
- case CASE_SMS:
+ case AndroidPermission.CASE_LOCATION:
+ case AndroidPermission.CASE_SMS:
+ case AndroidPermission.CASE_BATTERY:
break;
}
}
@@ -343,96 +341,97 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
}
@Override
- public void onClick(final View v) {
- final Activity activity = this;
- switch (v.getId()) {
- case R.id.overview_menuButton:
- PopupMenu popup = new PopupMenu(v.getContext(), v);
- MenuInflater inflater = popup.getMenuInflater();
- inflater.inflate(R.menu.menu_main, popup.getMenu());
- popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- int id = item.getItemId();
- switch (id) {
- case R.id.nav_preferences:
- PasswordProtection.QueryPassword(v.getContext(), R.string.settings_password, "settings_password", new Runnable() {
- @Override
- public void run() {
- Intent i = new Intent(v.getContext(), PreferencesActivity.class);
- i.putExtra("id", -1);
- startActivity(i);
- }
- }, null);
- break;
- case R.id.nav_historybrowser:
- startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
- break;
- case R.id.nav_resetdb:
- new AlertDialog.Builder(v.getContext())
- .setTitle(R.string.nav_resetdb)
- .setMessage(R.string.reset_db_confirm)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- MainApp.getDbHelper().resetDatabases();
- // should be handled by Plugin-Interface and
- // additional service interface and plugin registry
- FoodPlugin.getPlugin().getService().resetFood();
- TreatmentsPlugin.getPlugin().getService().resetTreatments();
- }
- })
- .create()
- .show();
- break;
- case R.id.nav_export:
- ImportExportPrefs.verifyStoragePermissions(activity);
- ImportExportPrefs.exportSharedPreferences(activity);
- break;
- case R.id.nav_import:
- ImportExportPrefs.verifyStoragePermissions(activity);
- ImportExportPrefs.importSharedPreferences(activity);
- break;
- case R.id.nav_show_logcat:
- LogDialog.showLogcat(v.getContext());
- break;
- case R.id.nav_about:
- AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
- builder.setTitle(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION);
- if (Config.NSCLIENT || Config.G5UPLOADER)
- builder.setIcon(R.mipmap.yellowowl);
- else
- builder.setIcon(R.mipmap.blueowl);
- String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
- message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
- message += MainApp.gs(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName;
- if (MainApp.engineeringMode)
- message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
- message += MainApp.gs(R.string.about_link_urls);
- final SpannableString messageSpanned = new SpannableString(message);
- Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
- builder.setMessage(messageSpanned);
- builder.setPositiveButton(MainApp.gs(R.string.ok), null);
- AlertDialog alertDialog = builder.create();
- alertDialog.show();
- ((TextView)alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
- break;
- case R.id.nav_exit:
- log.debug("Exiting");
- MainApp.instance().stopKeepAliveService();
- MainApp.bus().post(new EventAppExit());
- MainApp.closeDbHelper();
- finish();
- System.runFinalization();
- System.exit(0);
- break;
- }
- return false;
- }
- });
- popup.show();
- break;
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences);
+ menu.findItem(R.id.nav_historybrowser).setVisible(MainApp.devBranch);
+ checkPluginPreferences(findViewById(R.id.pager));
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ switch (id) {
+ case R.id.nav_preferences:
+ PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(this, PreferencesActivity.class);
+ i.putExtra("id", -1);
+ startActivity(i);
+ }, null);
+ return true;
+ case R.id.nav_historybrowser:
+ startActivity(new Intent(this, HistoryBrowseActivity.class));
+ return true;
+ case R.id.nav_setupwizard:
+ startActivity(new Intent(this, SetupWizardActivity.class));
+ return true;
+ case R.id.nav_resetdb:
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.nav_resetdb)
+ .setMessage(R.string.reset_db_confirm)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(android.R.string.ok, (dialog, which) -> {
+ MainApp.getDbHelper().resetDatabases();
+ // should be handled by Plugin-Interface and
+ // additional service interface and plugin registry
+ FoodPlugin.getPlugin().getService().resetFood();
+ TreatmentsPlugin.getPlugin().getService().resetTreatments();
+ })
+ .create()
+ .show();
+ return true;
+ case R.id.nav_export:
+ ImportExportPrefs.verifyStoragePermissions(this);
+ ImportExportPrefs.exportSharedPreferences(this);
+ return true;
+ case R.id.nav_import:
+ ImportExportPrefs.verifyStoragePermissions(this);
+ ImportExportPrefs.importSharedPreferences(this);
+ return true;
+ case R.id.nav_show_logcat:
+ LogDialog.showLogcat(this);
+ return true;
+ case R.id.nav_about:
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(MainApp.gs(R.string.app_name) + " " + BuildConfig.VERSION);
+ if (Config.NSCLIENT || Config.G5UPLOADER)
+ builder.setIcon(R.mipmap.yellowowl);
+ else
+ builder.setIcon(R.mipmap.blueowl);
+ String message = "Build: " + BuildConfig.BUILDVERSION + "\n";
+ message += "Flavor: " + BuildConfig.FLAVOR + BuildConfig.BUILD_TYPE + "\n";
+ message += MainApp.gs(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName;
+ if (MainApp.engineeringMode)
+ message += "\n" + MainApp.gs(R.string.engineering_mode_enabled);
+ message += MainApp.gs(R.string.about_link_urls);
+ final SpannableString messageSpanned = new SpannableString(message);
+ Linkify.addLinks(messageSpanned, Linkify.WEB_URLS);
+ builder.setMessage(messageSpanned);
+ builder.setPositiveButton(MainApp.gs(R.string.ok), null);
+ AlertDialog alertDialog = builder.create();
+ alertDialog.show();
+ ((TextView) alertDialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
+ return true;
+ case R.id.nav_exit:
+ log.debug("Exiting");
+ MainApp.instance().stopKeepAliveService();
+ MainApp.bus().post(new EventAppExit());
+ MainApp.closeDbHelper();
+ finish();
+ System.runFinalization();
+ System.exit(0);
+ return true;
+ case R.id.nav_plugin_preferences:
+ ViewPager viewPager = findViewById(R.id.pager);
+ final PluginBase plugin = ((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem());
+ PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(this, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ startActivity(i);
+ }, null);
+ return true;
}
+ return actionBarDrawerToggle.onOptionsItemSelected(item);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index 45aff91654..dbb6ddee8b 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -5,6 +5,7 @@ import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.SystemClock;
import android.support.annotation.Nullable;
+import android.support.annotation.PluralsRes;
import android.support.v4.content.LocalBroadcastManager;
import com.crashlytics.android.Crashlytics;
@@ -47,8 +48,6 @@ import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.Overview.OverviewPlugin;
-import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
-import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
@@ -61,14 +60,16 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin;
+import info.nightscout.androidaps.plugins.Source.SourcePoctechPlugin;
import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
@@ -148,6 +149,7 @@ public class MainApp extends Application {
pluginsList.add(SensitivityOref0Plugin.getPlugin());
pluginsList.add(SensitivityAAPSPlugin.getPlugin());
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
+ pluginsList.add(SensitivityOref1Plugin.getPlugin());
if (Config.HWPUMPS) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.HWPUMPS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
if (Config.HWPUMPS) pluginsList.add(DanaRv2Plugin.getPlugin());
@@ -178,30 +180,22 @@ public class MainApp extends Application {
pluginsList.add(SourceGlimpPlugin.getPlugin());
if (!Config.NSCLIENT)
pluginsList.add(SourceDexcomG5Plugin.getPlugin());
+ if (!Config.NSCLIENT)
+ pluginsList.add(SourcePoctechPlugin.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
pluginsList.add(FoodPlugin.getPlugin());
pluginsList.add(WearPlugin.initPlugin(this));
pluginsList.add(StatuslinePlugin.initPlugin(this));
- pluginsList.add(new PersistentNotificationPlugin(this));
+ pluginsList.add(PersistentNotificationPlugin.getPlugin());
pluginsList.add(NSClientPlugin.getPlugin());
pluginsList.add(sConfigBuilder = ConfigBuilderPlugin.getPlugin());
MainApp.getConfigBuilder().initialize();
}
- NSUpload.uploadAppStart();
- if (Config.NSCLIENT)
- FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-NSClient"));
- else if (Config.G5UPLOADER)
- FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader"));
- else if (Config.PUMPCONTROL)
- FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-PumpControl"));
- else if (MainApp.getConstraintChecker().isClosedLoopAllowed().value())
- FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop"));
- else
- FabricPrivacy.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop"));
+ NSUpload.uploadAppStart();
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (pump != null) {
@@ -278,6 +272,10 @@ public class MainApp extends Application {
return sResources.getString(id, args);
}
+ public static String gq(@PluralsRes int id, int quantity, Object... args) {
+ return sResources.getQuantityString(id, quantity, args);
+ }
+
public static int gc(int id) {
return sResources.getColor(id);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
index 014dfcd863..a8def0ebf9 100644
--- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
@@ -30,9 +30,10 @@ import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
@@ -152,6 +153,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
+ addPreferencesFromResourceIfEnabled(SensitivityOref1Plugin.getPlugin(), PluginType.SENSITIVITY);
if (Config.HWPUMPS) {
addPreferencesFromResourceIfEnabled(DanaRPlugin.getPlugin(), PluginType.PUMP);
diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java
index 881f2e3bac..ca7d760cc4 100644
--- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java
+++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java
@@ -13,6 +13,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.ProfileStore;
@@ -38,6 +39,7 @@ import info.nightscout.androidaps.plugins.Source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.Source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.Source.SourceMM640gPlugin;
import info.nightscout.androidaps.plugins.Source.SourceNSClientPlugin;
+import info.nightscout.androidaps.plugins.Source.SourcePoctechPlugin;
import info.nightscout.androidaps.plugins.Source.SourceXdripPlugin;
import info.nightscout.androidaps.receivers.DataReceiver;
import info.nightscout.utils.BundleLogger;
@@ -54,6 +56,7 @@ public class DataService extends IntentService {
boolean mm640gEnabled = false;
boolean glimpEnabled = false;
boolean dexcomG5Enabled = false;
+ boolean poctechEnabled = false;
public DataService() {
super("DataService");
@@ -70,36 +73,49 @@ public class DataService extends IntentService {
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = false;
+ poctechEnabled = false;
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceXdripPlugin.class)) {
xDripEnabled = true;
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = false;
+ poctechEnabled = false;
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceNSClientPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = true;
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = false;
+ poctechEnabled = false;
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceMM640gPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = true;
glimpEnabled = false;
dexcomG5Enabled = false;
+ poctechEnabled = false;
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceGlimpPlugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = true;
dexcomG5Enabled = false;
+ poctechEnabled = false;
} else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourceDexcomG5Plugin.class)) {
xDripEnabled = false;
nsClientEnabled = false;
mm640gEnabled = false;
glimpEnabled = false;
dexcomG5Enabled = true;
+ poctechEnabled = false;
+ } else if (ConfigBuilderPlugin.getPlugin().getActiveBgSource().getClass().equals(SourcePoctechPlugin.class)) {
+ xDripEnabled = false;
+ nsClientEnabled = false;
+ mm640gEnabled = false;
+ glimpEnabled = false;
+ dexcomG5Enabled = false;
+ poctechEnabled = true;
}
boolean isNSProfile = MainApp.getConfigBuilder().getActiveProfileInterface() != null && MainApp.getConfigBuilder().getActiveProfileInterface().getClass().equals(NSProfilePlugin.class);
@@ -129,6 +145,10 @@ public class DataService extends IntentService {
if (dexcomG5Enabled) {
handleNewDataFromDexcomG5(intent);
}
+ } else if (Intents.POCTECH_BG.equals(action)) {
+ if (poctechEnabled) {
+ handleNewDataFromPoctech(intent);
+ }
} else if (Intents.ACTION_NEW_SGV.equals(action)) {
if (nsClientEnabled || SP.getBoolean(R.string.key_ns_autobackfill, true))
handleNewDataFromNSClient(intent);
@@ -250,6 +270,41 @@ public class DataService extends IntentService {
}
}
+ private void handleNewDataFromPoctech(Intent intent) {
+
+ Bundle bundle = intent.getExtras();
+ if (bundle == null) return;
+
+ BgReading bgReading = new BgReading();
+
+ String data = bundle.getString("data");
+ log.debug("Received Poctech Data", data);
+
+ try {
+ JSONArray jsonArray = new JSONArray(data);
+ log.debug("Received Poctech Data size:" + jsonArray.length());
+ for (int i = 0; i < jsonArray.length(); i++) {
+ JSONObject json = jsonArray.getJSONObject(i);
+ bgReading.value = json.getDouble("current");
+ bgReading.direction = json.getString("direction");
+ bgReading.date = json.getLong("date");
+ bgReading.raw = json.getDouble("raw");
+ if (JsonHelper.safeGetString(json, "units", Constants.MGDL).equals("mmol/L"))
+ bgReading.value = bgReading.value * Constants.MMOLL_TO_MGDL;
+ boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "Poctech");
+ if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
+ NSUpload.uploadBg(bgReading);
+ }
+ if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
+ NSUpload.sendToXdrip(bgReading);
+ }
+ }
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
private void handleNewDataFromMM640g(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle == null) return;
@@ -427,9 +482,7 @@ public class DataService extends IntentService {
if (bundles.containsKey("sgv")) {
String sgvstring = bundles.getString("sgv");
JSONObject sgvJson = new JSONObject(sgvstring);
- NSSgv nsSgv = new NSSgv(sgvJson);
- BgReading bgReading = new BgReading(nsSgv);
- MainApp.getDbHelper().createIfNotExists(bgReading, "NS");
+ storeSgv(sgvJson);
}
if (bundles.containsKey("sgvs")) {
@@ -437,9 +490,7 @@ public class DataService extends IntentService {
JSONArray jsonArray = new JSONArray(sgvstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject sgvJson = jsonArray.getJSONObject(i);
- NSSgv nsSgv = new NSSgv(sgvJson);
- BgReading bgReading = new BgReading(nsSgv);
- MainApp.getDbHelper().createIfNotExists(bgReading, "NS");
+ storeSgv(sgvJson);
}
}
} catch (Exception e) {
@@ -452,11 +503,7 @@ public class DataService extends IntentService {
if (bundles.containsKey("mbg")) {
String mbgstring = bundles.getString("mbg");
JSONObject mbgJson = new JSONObject(mbgstring);
- NSMbg nsMbg = new NSMbg(mbgJson);
- CareportalEvent careportalEvent = new CareportalEvent(nsMbg);
- MainApp.getDbHelper().createOrUpdate(careportalEvent);
- if (Config.logIncommingData)
- log.debug("Adding/Updating new MBG: " + careportalEvent.log());
+ storeMbg(mbgJson);
}
if (bundles.containsKey("mbgs")) {
@@ -464,11 +511,7 @@ public class DataService extends IntentService {
JSONArray jsonArray = new JSONArray(sgvstring);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject mbgJson = jsonArray.getJSONObject(i);
- NSMbg nsMbg = new NSMbg(mbgJson);
- CareportalEvent careportalEvent = new CareportalEvent(nsMbg);
- MainApp.getDbHelper().createOrUpdate(careportalEvent);
- if (Config.logIncommingData)
- log.debug("Adding/Updating new MBG: " + careportalEvent.log());
+ storeMbg(mbgJson);
}
}
} catch (Exception e) {
@@ -549,6 +592,21 @@ public class DataService extends IntentService {
}
}
+ private void storeMbg(JSONObject mbgJson) {
+ NSMbg nsMbg = new NSMbg(mbgJson);
+ CareportalEvent careportalEvent = new CareportalEvent(nsMbg);
+ MainApp.getDbHelper().createOrUpdate(careportalEvent);
+ if (Config.logIncommingData)
+ log.debug("Adding/Updating new MBG: " + careportalEvent.log());
+ }
+
+ private void storeSgv(JSONObject sgvJson) {
+ NSSgv nsSgv = new NSSgv(sgvJson);
+ BgReading bgReading = new BgReading(nsSgv);
+ MainApp.getDbHelper().createIfNotExists(bgReading, "NS");
+ SourceNSClientPlugin.getPlugin().detectSource(JsonHelper.safeGetString(sgvJson, "device"), JsonHelper.safeGetLong(sgvJson, "mills"));
+ }
+
private void handleNewSMS(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle == null) return;
diff --git a/app/src/main/java/info/nightscout/androidaps/Services/Intents.java b/app/src/main/java/info/nightscout/androidaps/Services/Intents.java
index 744530c8f2..25485fb34d 100644
--- a/app/src/main/java/info/nightscout/androidaps/Services/Intents.java
+++ b/app/src/main/java/info/nightscout/androidaps/Services/Intents.java
@@ -49,4 +49,6 @@ public interface Intents {
String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED";
String DEXCOMG5_BG = "com.dexcom.cgm.DATA";
+
+ String POCTECH_BG = "com.china.poctech.data";
}
diff --git a/app/src/main/java/info/nightscout/androidaps/SingleFragmentActivity.java b/app/src/main/java/info/nightscout/androidaps/SingleFragmentActivity.java
new file mode 100644
index 0000000000..567799fe5e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/SingleFragmentActivity.java
@@ -0,0 +1,59 @@
+package info.nightscout.androidaps;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.tabs.TabPageAdapter;
+import info.nightscout.utils.PasswordProtection;
+
+public class SingleFragmentActivity extends AppCompatActivity {
+
+ private PluginBase plugin;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_single_fragment);
+
+ this.plugin = MainApp.getPluginsList().get(getIntent().getIntExtra("plugin", -1));
+ setTitle(plugin.getName());
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+
+ if (savedInstanceState == null) {
+ getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout,
+ Fragment.instantiate(this, plugin.pluginDescription.getFragmentClass())).commit();
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ }
+ else if (item.getItemId() == R.id.nav_plugin_preferences) {
+ PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(this, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ startActivity(i);
+ }, null);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (plugin.getPreferencesId() != -1)
+ getMenuInflater().inflate(R.menu.menu_single_fragment, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
index 3161cb19f3..bfbbfedbd1 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/ConstraintChecker.java
@@ -4,12 +4,10 @@ import java.util.ArrayList;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
/**
* Created by mike on 19.03.2018.
@@ -25,7 +23,7 @@ public class ConstraintChecker implements ConstraintsInterface {
public Constraint isLoopInvokationAllowed() {
- return isLoopInvokationAllowed(new Constraint<>(true));
+ return isLoopInvocationAllowed(new Constraint<>(true));
}
public Constraint isClosedLoopAllowed() {
@@ -69,13 +67,13 @@ public class ConstraintChecker implements ConstraintsInterface {
}
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
ArrayList constraintsPlugins = mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class);
for (PluginBase p : constraintsPlugins) {
ConstraintsInterface constraint = (ConstraintsInterface) p;
if (!p.isEnabled(PluginType.CONSTRAINTS)) continue;
- constraint.isLoopInvokationAllowed(value);
+ constraint.isLoopInvocationAllowed(value);
}
return value;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java
index c2f9d16dc3..6e65e6d6d3 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java
@@ -10,6 +10,7 @@ import java.util.Date;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
/**
* Created by mike on 29.05.2017.
@@ -17,6 +18,7 @@ import info.nightscout.androidaps.db.Source;
public class DetailedBolusInfo {
public long date = System.currentTimeMillis();
+ public long lastKnownBolusTime;
public String eventType = CareportalEvent.MEALBOLUS;
public double insulin = 0;
public double carbs = 0;
diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
index 374612f2f5..7412f8ce4c 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -202,6 +202,12 @@ public class Profile {
if (targetHigh_v == null)
targetHigh_v = convertToSparseArray(targetHigh);
validate(targetHigh_v);
+
+ if (targetHigh_v.size() != targetLow_v.size()) isValid = false;
+ else for (int i = 0; i < targetHigh_v.size(); i++)
+ if (targetHigh_v.valueAt(i) < targetLow_v.valueAt(i))
+ isValid = false;
+
isValidated = true;
}
@@ -226,6 +232,10 @@ public class Profile {
basal_v.setValueAt(i, description.basalMinimumRate);
if (notify)
sendBelowMinimumNotification(from);
+ } else if (basal_v.valueAt(i) > description.basalMaximumRate) {
+ basal_v.setValueAt(i, description.basalMaximumRate);
+ if (notify)
+ sendAboveMaximumNotification(from);
}
}
} else {
@@ -235,12 +245,16 @@ public class Profile {
isValidated = false;
}
- }
+ }
return isValid;
}
protected void sendBelowMinimumNotification(String from) {
- MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
+ MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
+ }
+
+ protected void sendAboveMaximumNotification(String from) {
+ MainApp.bus().post(new EventNewNotification(new Notification(Notification.MAXIMUM_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.maximumbasalvaluereplaced), from), Notification.NORMAL)));
}
private void validate(LongSparseArray array) {
@@ -444,12 +458,12 @@ public class Profile {
return ret;
}
- public double getTarget(){
- return getTarget(secondsFromMidnight(System.currentTimeMillis()));
+ public double getTarget() {
+ return getTarget(secondsFromMidnight(System.currentTimeMillis()));
}
protected double getTarget(int timeAsSeconds) {
- return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds))/2;
+ return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds)) / 2;
}
public double getTargetLow() {
@@ -544,6 +558,12 @@ public class Profile {
else return DecimalFormatter.to1Decimal(valueInMmol);
}
+ public static String toSignedUnitsString(Double valueInMgdl, Double valueInMmol, String units) {
+ if (units.equals(Constants.MGDL))
+ return (valueInMgdl > 0 ? "+" : "") + DecimalFormatter.to0Decimal(valueInMgdl);
+ else return (valueInMmol > 0 ? "+" : "") + DecimalFormatter.to1Decimal(valueInMmol);
+ }
+
// targets are stored in mg/dl but profile vary
public static String toTargetRangeString(double low, double high, String sourceUnits, String units) {
double lowMgdl = toMgdl(low, sourceUnits);
diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
index d5a1c90100..6cda2ab4ce 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java
@@ -24,15 +24,17 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.interfaces.Interval;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg;
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.T;
import info.nightscout.utils.Translator;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS)
-public class CareportalEvent implements DataPointWithLabelInterface {
+public class CareportalEvent implements DataPointWithLabelInterface, Interval {
private static Logger log = LoggerFactory.getLogger(CareportalEvent.class);
@DatabaseField(id = true)
@@ -87,7 +89,7 @@ public class CareportalEvent implements DataPointWithLabelInterface {
}
public long getHoursFromStart() {
- return (System.currentTimeMillis() - date) / (60 * 1000);
+ return (System.currentTimeMillis() - date) / (60 * 60 * 1000);
}
public String age() {
@@ -98,13 +100,7 @@ public class CareportalEvent implements DataPointWithLabelInterface {
return diff.get(TimeUnit.DAYS) + " " + MainApp.gs(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.gs(R.string.hours);
}
- public boolean isOlderThan(double hours) {
- Map diff = computeDiff(date, System.currentTimeMillis());
- if(diff.get(TimeUnit.DAYS)*24 + diff.get(TimeUnit.HOURS) > hours)
- return true;
- else
- return false;
- }
+ public boolean isOlderThan(double hours) { return getHoursFromStart() > hours; }
public String log() {
return "CareportalEvent{" +
@@ -133,6 +129,19 @@ public class CareportalEvent implements DataPointWithLabelInterface {
return result;
}
+
+ public static boolean isEvent5minBack(List list, long time) {
+ for (int i = 0; i < list.size(); i++) {
+ CareportalEvent event = list.get(i);
+ if (event.date <= time && event.date > (time - T.mins(5).msecs())) {
+ //log.debug("Found event for time: " + DateUtil.dateAndTimeString(time) + " " + event.toString());
+ return true;
+ }
+ }
+ //log.debug("WWWWWW No found event for time: " + DateUtil.dateAndTimeString(time));
+ return false;
+ }
+
// -------- DataPointWithLabelInterface -------
@Override
@@ -213,14 +222,7 @@ public class CareportalEvent implements DataPointWithLabelInterface {
@Override
public long getDuration() {
- try {
- JSONObject object = new JSONObject(json);
- if (object.has("duration"))
- return object.getInt("duration") * 60 * 1000L;
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- }
- return 0;
+ return end() - start();
}
@Override
@@ -259,8 +261,79 @@ public class CareportalEvent implements DataPointWithLabelInterface {
if (eventType.equals(EXERCISE))
return Color.BLUE;
if (eventType.equals(OPENAPSOFFLINE))
- return Color.GRAY;
+ return Color.GRAY & 0x80FFFFFF;
return Color.GRAY;
}
+ // Interval interface
+ Long cuttedEnd = null;
+
+ @Override
+ public long durationInMsec() {
+ try {
+ JSONObject object = new JSONObject(json);
+ if (object.has("duration"))
+ return object.getInt("duration") * 60 * 1000L;
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+ return 0;
+ }
+
+ @Override
+ public long start() {
+ return date;
+ }
+
+ @Override
+ public long originalEnd() {
+ return date + durationInMsec();
+ }
+
+ @Override
+ public long end() {
+ if (cuttedEnd != null)
+ return cuttedEnd;
+ return originalEnd();
+ }
+
+ @Override
+ public void cutEndTo(long end) {
+ cuttedEnd = end;
+ }
+
+ @Override
+ public boolean match(long time) {
+ if (start() <= time && end() >= time)
+ return true;
+ return false;
+ }
+
+ public boolean before(long time) {
+ if (end() < time)
+ return true;
+ return false;
+ }
+
+ public boolean after(long time) {
+ if (start() > time)
+ return true;
+ return false;
+ }
+
+ @Override
+ public boolean isInProgress() {
+ return match(System.currentTimeMillis());
+ }
+
+ @Override
+ public boolean isEndingEvent() {
+ return durationInMsec() == 0;
+ }
+
+ @Override
+ public boolean isValid() {
+ return eventType.equals(OPENAPSOFFLINE);
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
index 7174c19ec4..f869ca36c5 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
@@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.data.OverlappingIntervals;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange;
@@ -675,7 +676,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
.source(Source.NIGHTSCOUT);
createOrUpdate(tempTarget);
} catch (JSONException e) {
- log.error("Unhandled exception", e);
+ log.error("Unhandled exception: " + trJson.toString(), e);
}
}
@@ -761,7 +762,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
}
} catch (SQLException | JSONException e) {
- log.error("Unhandled exception", e);
+ log.error("Unhandled exception: " + trJson.toString(), e);
}
}
@@ -966,7 +967,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
createOrUpdate(tempBasal);
}
} catch (JSONException e) {
- log.error("Unhandled exception", e);
+ log.error("Unhandled exception: " + trJson.toString(), e);
}
}
@@ -1242,6 +1243,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
where.ge("date", mills);
PreparedQuery preparedQuery = queryBuilder.prepare();
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
return careportalEvents;
} catch (SQLException e) {
log.error("Unhandled exception", e);
@@ -1249,13 +1251,41 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
- public List getCareportalEventsFromTime(boolean ascending) {
+ public void preprocessOpenAPSOfflineEvents(List list) {
+ OverlappingIntervals offlineEvents = new OverlappingIntervals();
+ for (int i = 0; i < list.size(); i++) {
+ CareportalEvent event = list.get(i);
+ if (!event.eventType.equals(CareportalEvent.OPENAPSOFFLINE)) continue;
+ offlineEvents.add(event);
+ }
+
+ }
+
+ public List getCareportalEventsFromTime(long mills, String type, boolean ascending) {
+ try {
+ List careportalEvents;
+ QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder();
+ queryBuilder.orderBy("date", ascending);
+ Where where = queryBuilder.where();
+ where.ge("date", mills).and().eq("eventType", type);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
+ return careportalEvents;
+ } catch (SQLException e) {
+ log.error("Unhandled exception", e);
+ }
+ return new ArrayList<>();
+ }
+
+ public List getCareportalEvents(boolean ascending) {
try {
List careportalEvents;
QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder();
queryBuilder.orderBy("date", ascending);
PreparedQuery preparedQuery = queryBuilder.prepare();
careportalEvents = getDaoCareportalEvents().query(preparedQuery);
+ preprocessOpenAPSOfflineEvents(careportalEvents);
return careportalEvents;
} catch (SQLException e) {
log.error("Unhandled exception", e);
@@ -1315,7 +1345,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
careportalEvent._id = trJson.getString("_id");
createOrUpdate(careportalEvent);
} catch (SQLException | JSONException e) {
- log.error("Unhandled exception", e);
+ log.error("Unhandled exception: " + trJson.toString(), e);
}
}
@@ -1470,14 +1500,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
profileSwitch.profileJson = trJson.getString("profileJson");
else {
ProfileStore store = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
- Profile profile = store.getSpecificProfile(profileSwitch.profileName);
- if (profile != null) {
- profileSwitch.profileJson = profile.getData().toString();
- log.debug("Profile switch prefilled with JSON from local store");
- // Update data in NS
- NSUpload.updateProfileSwitch(profileSwitch);
+ if (store != null) {
+ Profile profile = store.getSpecificProfile(profileSwitch.profileName);
+ if (profile != null) {
+ profileSwitch.profileJson = profile.getData().toString();
+ log.debug("Profile switch prefilled with JSON from local store");
+ // Update data in NS
+ NSUpload.updateProfileSwitch(profileSwitch);
+ } else {
+ log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
+ return;
+ }
} else {
- log.debug("JSON for profile switch doesn't exist. Ignoring: " + trJson.toString());
+ log.debug("Store for profile switch doesn't exist. Ignoring: " + trJson.toString());
return;
}
}
@@ -1485,7 +1520,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
profileSwitch.profilePlugin = trJson.getString("profilePlugin");
createOrUpdate(profileSwitch);
} catch (JSONException e) {
- log.error("Unhandled exception", e);
+ log.error("Unhandled exception: " + trJson.toString(), e);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java
index 1123cb58df..ea97f4ddca 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java
@@ -58,7 +58,7 @@ public class ExtendedBolus implements Interval, DataPointWithLabelInterface {
public int durationInMinutes = 0; // duration == 0 means end of extended bolus
@DatabaseField
- public int insulinInterfaceID = InsulinInterface.FASTACTINGINSULIN;
+ public int insulinInterfaceID = InsulinInterface.OREF_RAPID_ACTING;
@DatabaseField
public double dia = Constants.defaultDIA;
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
index 03df71f31b..57050bdcc9 100644
--- a/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventNetworkChange.java
@@ -1,5 +1,8 @@
package info.nightscout.androidaps.events;
+
+import info.nightscout.utils.StringUtils;
+
public class EventNetworkChange extends Event {
public boolean mobileConnected = false;
@@ -9,6 +12,6 @@ public class EventNetworkChange extends Event {
public boolean roaming = false;
public String getSsid() {
- return ssid.replace("SSID: ","").replaceAll("\"","");
+ return StringUtils.removeSurroundingQuotes(ssid);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java
new file mode 100644
index 0000000000..0b2d933c12
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileStoreChanged.java
@@ -0,0 +1,4 @@
+package info.nightscout.androidaps.events;
+
+public class EventProfileStoreChanged extends Event {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
index a1daa08a56..820170dc0f 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ConstraintsInterface.java
@@ -7,7 +7,7 @@ import info.nightscout.androidaps.data.Profile;
*/
public interface ConstraintsInterface {
- default Constraint isLoopInvokationAllowed(Constraint value) {
+ default Constraint isLoopInvocationAllowed(Constraint value) {
return value;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java
index 1c5ee83834..374d96890a 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java
@@ -9,4 +9,5 @@ import info.nightscout.androidaps.data.PumpEnactResult;
public interface DanaRInterface {
PumpEnactResult loadHistory(byte type); // for history browser
PumpEnactResult loadEvents(); // events history to build treatments from
+ PumpEnactResult setUserOptions(); // like AnyDana does
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java
index a123554ae8..34b14d9b5d 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java
@@ -8,8 +8,8 @@ import info.nightscout.androidaps.plugins.Treatments.Treatment;
*/
public interface InsulinInterface {
- int FASTACTINGINSULIN = 0;
- int FASTACTINGINSULINPROLONGED = 1;
+ // int FASTACTINGINSULIN = 0; // old model no longer available
+ // int FASTACTINGINSULINPROLONGED = 1; // old model no longer available
int OREF_RAPID_ACTING = 2;
int OREF_ULTRA_RAPID_ACTING = 3;
int OREF_FREE_PEAK = 4;
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
index 1173936430..9f3e4fe5c0 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java
@@ -1,11 +1,13 @@
package info.nightscout.androidaps.interfaces;
import android.os.SystemClock;
+import android.support.v4.app.FragmentActivity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
/**
@@ -32,6 +34,12 @@ public abstract class PluginBase {
this.pluginDescription = pluginDescription;
}
+ // Default always calls invoke
+ // Plugins that have special constraints if they get switched to may override this method
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity activity) {
+ pluginSwitcher.invoke();
+ }
+
// public PluginType getType() {
// return mainType;
// }
@@ -57,6 +65,11 @@ public abstract class PluginBase {
return getName();
}
+ public String getDescription() {
+ if (pluginDescription.description == -1) return null;
+ else return MainApp.gs(pluginDescription.description);
+ }
+
public PluginType getType() {
return pluginDescription.mainType;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java
index c86ae639fa..1634fc672d 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java
@@ -9,6 +9,7 @@ public class PluginDescription {
boolean showInList = true;
int pluginName = -1;
int shortName = -1;
+ int description = -1;
int preferencesId = -1;
int advancedPreferencesId = -1;
public boolean enableByDefault = false;
@@ -74,6 +75,11 @@ public class PluginDescription {
return this;
}
+ public PluginDescription description(int description) {
+ this.description = description;
+ return this;
+ }
+
public String getFragmentClass() {
return fragmentClass;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java
index ec6976a2c7..2edf9033bf 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java
@@ -35,6 +35,7 @@ public class PumpDescription {
public boolean isSetBasalProfileCapable = true;
public double basalStep = 0.01d;
public double basalMinimumRate = 0.04d;
+ public double basalMaximumRate = 25d;
public boolean isRefillingCapable = false;
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java
index deb649c21f..81af28eaa4 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java
@@ -7,5 +7,10 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
*/
public interface SensitivityInterface {
+
+ double MIN_HOURS = 1;
+ double MIN_HOURS_FULL_AUTOSENS = 4;
+
AutosensResult detectSensitivity(long fromTime, long toTime);
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java
index 27a6a0846b..dc437e04ab 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java
@@ -50,7 +50,7 @@ public interface TreatmentsInterface {
boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus);
- boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo);
+ boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate);
TempTarget getTempTargetFromHistory();
TempTarget getTempTargetFromHistory(long time);
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 84086d6117..d45fb10b4e 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
@@ -87,6 +87,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
tempBasalCancel.setOnClickListener(this);
fill.setOnClickListener(this);
history.setOnClickListener(this);
+ history.setVisibility(MainApp.devBranch ? View.VISIBLE : View.GONE);
tddStats.setOnClickListener(this);
updateGUI();
@@ -125,7 +126,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
+ if (MainApp.getConfigBuilder().getActiveProfileInterface() != null && MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
profileSwitch.setVisibility(View.VISIBLE);
} else {
profileSwitch.setVisibility(View.GONE);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java
index 2397410693..ff6275c9c9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsPlugin.java
@@ -17,6 +17,7 @@ public class ActionsPlugin extends PluginBase {
.fragmentClass(ActionsFragment.class.getName())
.pluginName(R.string.actions)
.shortName(R.string.actions_shortname)
+ .description(R.string.description_actions)
);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java
index dda2e61006..558a7c381c 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
@@ -61,6 +61,10 @@ public class FillDialog extends DialogFragment implements OnClickListener {
private EditText notesEdit;
+ //one shot guards
+ private boolean accepted;
+ private boolean okClicked;
+
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
@@ -163,7 +167,14 @@ public class FillDialog extends DialogFragment implements OnClickListener {
}
- private void confirmAndDeliver() {
+ private synchronized void confirmAndDeliver() {
+ if (okClicked) {
+ log.debug("guarding: ok already clicked");
+ dismiss();
+ return;
+ }
+ okClicked = true;
+
try {
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
@@ -179,10 +190,10 @@ public class FillDialog extends DialogFragment implements OnClickListener {
}
if (pumpSiteChangeCheckbox.isChecked())
- confirmMessage.add("" + "" + MainApp.gs(R.string.record_pump_site_change) + "");
+ confirmMessage.add("" + "" + MainApp.gs(R.string.record_pump_site_change) + "");
if (insulinCartridgeChangeCheckbox.isChecked())
- confirmMessage.add("" + "" + MainApp.gs(R.string.record_insulin_cartridge_change) + "");
+ confirmMessage.add("" + "" + MainApp.gs(R.string.record_insulin_cartridge_change) + "");
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
@@ -198,32 +209,40 @@ public class FillDialog extends DialogFragment implements OnClickListener {
if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) {
builder.setMessage(Html.fromHtml(Joiner.on(" ").join(confirmMessage)));
builder.setPositiveButton(MainApp.gs(R.string.primefill), (dialog, id) -> {
- if (finalInsulinAfterConstraints > 0) {
- 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)
- detailedBolusInfo.notes = notes;
- 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.gs(R.string.treatmentdeliveryerror));
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- MainApp.instance().startActivity(i);
+ synchronized (builder) {
+ if (accepted) {
+ log.debug("guarding: already accepted");
+ return;
+ }
+ accepted = true;
+
+ if (finalInsulinAfterConstraints > 0) {
+ 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)
+ detailedBolusInfo.notes = notes;
+ 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.gs(R.string.treatmentdeliveryerror));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+ }
}
- }
- });
- FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill"));
+ });
+ FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill"));
+ }
+ if (pumpSiteChangeCheckbox.isChecked())
+ NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes);
+ if (insulinCartridgeChangeCheckbox.isChecked())
+ NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes);
}
- if (pumpSiteChangeCheckbox.isChecked())
- NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes);
- if (insulinCartridgeChangeCheckbox.isChecked())
- NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes);
});
} else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java
index 4a4210f29e..264488f684 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalFragment.java
@@ -218,50 +218,19 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);
+ handleAge(iage, CareportalEvent.INSULINCHANGE, iageWarn, iageUrgent);
+
double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72);
double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48);
+ handleAge(cage, CareportalEvent.SITECHANGE, cageWarn, cageUrgent);
+
double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166);
double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164);
+ handleAge(sage, CareportalEvent.SENSORCHANGE, sageWarn, sageUrgent);
+
double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360);
double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240);
-
- String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.gs(R.string.notavailable);
- if (sage != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
- if (careportalEvent != null) {
- sage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, sageWarn, sageUrgent));
- sage.setText(careportalEvent.age());
- } else {
- sage.setText(notavailable);
- }
- }
- if (iage != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE);
- if (careportalEvent != null) {
- iage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, iageWarn, iageUrgent));
- iage.setText(careportalEvent.age());
- } else {
- iage.setText(notavailable);
- }
- }
- if (cage != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE);
- if (careportalEvent != null) {
- cage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, cageWarn, cageUrgent));
- cage.setText(careportalEvent.age());
- } else {
- cage.setText(notavailable);
- }
- }
- if (pbage != null) {
- careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE);
- if (careportalEvent != null) {
- pbage.setTextColor(CareportalFragment.determineTextColor(careportalEvent, pbageWarn, pbageUrgent));
- pbage.setText(careportalEvent.age());
- } else {
- pbage.setText(notavailable);
- }
- }
+ handleAge(pbage, CareportalEvent.PUMPBATTERYCHANGE, pbageWarn, pbageUrgent);
}
);
}
@@ -277,5 +246,21 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
}
}
+
+ private static TextView handleAge(final TextView age, String eventType, double warnThreshold, double urgentThreshold) {
+ String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.gs(R.string.notavailable);
+
+ if (age != null) {
+ CareportalEvent careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(eventType);
+ if (careportalEvent != null) {
+ age.setTextColor(CareportalFragment.determineTextColor(careportalEvent, warnThreshold, urgentThreshold));
+ age.setText(careportalEvent.age());
+ } else {
+ age.setText(notavailable);
+ }
+ }
+
+ return age;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java
index 1428880a81..22aa4686b2 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java
@@ -23,6 +23,9 @@ public class CareportalPlugin extends PluginBase {
.fragmentClass(CareportalFragment.class.getName())
.pluginName(R.string.careportal)
.shortName(R.string.careportal_shortname)
+ .visibleByDefault(true)
+ .enableByDefault(true)
+ .description(R.string.description_careportal)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java
index 5ca9232646..fabd83f0ea 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java
@@ -21,7 +21,7 @@ abstract public class SubscriberFragment extends Fragment {
updateGUI();
}
- @Override public void onDestroyView() {
+ @Override public synchronized void onDestroyView() {
super.onDestroyView();
if (unbinder != null)
unbinder.unbind();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java
index 70b5eb466b..3e60ca2b77 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java
@@ -1,30 +1,30 @@
package info.nightscout.androidaps.plugins.ConfigBuilder;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
-import android.widget.ImageView;
+import android.widget.ImageButton;
import android.widget.LinearLayout;
-import android.widget.ListAdapter;
-import android.widget.ListView;
+import android.widget.RadioButton;
+import android.widget.ScrollView;
import android.widget.TextView;
import com.crashlytics.android.answers.CustomEvent;
import java.util.ArrayList;
+import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
-import info.nightscout.androidaps.Config;
+import butterknife.Unbinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.PreferencesActivity;
import info.nightscout.androidaps.R;
@@ -43,76 +43,36 @@ import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.Insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.PasswordProtection;
public class ConfigBuilderFragment extends SubscriberFragment {
- @BindView(R.id.configbuilder_insulinlistview)
- ListView insulinListView;
- @BindView(R.id.configbuilder_sensitivitylistview)
- ListView sensitivityListView;
- @BindView(R.id.configbuilder_bgsourcelistview)
- ListView bgsourceListView;
- @BindView(R.id.configbuilder_bgsourcelabel)
- TextView bgsourceLabel;
- @BindView(R.id.configbuilder_pumplistview)
- ListView pumpListView;
- @BindView(R.id.configbuilder_pumplabel)
- TextView pumpLabel;
- @BindView(R.id.configbuilder_looplistview)
- ListView loopListView;
- @BindView(R.id.configbuilder_looplabel)
- TextView loopLabel;
- @BindView(R.id.configbuilder_treatmentslistview)
- ListView treatmentsListView;
- @BindView(R.id.configbuilder_treatmentslabel)
- TextView treatmentsLabel;
- @BindView(R.id.configbuilder_profilelistview)
- ListView profileListView;
- @BindView(R.id.configbuilder_profilelabel)
- TextView profileLabel;
- @BindView(R.id.configbuilder_apslistview)
- ListView apsListView;
- @BindView(R.id.configbuilder_apslabel)
- TextView apsLabel;
- @BindView(R.id.configbuilder_constraintslistview)
- ListView constraintsListView;
- @BindView(R.id.configbuilder_constraintslabel)
- TextView constraintsLabel;
- @BindView(R.id.configbuilder_generallistview)
- ListView generalListView;
+ private List pluginViewHolders = new ArrayList<>();
- @BindView(R.id.configbuilder_mainlayout)
- LinearLayout mainLayout;
- @BindView(R.id.configbuilder_unlock)
+ @BindView(R.id.categories)
+ LinearLayout categories;
+
+ @BindView(R.id.main_layout)
+ ScrollView mainLayout;
+ @BindView(R.id.unlock)
Button unlock;
- PluginCustomAdapter insulinDataAdapter = null;
- PluginCustomAdapter sensivityDataAdapter = null;
- PluginCustomAdapter bgsourceDataAdapter = null;
- PluginCustomAdapter pumpDataAdapter = null;
- PluginCustomAdapter loopDataAdapter = null;
- PluginCustomAdapter treatmentDataAdapter = null;
- PluginCustomAdapter profileDataAdapter = null;
- PluginCustomAdapter apsDataAdapter = null;
- PluginCustomAdapter constraintsDataAdapter = null;
- PluginCustomAdapter generalDataAdapter = null;
-
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
View view = inflater.inflate(R.layout.configbuilder_fragment, container, false);
-
unbinder = ButterKnife.bind(this, view);
if (PasswordProtection.isLocked("settings_password"))
mainLayout.setVisibility(View.GONE);
- else
- unlock.setVisibility(View.GONE);
+ else unlock.setVisibility(View.GONE);
+
+ createViews();
+
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
@@ -121,225 +81,58 @@ public class ConfigBuilderFragment extends SubscriberFragment {
return null;
}
- @OnClick(R.id.configbuilder_unlock)
- public void onClickUnlock() {
+ @OnClick(R.id.unlock)
+ void onClickUnlock() {
PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
mainLayout.setVisibility(View.VISIBLE);
unlock.setVisibility(View.GONE);
}, null);
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.unbind();
+ pluginViewHolders.clear();
+ }
@Override
protected void updateGUI() {
-
- insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN), PluginType.INSULIN);
- insulinListView.setAdapter(insulinDataAdapter);
- setListViewHeightBasedOnChildren(insulinListView);
- bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE), PluginType.BGSOURCE);
- bgsourceListView.setAdapter(bgsourceDataAdapter);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.BGSOURCE).size() == 0)
- bgsourceLabel.setVisibility(View.GONE);
- setListViewHeightBasedOnChildren(bgsourceListView);
- pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP), PluginType.PUMP);
- pumpListView.setAdapter(pumpDataAdapter);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP).size() == 0 || Config.NSCLIENT || Config.G5UPLOADER) {
- pumpLabel.setVisibility(View.GONE);
- pumpListView.setVisibility(View.GONE);
- }
- setListViewHeightBasedOnChildren(pumpListView);
- loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP), PluginType.LOOP);
- loopListView.setAdapter(loopDataAdapter);
- setListViewHeightBasedOnChildren(loopListView);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP).size() == 0)
- loopLabel.setVisibility(View.GONE);
- treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT), PluginType.TREATMENT);
- treatmentsListView.setAdapter(treatmentDataAdapter);
- setListViewHeightBasedOnChildren(treatmentsListView);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT).size() == 0)
- treatmentsLabel.setVisibility(View.GONE);
- profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE), PluginType.PROFILE);
- profileListView.setAdapter(profileDataAdapter);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.PROFILE).size() == 0)
- profileLabel.setVisibility(View.GONE);
- setListViewHeightBasedOnChildren(profileListView);
- apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.APS), PluginType.APS);
- apsListView.setAdapter(apsDataAdapter);
- setListViewHeightBasedOnChildren(apsListView);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.APS).size() == 0)
- apsLabel.setVisibility(View.GONE);
- sensivityDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY), PluginType.SENSITIVITY);
- sensitivityListView.setAdapter(sensivityDataAdapter);
- setListViewHeightBasedOnChildren(sensitivityListView);
- constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS), PluginType.CONSTRAINTS);
- constraintsListView.setAdapter(constraintsDataAdapter);
- setListViewHeightBasedOnChildren(constraintsListView);
- if (MainApp.getSpecificPluginsVisibleInList(PluginType.CONSTRAINTS).size() == 0)
- constraintsLabel.setVisibility(View.GONE);
- generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL), PluginType.GENERAL);
- generalListView.setAdapter(generalDataAdapter);
- setListViewHeightBasedOnChildren(generalListView);
+ for (PluginViewHolder pluginViewHolder : pluginViewHolders) pluginViewHolder.update();
}
- /*
- * ConfigBuilderFragment code
- */
-
- private class PluginCustomAdapter extends ArrayAdapter {
-
- private ArrayList pluginList;
- final private PluginType type;
-
- PluginCustomAdapter(Context context, int textViewResourceId,
- ArrayList pluginList, PluginType type) {
- super(context, textViewResourceId, pluginList);
- this.pluginList = new ArrayList<>();
- this.pluginList.addAll(pluginList);
- this.type = type;
- }
-
- private class PluginViewHolder {
- TextView name;
- CheckBox checkboxEnabled;
- CheckBox checkboxVisible;
- ImageView settings;
- }
-
- @NonNull
- @Override
- public View getView(int position, View view, @NonNull ViewGroup parent) {
-
- PluginViewHolder holder;
- PluginBase plugin = pluginList.get(position);
-
- if (view == null) {
- view = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null);
-
- holder = new PluginViewHolder();
- holder.name = (TextView) view.findViewById(R.id.configbuilder_simpleitem_name);
- holder.checkboxEnabled = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxenabled);
- holder.checkboxVisible = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxvisible);
- holder.settings = (ImageView) view.findViewById(R.id.configbuilder_simpleitem_settings);
-
- if (plugin.isEnabled(type) && plugin.getPreferencesId() != -1)
- holder.settings.setVisibility(View.VISIBLE);
- else
- holder.settings.setVisibility(View.INVISIBLE);
-
- view.setTag(holder);
-
- holder.checkboxEnabled.setOnClickListener(v -> {
- CheckBox cb = (CheckBox) v;
- PluginBase plugin1 = (PluginBase) cb.getTag();
- plugin1.setPluginEnabled(type, cb.isChecked());
- plugin1.setFragmentVisible(type, cb.isChecked());
- onEnabledCategoryChanged(plugin1, type);
- ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
- MainApp.bus().post(new EventRefreshGui());
- MainApp.bus().post(new EventConfigBuilderChange());
- ConfigBuilderPlugin.getPlugin().logPluginStatus();
- FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
- });
-
- holder.checkboxVisible.setOnClickListener(v -> {
- CheckBox cb = (CheckBox) v;
- PluginBase plugin12 = (PluginBase) cb.getTag();
- plugin12.setFragmentVisible(type, cb.isChecked());
- ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
- MainApp.bus().post(new EventRefreshGui());
- ConfigBuilderPlugin.getPlugin().logPluginStatus();
- });
-
- holder.settings.setOnClickListener(v -> {
- final PluginBase plugin13 = (PluginBase) v.getTag();
- PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
- Intent i = new Intent(getContext(), PreferencesActivity.class);
- i.putExtra("id", plugin13.getPreferencesId());
- startActivity(i);
- }, null);
- });
-
- holder.name.setOnLongClickListener(v -> {
- final PluginBase plugin14 = (PluginBase) v.getTag();
- PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
- Intent i = new Intent(getContext(), PreferencesActivity.class);
- i.putExtra("id", plugin14.getPreferencesId());
- startActivity(i);
- }, null);
- return false;
- });
-
- } else {
- holder = (PluginViewHolder) view.getTag();
- }
-
- holder.name.setText(plugin.getName());
- holder.checkboxEnabled.setChecked(plugin.isEnabled(type));
- holder.checkboxVisible.setChecked(plugin.isFragmentVisible());
- holder.name.setTag(plugin);
- holder.checkboxEnabled.setTag(plugin);
- holder.checkboxVisible.setTag(plugin);
- holder.settings.setTag(plugin);
-
- if (plugin.pluginDescription.alwaysEnabled) {
- holder.checkboxEnabled.setEnabled(false);
- }
-
- if (plugin.pluginDescription.alwayVisible) {
- holder.checkboxEnabled.setEnabled(false);
- }
-
- if (!plugin.isEnabled(type)) {
- holder.checkboxVisible.setEnabled(false);
- }
-
- if (!plugin.hasFragment()) {
- holder.checkboxVisible.setVisibility(View.INVISIBLE);
- }
-
- // Hide enabled control and force enabled plugin if there is only one plugin available
- if (type == PluginType.INSULIN || type == PluginType.PUMP || type == PluginType.SENSITIVITY)
- if (pluginList.size() < 2) {
- holder.checkboxEnabled.setEnabled(false);
- plugin.setPluginEnabled(type, true);
- ConfigBuilderPlugin.getPlugin().storeSettings("ForceEnable");
- }
-
- // Constraints cannot be disabled
- if (type == PluginType.CONSTRAINTS)
- holder.checkboxEnabled.setEnabled(false);
-
- // Hide disabled profiles by default
- if (type == PluginType.PROFILE) {
- if (!plugin.isEnabled(type)) {
- holder.checkboxVisible.setEnabled(false);
- holder.checkboxVisible.setChecked(false);
- } else {
- holder.checkboxVisible.setEnabled(true);
- }
- }
-
- // Disable profile control for pump profiles if pump is not enabled
- if (type == PluginType.PROFILE) {
- if (PumpInterface.class.isAssignableFrom(plugin.getClass())) {
- if (!plugin.isEnabled(PluginType.PUMP)) {
- holder.checkboxEnabled.setEnabled(false);
- holder.checkboxEnabled.setChecked(false);
- }
- }
- }
-
- if (plugin.isEnabled(type)) {
- view.setBackgroundColor(MainApp.gc(R.color.configBuilderSelectedBackground));
- }
-
- return view;
-
- }
-
+ private void createViews() {
+ createViewsForPlugins(R.string.configbuilder_profile, R.string.configbuilder_profile_description, PluginType.PROFILE, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE));
+ createViewsForPlugins(R.string.configbuilder_insulin, R.string.configbuilder_insulin_description, PluginType.INSULIN, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN));
+ createViewsForPlugins(R.string.configbuilder_bgsource, R.string.configbuilder_bgsource_description, PluginType.BGSOURCE, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE));
+ createViewsForPlugins(R.string.configbuilder_pump, R.string.configbuilder_pump_description, PluginType.PUMP, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP));
+ createViewsForPlugins(R.string.configbuilder_sensitivity, R.string.configbuilder_sensitivity_description, PluginType.SENSITIVITY, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY));
+ createViewsForPlugins(R.string.configbuilder_aps, R.string.configbuilder_aps_description, PluginType.APS, MainApp.getSpecificPluginsVisibleInList(PluginType.APS));
+ createViewsForPlugins(R.string.configbuilder_loop, R.string.configbuilder_loop_description, PluginType.LOOP, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP));
+ createViewsForPlugins(R.string.constraints, R.string.configbuilder_constraints_description, PluginType.CONSTRAINTS, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS));
+ createViewsForPlugins(R.string.configbuilder_treatments, R.string.configbuilder_treatments_description, PluginType.TREATMENT, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT));
+ createViewsForPlugins(R.string.configbuilder_general, R.string.configbuilder_general_description, PluginType.GENERAL, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL));
}
- void onEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
+ private void createViewsForPlugins(@StringRes int title, @StringRes int description, PluginType pluginType, List plugins) {
+ if (plugins.size() == 0) return;
+ LinearLayout parent = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_category, null);
+ ((TextView) parent.findViewById(R.id.category_title)).setText(MainApp.gs(title));
+ ((TextView) parent.findViewById(R.id.category_description)).setText(MainApp.gs(description));
+ LinearLayout pluginContainer = parent.findViewById(R.id.category_plugins);
+ for (PluginBase plugin: plugins) {
+ PluginViewHolder pluginViewHolder = new PluginViewHolder(pluginType, plugin);
+ pluginContainer.addView(pluginViewHolder.getBaseView());
+ pluginViewHolders.add(pluginViewHolder);
+ }
+ categories.addView(parent);
+ }
+
+ private boolean areMultipleSelectionsAllowed(PluginType type) {
+ return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS ||type == PluginType.LOOP;
+ }
+
+ public static void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) {
ArrayList pluginsInCategory = null;
switch (type) {
// Multiple selection allowed
@@ -391,34 +184,103 @@ public class ConfigBuilderFragment extends SubscriberFragment {
else
pluginsInCategory.get(0).setPluginEnabled(type, true);
}
- updateGUI();
}
}
- /****
- * Method for Setting the Height of the ListView dynamically.
- * *** Hack to fix the issue of not showing all the items of the ListView
- * *** when placed inside a ScrollView
- ****/
- public static void setListViewHeightBasedOnChildren(ListView listView) {
- ListAdapter listAdapter = listView.getAdapter();
- if (listAdapter == null)
- return;
+ public class PluginViewHolder {
- int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED);
- int totalHeight = 0;
- View view = null;
- for (int i = 0; i < listAdapter.getCount(); i++) {
- view = listAdapter.getView(i, view, listView);
- if (i == 0)
- view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
+ private Unbinder unbinder;
+ private PluginType pluginType;
+ private PluginBase plugin;
- view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
- totalHeight += view.getMeasuredHeight();
+ LinearLayout baseView;
+ @BindView(R.id.plugin_enabled_exclusive)
+ RadioButton enabledExclusive;
+ @BindView(R.id.plugin_enabled_inclusive)
+ CheckBox enabledInclusive;
+ @BindView(R.id.plugin_name)
+ TextView pluginName;
+ @BindView(R.id.plugin_description)
+ TextView pluginDescription;
+ @BindView(R.id.plugin_preferences)
+ ImageButton pluginPreferences;
+ @BindView(R.id.plugin_visibility)
+ CheckBox pluginVisibility;
+
+ public PluginViewHolder(PluginType pluginType, PluginBase plugin) {
+ this.pluginType = pluginType;
+ this.plugin = plugin;
+ baseView = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_plugin, null);
+ unbinder = ButterKnife.bind(this, baseView);
+ update();
}
- ViewGroup.LayoutParams params = listView.getLayoutParams();
- params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
- listView.setLayoutParams(params);
- }
+ public LinearLayout getBaseView() {
+ return baseView;
+ }
+
+ public void update() {
+ enabledExclusive.setVisibility(areMultipleSelectionsAllowed(pluginType) ? View.GONE : View.VISIBLE);
+ enabledInclusive.setVisibility(areMultipleSelectionsAllowed(pluginType) ? View.VISIBLE : View.GONE);
+ enabledExclusive.setChecked(plugin.isEnabled(pluginType));
+ enabledInclusive.setChecked(plugin.isEnabled(pluginType));
+ enabledInclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled);
+ enabledExclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled);
+ pluginName.setText(plugin.getName());
+ if (plugin.getDescription() == null) pluginDescription.setVisibility(View.GONE);
+ else {
+ pluginDescription.setVisibility(View.VISIBLE);
+ pluginDescription.setText(plugin.getDescription());
+ }
+ pluginPreferences.setVisibility(plugin.getPreferencesId() == -1 || !plugin.isEnabled(pluginType) ? View.INVISIBLE : View.VISIBLE);
+ pluginVisibility.setVisibility(plugin.hasFragment() ? View.VISIBLE : View.INVISIBLE);
+ pluginVisibility.setEnabled(!(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwayVisible) && plugin.isEnabled(pluginType));
+ pluginVisibility.setChecked(plugin.isFragmentVisible());
+ }
+
+ @OnClick(R.id.plugin_visibility)
+ void onVisibilityChanged() {
+ plugin.setFragmentVisible(pluginType, pluginVisibility.isChecked());
+ ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible");
+ MainApp.bus().post(new EventRefreshGui());
+ ConfigBuilderPlugin.getPlugin().logPluginStatus();
+ }
+
+ @OnClick({R.id.plugin_enabled_exclusive, R.id.plugin_enabled_inclusive})
+ void onEnabledChanged() {
+ plugin.switchAllowed(new PluginSwitcher(), getActivity());
+ }
+
+ @OnClick(R.id.plugin_preferences)
+ void onPluginPreferencesClicked() {
+ PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(getContext(), PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ startActivity(i);
+ }, null);
+ }
+
+ public void unbind() {
+ unbinder.unbind();
+ }
+
+ public class PluginSwitcher {
+ public void invoke() {
+ boolean enabled = enabledExclusive.getVisibility() == View.VISIBLE ? enabledExclusive.isChecked() : enabledInclusive.isChecked();
+ plugin.setPluginEnabled(pluginType, enabled);
+ plugin.setFragmentVisible(pluginType, enabled);
+ processOnEnabledCategoryChanged(plugin, pluginType);
+ updateGUI();
+ ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled");
+ MainApp.bus().post(new EventRefreshGui());
+ MainApp.bus().post(new EventConfigBuilderChange());
+ ConfigBuilderPlugin.getPlugin().logPluginStatus();
+ FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange"));
+ }
+
+ public void cancel(){
+ updateGUI();
+ }
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java
index 35130c5209..886eeb3db7 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java
@@ -43,7 +43,7 @@ import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.utils.FabricPrivacy;
@@ -87,11 +87,12 @@ public class ConfigBuilderPlugin extends PluginBase {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(ConfigBuilderFragment.class.getName())
- .showInList(false)
+ .showInList(true)
.alwaysEnabled(true)
- .alwayVisible(true)
+ .alwayVisible(false)
.pluginName(R.string.configbuilder)
.shortName(R.string.configbuilder_shortname)
+ .description(R.string.description_config_builder)
);
}
@@ -112,9 +113,17 @@ public class ConfigBuilderPlugin extends PluginBase {
pluginList = MainApp.getPluginsList();
upgradeSettings();
loadSettings();
+ setAlwaysEnabledPluginsEnabled();
MainApp.bus().post(new EventAppInitialized());
}
+ private void setAlwaysEnabledPluginsEnabled() {
+ for (PluginBase plugin : pluginList) {
+ if (plugin.pluginDescription.alwaysEnabled) plugin.setPluginEnabled(plugin.getType(), true);
+ }
+ storeSettings("setAlwaysEnabledPluginsEnabled");
+ }
+
public void storeSettings(String from) {
if (pluginList != null) {
if (Config.logPrefsChange)
@@ -519,6 +528,7 @@ public class ConfigBuilderPlugin extends PluginBase {
// deliver SMB
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
+ detailedBolusInfo.lastKnownBolusTime = activeTreatments.getLastBolusTime();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = request.smb;
detailedBolusInfo.isSMB = true;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java
index 1424013440..2f896ba91b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java
@@ -1,12 +1,18 @@
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
+import android.animation.LayoutTransition;
import android.app.Activity;
-import android.content.Context;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
+import android.text.Html;
+import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -16,203 +22,40 @@ import android.widget.LinearLayout;
import android.widget.TextView;
+import com.squareup.otto.Subscribe;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
-import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventConfigBuilderChange;
+import info.nightscout.androidaps.events.EventNewBG;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
+import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective;
import info.nightscout.utils.FabricPrivacy;
-import info.nightscout.utils.T;
public class ObjectivesFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class);
RecyclerView recyclerView;
- LinearLayoutManager llm;
CheckBox enableFake;
- LinearLayout fake_layout;
TextView reset;
+ ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter();
+ Handler handler = new Handler(Looper.getMainLooper());
- public class RecyclerViewAdapter extends RecyclerView.Adapter {
-
- List objectives;
-
- RecyclerViewAdapter(List objectives) {
- this.objectives = objectives;
- }
-
+ private Runnable objectiveUpdater = new Runnable() {
@Override
- public ObjectiveViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
- View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.objectives_item, viewGroup, false);
- return new ObjectiveViewHolder(v);
+ public void run() {
+ handler.postDelayed(this, 60 * 1000);
+ updateGUI();
}
-
- @Override
- public void onBindViewHolder(ObjectiveViewHolder holder, int position) {
- ObjectivesPlugin.Objective o = objectives.get(position);
- ObjectivesPlugin.RequirementResult requirementsMet = ObjectivesPlugin.getPlugin().requirementsMet(position);
- Context context = MainApp.instance().getApplicationContext();
- holder.position.setText(String.valueOf(position + 1));
- holder.objective.setText(o.objective);
- holder.gate.setText(o.gate);
- holder.duration.setText(MainApp.gs(R.string.objectives_minimalduration) + " " + o.durationInDays + " " + MainApp.gs(R.string.days));
- holder.progress.setText(requirementsMet.comment);
- holder.started.setText(o.started.toLocaleString());
- holder.accomplished.setText(o.accomplished.toLocaleString());
-
- holder.startButton.setTag(o);
- holder.verifyButton.setTag(o);
-
- holder.startButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag();
- o.started = new Date();
- updateGUI();
- ObjectivesPlugin.saveProgress();
- }
- });
- holder.verifyButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- ObjectivesPlugin.Objective o = (ObjectivesPlugin.Objective) v.getTag();
- if (ObjectivesPlugin.getPlugin().requirementsMet(o.num).done || enableFake.isChecked()) {
- o.accomplished = new Date();
- updateGUI();
- ObjectivesPlugin.saveProgress();
- }
- }
- });
-
- long prevObjectiveAccomplishedTime = position > 0 ?
- objectives.get(position - 1).accomplished.getTime() : -1;
-
- int phase = modifyVisibility(position, prevObjectiveAccomplishedTime,
- o.started.getTime(), o.durationInDays,
- o.accomplished.getTime(), requirementsMet.done, enableFake.isChecked());
-
- switch (phase) {
- case 0:
- // Phase 0: previous not completed
- holder.startedLayout.setVisibility(View.GONE);
- holder.durationLayout.setVisibility(View.GONE);
- holder.progressLayout.setVisibility(View.GONE);
- holder.verifyLayout.setVisibility(View.GONE);
- break;
- case 1:
- // Phase 1: not started
- holder.durationLayout.setVisibility(View.GONE);
- holder.progressLayout.setVisibility(View.GONE);
- holder.verifyLayout.setVisibility(View.GONE);
- holder.started.setVisibility(View.GONE);
- break;
- case 2:
- // Phase 2: started, waiting for duration and met requirements
- holder.startButton.setEnabled(false);
- holder.verifyLayout.setVisibility(View.GONE);
- break;
- case 3:
- // Phase 3: started, after duration, requirements met
- holder.startButton.setEnabled(false);
- holder.accomplished.setVisibility(View.INVISIBLE);
- break;
- case 4:
- // Phase 4: verified
- holder.gateLayout.setVisibility(View.GONE);
- holder.startedLayout.setVisibility(View.GONE);
- holder.durationLayout.setVisibility(View.GONE);
- holder.progressLayout.setVisibility(View.GONE);
- holder.verifyButton.setVisibility(View.INVISIBLE);
- break;
- default:
- // should not happen
- }
- }
-
-
- @Override
- public int getItemCount() {
- return objectives.size();
- }
-
- @Override
- public void onAttachedToRecyclerView(RecyclerView recyclerView) {
- super.onAttachedToRecyclerView(recyclerView);
- }
-
- public class ObjectiveViewHolder extends RecyclerView.ViewHolder {
- CardView cv;
- TextView position;
- TextView objective;
- LinearLayout gateLayout;
- TextView gate;
- TextView duration;
- LinearLayout durationLayout;
- TextView progress;
- LinearLayout progressLayout;
- TextView started;
- Button startButton;
- LinearLayout startedLayout;
- TextView accomplished;
- Button verifyButton;
- LinearLayout verifyLayout;
-
- ObjectiveViewHolder(View itemView) {
- super(itemView);
- cv = (CardView) itemView.findViewById(R.id.objectives_cardview);
- position = (TextView) itemView.findViewById(R.id.objectives_position);
- objective = (TextView) itemView.findViewById(R.id.objectives_objective);
- durationLayout = (LinearLayout) itemView.findViewById(R.id.objectives_duration_linearlayout);
- duration = (TextView) itemView.findViewById(R.id.objectives_duration);
- progressLayout = (LinearLayout) itemView.findViewById(R.id.objectives_progresslayout);
- progress = (TextView) itemView.findViewById(R.id.objectives_progress);
- gateLayout = (LinearLayout) itemView.findViewById(R.id.objectives_gate_linearlayout);
- gate = (TextView) itemView.findViewById(R.id.objectives_gate);
- startedLayout = (LinearLayout) itemView.findViewById(R.id.objectives_start_linearlayout);
- started = (TextView) itemView.findViewById(R.id.objectives_started);
- startButton = (Button) itemView.findViewById(R.id.objectives_start);
- verifyLayout = (LinearLayout) itemView.findViewById(R.id.objectives_verify_linearlayout);
- accomplished = (TextView) itemView.findViewById(R.id.objectives_accomplished);
- verifyButton = (Button) itemView.findViewById(R.id.objectives_verify);
- }
- }
- }
-
- /**
- * returns an int, which represents the phase the current objective is at.
- *
- * this is mainly used for unit-testing the conditions
- *
- * @param currentPosition
- * @param prevObjectiveAccomplishedTime
- * @param objectiveStartedTime
- * @param durationInDays
- * @param objectiveAccomplishedTime
- * @param requirementsMet
- * @return
- */
- public int modifyVisibility(int currentPosition,
- long prevObjectiveAccomplishedTime,
- long objectiveStartedTime, int durationInDays,
- long objectiveAccomplishedTime, boolean requirementsMet,
- boolean enableFakeValue) {
- Long now = System.currentTimeMillis();
- if (currentPosition > 0 && prevObjectiveAccomplishedTime == 0) {
- return 0;
- } else if (objectiveStartedTime == 0) {
- return 1;
- } else if (objectiveStartedTime > 0 && !enableFakeValue
- && objectiveAccomplishedTime == 0
- && !(objectiveStartedTime + T.days(durationInDays).msecs() < now && requirementsMet)) {
- return 2;
- } else if (objectiveAccomplishedTime == 0) {
- return 3;
- } else {
- return 4;
- }
- }
+ };
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -220,44 +63,20 @@ public class ObjectivesFragment extends SubscriberFragment {
try {
View view = inflater.inflate(R.layout.objectives_fragment, container, false);
- recyclerView = (RecyclerView) view.findViewById(R.id.objectives_recyclerview);
- recyclerView.setHasFixedSize(true);
- llm = new LinearLayoutManager(view.getContext());
- recyclerView.setLayoutManager(llm);
- enableFake = (CheckBox) view.findViewById(R.id.objectives_fake);
- fake_layout = (LinearLayout) view.findViewById(R.id.objectives_fake_layout);
- reset = (TextView) view.findViewById(R.id.objectives_reset);
- enableFake.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- updateGUI();
- }
+ recyclerView = view.findViewById(R.id.objectives_recyclerview);
+ recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
+ recyclerView.setAdapter(objectivesAdapter);
+ enableFake = view.findViewById(R.id.objectives_fake);
+ reset = view.findViewById(R.id.objectives_reset);
+ enableFake.setOnClickListener(v -> updateGUI());
+ reset.setOnClickListener(v -> {
+ ObjectivesPlugin.getPlugin().reset();
+ ObjectivesPlugin.saveProgress();
+ recyclerView.getAdapter().notifyDataSetChanged();
+ scrollToCurrentObjective();
});
- reset.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- ObjectivesPlugin.getPlugin().initializeData();
- ObjectivesPlugin.saveProgress();
- updateGUI();
- }
- });
-
- // Add correct translations to array after app is initialized
- ObjectivesPlugin.objectives.get(0).objective = MainApp.gs(R.string.objectives_0_objective);
- ObjectivesPlugin.objectives.get(1).objective = MainApp.gs(R.string.objectives_1_objective);
- ObjectivesPlugin.objectives.get(2).objective = MainApp.gs(R.string.objectives_2_objective);
- ObjectivesPlugin.objectives.get(3).objective = MainApp.gs(R.string.objectives_3_objective);
- ObjectivesPlugin.objectives.get(4).objective = MainApp.gs(R.string.objectives_4_objective);
- ObjectivesPlugin.objectives.get(5).objective = MainApp.gs(R.string.objectives_5_objective);
- ObjectivesPlugin.objectives.get(6).objective = MainApp.gs(R.string.objectives_6_objective);
- ObjectivesPlugin.objectives.get(7).objective = MainApp.gs(R.string.objectives_7_objective);
- ObjectivesPlugin.objectives.get(0).gate = MainApp.gs(R.string.objectives_0_gate);
- ObjectivesPlugin.objectives.get(1).gate = MainApp.gs(R.string.objectives_1_gate);
- ObjectivesPlugin.objectives.get(2).gate = MainApp.gs(R.string.objectives_2_gate);
- ObjectivesPlugin.objectives.get(3).gate = MainApp.gs(R.string.objectives_3_gate);
- ObjectivesPlugin.objectives.get(4).gate = MainApp.gs(R.string.objectives_4_gate);
- ObjectivesPlugin.objectives.get(5).gate = MainApp.gs(R.string.objectives_5_gate);
-
- updateGUI();
-
+ scrollToCurrentObjective();
+ startUpdateTimer();
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
@@ -266,14 +85,143 @@ public class ObjectivesFragment extends SubscriberFragment {
return null;
}
+ @Override
+ public synchronized void onDestroyView() {
+ super.onDestroyView();
+ handler.removeCallbacks(objectiveUpdater);
+ }
+
+ private void startUpdateTimer() {
+ handler.removeCallbacks(objectiveUpdater);
+ for (Objective objective : ObjectivesPlugin.getObjectives()) {
+ if (objective.isStarted() && !objective.isAccomplished()) {
+ long timeTillNextMinute = (System.currentTimeMillis() - objective.getStartedOn().getTime()) % (60 * 1000);
+ handler.postDelayed(objectiveUpdater, timeTillNextMinute);
+ break;
+ }
+ }
+ }
+
+ private void scrollToCurrentObjective() {
+ for (int i = 0; i < ObjectivesPlugin.getObjectives().size(); i++) {
+ Objective objective = ObjectivesPlugin.getObjectives().get(i);
+ if (!objective.isStarted() || !objective.isAccomplished()) {
+ RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) {
+ @Override
+ protected int getVerticalSnapPreference() {
+ return LinearSmoothScroller.SNAP_TO_START;
+ }
+
+ @Override
+ protected int calculateTimeForScrolling(int dx) {
+ return super.calculateTimeForScrolling(dx) * 4;
+ }
+ };
+ smoothScroller.setTargetPosition(i);
+ recyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
+ break;
+ }
+ }
+ }
+
+ private class ObjectivesAdapter extends RecyclerView.Adapter {
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.objectives_item, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ Objective objective = ObjectivesPlugin.getObjectives().get(position);
+ holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1));
+ if (objective.getObjective() != 0) {
+ holder.objective.setVisibility(View.VISIBLE);
+ holder.objective.setText(MainApp.gs(objective.getObjective()));
+ } else holder.objective.setVisibility(View.GONE);
+ if (objective.getGate() != 0) {
+ holder.gate.setVisibility(View.VISIBLE);
+ holder.gate.setText(MainApp.gs(objective.getGate()));
+ } else holder.gate.setVisibility(View.GONE);
+ if (!objective.isStarted()) {
+ holder.gate.setTextColor(0xFFFFFFFF);
+ holder.verify.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.GONE);
+ if (position == 0 || ObjectivesPlugin.getObjectives().get(position - 1).isAccomplished())
+ holder.start.setVisibility(View.VISIBLE);
+ else holder.start.setVisibility(View.GONE);
+ } else if (objective.isAccomplished()) {
+ holder.gate.setTextColor(0xFF4CAF50);
+ holder.verify.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.GONE);
+ holder.start.setVisibility(View.GONE);
+ } else if (objective.isStarted()) {
+ holder.gate.setTextColor(0xFFFFFFFF);
+ holder.verify.setVisibility(View.VISIBLE);
+ holder.verify.setEnabled(objective.isCompleted() || enableFake.isChecked());
+ holder.start.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.VISIBLE);
+ holder.progress.removeAllViews();
+ for (Objective.Task task : objective.getTasks()) {
+ if (task.shouldBeIgnored()) continue;
+ TextView textView = new TextView(holder.progress.getContext());
+ textView.setTextColor(0xFFFFFFFF);
+ String basicHTML = "%2$s: %3$s";
+ String formattedHTML = String.format(basicHTML, task.isCompleted() ? "#4CAF50" : "#FF9800", MainApp.gs(task.getTask()), task.getProgress());
+ textView.setText(Html.fromHtml(formattedHTML));
+ holder.progress.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ }
+ }
+ holder.verify.setOnClickListener((view) -> {
+ objective.setAccomplishedOn(new Date());
+ notifyDataSetChanged();
+ scrollToCurrentObjective();
+ startUpdateTimer();
+ });
+ holder.start.setOnClickListener((view) -> {
+ objective.setStartedOn(new Date());
+ notifyDataSetChanged();
+ scrollToCurrentObjective();
+ startUpdateTimer();
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return ObjectivesPlugin.getObjectives().size();
+ }
+
+ public class ViewHolder extends RecyclerView.ViewHolder {
+
+ public CardView cardView;
+ public TextView title;
+ public TextView objective;
+ public TextView gate;
+ public LinearLayout progress;
+ public Button verify;
+ public Button start;
+
+ public ViewHolder(View itemView) {
+ super(itemView);
+ cardView = (CardView) itemView;
+ title = itemView.findViewById(R.id.objective_title);
+ objective = itemView.findViewById(R.id.objective_objective);
+ gate = itemView.findViewById(R.id.objective_gate);
+ progress = itemView.findViewById(R.id.objective_progress);
+ verify = itemView.findViewById(R.id.objective_verify);
+ start = itemView.findViewById(R.id.objective_start);
+ }
+ }
+ }
+
@Override
public void updateGUI() {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(ObjectivesPlugin.objectives);
- recyclerView.setAdapter(adapter);
+ objectivesAdapter.notifyDataSetChanged();
});
}
-}
\ No newline at end of file
+}
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 5a899bebe5..a67f694eb8 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java
@@ -1,20 +1,14 @@
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.db.DatabaseHelper;
-import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
@@ -22,12 +16,16 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
-import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
-import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
-import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
-import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
-import info.nightscout.utils.DateUtil;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective1;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective2;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective3;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective4;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective5;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective6;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective7;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives.Objective8;
import info.nightscout.utils.SP;
/**
@@ -38,6 +36,11 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
private static ObjectivesPlugin objectivesPlugin;
+ public static List objectives = new ArrayList<>();
+ public static boolean bgIsAvailableInNS = false;
+ public static boolean pumpStatusIsAvailableInNS = false;
+ public static Integer manualEnacts = 0;
+
public static ObjectivesPlugin getPlugin() {
if (objectivesPlugin == null) {
objectivesPlugin = new ObjectivesPlugin();
@@ -45,8 +48,6 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
return objectivesPlugin;
}
- public static List objectives;
-
private ObjectivesPlugin() {
super(new PluginDescription()
.mainType(PluginType.CONSTRAINTS)
@@ -55,8 +56,9 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
.showInList(!Config.NSCLIENT && !Config.G5UPLOADER)
.pluginName(R.string.objectives)
.shortName(R.string.objectives_shortname)
+ .description(R.string.description_objectives)
);
- initializeData();
+ setupObjectives();
loadProgress();
}
@@ -66,186 +68,38 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
return pump == null || pump.getPumpDescription().isTempBasalCapable;
}
- public class Objective {
- Integer num;
- String objective;
- String gate;
- Date started;
- Integer durationInDays;
- Date accomplished;
-
- Objective(Integer num, String objective, String gate, Date started, Integer durationInDays, Date accomplished) {
- this.num = num;
- this.objective = objective;
- this.gate = gate;
- this.started = started;
- this.durationInDays = durationInDays;
- this.accomplished = accomplished;
- }
-
- public void setStarted(Date started) {
- this.started = started;
- }
-
- boolean isStarted() {
- return started.getTime() > 0;
- }
-
- boolean isFinished() {
- return accomplished.getTime() != 0;
- }
+ private void setupObjectives() {
+ objectives.add(new Objective1());
+ objectives.add(new Objective2());
+ objectives.add(new Objective3());
+ objectives.add(new Objective4());
+ objectives.add(new Objective5());
+ objectives.add(new Objective6());
+ objectives.add(new Objective7());
+ objectives.add(new Objective8());
}
- // Objective 0
- public static boolean bgIsAvailableInNS = false;
- public static boolean pumpStatusIsAvailableInNS = false;
- // Objective 1
- public static Integer manualEnacts = 0;
- private static final Integer manualEnactsNeeded = 20;
-
- class RequirementResult {
- boolean done = false;
- String comment = "";
-
- RequirementResult(boolean done, String comment) {
- this.done = done;
- this.comment = comment;
+ public void reset() {
+ for (Objective objective : objectives) {
+ objective.setStartedOn(null);
+ objective.setAccomplishedOn(null);
}
- }
-
- private String yesOrNo(boolean yes) {
- if (yes) return "☺";
- else return "---";
- }
-
- RequirementResult requirementsMet(Integer objNum) {
- switch (objNum) {
- case 0:
- boolean isVirtualPump = VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
- boolean vpUploadEnabled = SP.getBoolean("virtualpump_uploadstatus", false);
- boolean vpUploadNeeded = !isVirtualPump || vpUploadEnabled;
- boolean hasBGData = DatabaseHelper.lastBg() != null;
-
- boolean apsEnabled = false;
- APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
- if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
- apsEnabled = true;
-
- boolean profileSwitchExists = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
-
- return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && apsEnabled && vpUploadNeeded && profileSwitchExists,
- MainApp.gs(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
- + "\n" + MainApp.gs(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientPlugin.getPlugin().hasWritePermission())
- + (isVirtualPump ? "\n" + MainApp.gs(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
- + "\n" + MainApp.gs(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
- + "\n" + MainApp.gs(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
- + "\n" + MainApp.gs(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
- + "\n" + MainApp.gs(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
- + "\n" + MainApp.gs(R.string.activate_profile) + ": " + yesOrNo(profileSwitchExists)
- );
- case 1:
- return new RequirementResult(manualEnacts >= manualEnactsNeeded,
- MainApp.gs(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
- case 2:
- return new RequirementResult(true, "");
- case 3:
- Constraint closedLoopEnabled = new Constraint<>(true);
- SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
- return new RequirementResult(closedLoopEnabled.value(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.value()));
- case 4:
- double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
- boolean maxIobSet = maxIOB > 0;
- return new RequirementResult(maxIobSet, MainApp.gs(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
- default:
- return new RequirementResult(true, "");
- }
- }
-
-
- void initializeData() {
bgIsAvailableInNS = false;
pumpStatusIsAvailableInNS = false;
manualEnacts = 0;
-
- objectives = new ArrayList<>();
- objectives.add(new Objective(0,
- MainApp.gs(R.string.objectives_0_objective),
- MainApp.gs(R.string.objectives_0_gate),
- new Date(0),
- 0, // 0 day
- new Date(0)));
- objectives.add(new Objective(1,
- MainApp.gs(R.string.objectives_1_objective),
- MainApp.gs(R.string.objectives_1_gate),
- new Date(0),
- 7, // 7 days
- new Date(0)));
- objectives.add(new Objective(2,
- MainApp.gs(R.string.objectives_2_objective),
- MainApp.gs(R.string.objectives_2_gate),
- new Date(0),
- 0, // 0 days
- new Date(0)));
- objectives.add(new Objective(3,
- MainApp.gs(R.string.objectives_3_objective),
- MainApp.gs(R.string.objectives_3_gate),
- new Date(0),
- 5, // 5 days
- new Date(0)));
- objectives.add(new Objective(4,
- MainApp.gs(R.string.objectives_4_objective),
- MainApp.gs(R.string.objectives_4_gate),
- new Date(0),
- 1,
- new Date(0)));
- objectives.add(new Objective(5,
- MainApp.gs(R.string.objectives_5_objective),
- MainApp.gs(R.string.objectives_5_gate),
- new Date(0),
- 7,
- new Date(0)));
- objectives.add(new Objective(6,
- MainApp.gs(R.string.objectives_6_objective),
- "",
- new Date(0),
- 28,
- new Date(0)));
- objectives.add(new Objective(7,
- MainApp.gs(R.string.objectives_7_objective),
- "",
- new Date(0),
- 28,
- new Date(0)));
+ saveProgress();
}
public static void saveProgress() {
- if (objectives != null) {
- SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
- SharedPreferences.Editor editor = settings.edit();
- for (int num = 0; num < objectives.size(); num++) {
- Objective o = objectives.get(num);
- editor.putString("Objectives" + num + "started", Long.toString(o.started.getTime()));
- editor.putString("Objectives" + num + "accomplished", Long.toString(o.accomplished.getTime()));
- }
- editor.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS);
- editor.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS);
- editor.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts));
- editor.apply();
- if (Config.logPrefsChange)
- log.debug("Objectives stored");
- }
+ SP.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS);
+ SP.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS);
+ SP.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts));
+ if (Config.logPrefsChange)
+ log.debug("Objectives stored");
+ MainApp.bus().post(new EventObjectivesSaved());
}
private void loadProgress() {
- for (int num = 0; num < objectives.size(); num++) {
- Objective o = objectives.get(num);
- try {
- o.started = new Date(SP.getLong("Objectives" + num + "started", 0L));
- o.accomplished = new Date(SP.getLong("Objectives" + num + "accomplished", 0L));
- } catch (Exception e) {
- log.error("Unhandled exception", e);
- }
- }
bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false);
pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false);
try {
@@ -257,11 +111,15 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
log.debug("Objectives loaded");
}
+ public static List getObjectives() {
+ return objectives;
+ }
+
/**
* Constraints interface
**/
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
if (!objectives.get(0).isStarted())
value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this);
return value;
@@ -297,7 +155,7 @@ public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface
@Override
public Constraint applyMaxIOBConstraints(Constraint maxIob) {
- if (objectives.get(3).isStarted() && !objectives.get(3).isFinished())
+ if (objectives.get(3).isStarted() && !objectives.get(3).isAccomplished())
maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this);
return maxIob;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/events/EventObjectivesSaved.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/events/EventObjectivesSaved.java
new file mode 100644
index 0000000000..1822368cf9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/events/EventObjectivesSaved.java
@@ -0,0 +1,6 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.events;
+
+import info.nightscout.androidaps.events.Event;
+
+public class EventObjectivesSaved extends Event {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java
new file mode 100644
index 0000000000..bba29c5201
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective.java
@@ -0,0 +1,140 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import android.support.annotation.StringRes;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.utils.SP;
+
+public abstract class Objective {
+
+ private int number;
+ @StringRes
+ private int objective;
+ @StringRes
+ private int gate;
+ private Date startedOn;
+ private Date accomplishedOn;
+ private List tasks = new ArrayList<>();
+
+ public Objective(int number, @StringRes int objective, @StringRes int gate) {
+ this.number = number;
+ this.objective = objective;
+ this.gate = gate;
+ startedOn = new Date(SP.getLong("Objectives" + number + "started", 0L));
+ if (startedOn.getTime() == 0L) startedOn = null;
+ accomplishedOn = new Date(SP.getLong("Objectives" + number + "accomplished", 0L));
+ if (accomplishedOn.getTime() == 0L) accomplishedOn = null;
+ setupTasks(tasks);
+ for (Task task : tasks) task.objective = this;
+ }
+
+ public boolean isCompleted() {
+ for (Task task : tasks) {
+ if (!task.shouldBeIgnored() && !task.isCompleted())
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isAccomplished() {
+ return accomplishedOn != null;
+ }
+
+ public boolean isStarted() {
+ return startedOn != null;
+ }
+
+ public Date getStartedOn() {
+ return startedOn;
+ }
+
+ public int getObjective() {
+ return objective;
+ }
+
+ public int getGate() {
+ return gate;
+ }
+
+ public void setStartedOn(Date startedOn) {
+ this.startedOn = startedOn;
+ SP.putLong("Objectives" + number + "started", startedOn == null ? 0 : startedOn.getTime());
+ }
+
+ public void setAccomplishedOn(Date accomplishedOn) {
+ this.accomplishedOn = accomplishedOn;
+ SP.putLong("Objectives" + number + "accomplished", accomplishedOn == null ? 0 : accomplishedOn.getTime());
+ }
+
+ protected void setupTasks(List tasks) {
+
+ }
+
+ public List getTasks() {
+ return tasks;
+ }
+
+ public abstract class Task {
+ @StringRes
+ private int task;
+ private Objective objective;
+
+ public Task(@StringRes int task) {
+ this.task = task;
+ }
+
+ public int getTask() {
+ return task;
+ }
+
+ protected Objective getObjective() {
+ return objective;
+ }
+
+ public abstract boolean isCompleted();
+
+ public String getProgress() {
+ return MainApp.gs(isCompleted() ? R.string.completed_well_done : R.string.not_completed_yet);
+ }
+
+ public boolean shouldBeIgnored() {
+ return false;
+ }
+ }
+
+ public class MinimumDurationTask extends Task {
+
+ private long minimumDuration;
+
+ public MinimumDurationTask(long minimumDuration) {
+ super(R.string.time_elapsed);
+ this.minimumDuration = minimumDuration;
+ }
+
+ @Override
+ public boolean isCompleted() {
+ return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn().getTime() >= minimumDuration;
+ }
+
+ @Override
+ public String getProgress() {
+ return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn().getTime())
+ + " / " + getDurationText(minimumDuration);
+ }
+
+ private String getDurationText(long duration) {
+ int days = (int) Math.floor((double) duration / (24D * 60D * 60D * 1000D));
+ int hours = (int) Math.floor((double) duration / (60D * 60D * 1000D));
+ int minutes = (int) Math.floor((double) duration / (60D * 1000D));
+ if (days > 0) return MainApp.gq(R.plurals.objective_days, days, days);
+ else if (hours > 0) return MainApp.gq(R.plurals.objective_hours, hours, hours);
+ else return MainApp.gq(R.plurals.objective_minutes, minutes, minutes);
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective1.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective1.java
new file mode 100644
index 0000000000..e374126b11
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective1.java
@@ -0,0 +1,84 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.db.DatabaseHelper;
+import info.nightscout.androidaps.interfaces.APSInterface;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
+import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.SP;
+
+public class Objective1 extends Objective {
+
+ public Objective1() {
+ super(0, R.string.objectives_0_objective, R.string.objectives_0_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new Task(R.string.objectives_bgavailableinns) {
+ @Override
+ public boolean isCompleted() {
+ return ObjectivesPlugin.bgIsAvailableInNS;
+ }
+ });
+ tasks.add(new Task(R.string.nsclienthaswritepermission) {
+ @Override
+ public boolean isCompleted() {
+ return NSClientPlugin.getPlugin().hasWritePermission();
+ }
+ });
+ tasks.add(new Task(R.string.virtualpump_uploadstatus_title) {
+ @Override
+ public boolean isCompleted() {
+ return SP.getBoolean("virtualpump_uploadstatus", false);
+ }
+
+ @Override
+ public boolean shouldBeIgnored() {
+ return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP);
+ }
+ });
+ tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) {
+ @Override
+ public boolean isCompleted() {
+ return ObjectivesPlugin.pumpStatusIsAvailableInNS;
+ }
+ });
+ tasks.add(new Task(R.string.hasbgdata) {
+ @Override
+ public boolean isCompleted() {
+ return DatabaseHelper.lastBg() != null;
+ }
+ });
+ tasks.add(new Task(R.string.loopenabled) {
+ @Override
+ public boolean isCompleted() {
+ return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP);
+ }
+ });
+ tasks.add(new Task(R.string.apsselected) {
+ @Override
+ public boolean isCompleted() {
+ APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
+ if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS))
+ return true;
+ return false;
+ }
+ });
+ tasks.add(new Task(R.string.activate_profile) {
+ @Override
+ public boolean isCompleted() {
+ return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null;
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java
new file mode 100644
index 0000000000..305f00ec6f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective2.java
@@ -0,0 +1,33 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+
+public class Objective2 extends Objective {
+
+ public static final int MANUAL_ENACTS_NEEDED = 20;
+
+ public Objective2() {
+ super(1, R.string.objectives_1_objective, R.string.objectives_1_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(7L * 24L * 60L * 60L * 1000L));
+ tasks.add(new Task(R.string.objectives_manualenacts) {
+ @Override
+ public boolean isCompleted() {
+ return ObjectivesPlugin.manualEnacts >= MANUAL_ENACTS_NEEDED;
+ }
+
+ @Override
+ public String getProgress() {
+ if (ObjectivesPlugin.manualEnacts >= MANUAL_ENACTS_NEEDED) return MainApp.gs(R.string.completed_well_done);
+ else return ObjectivesPlugin.manualEnacts + " / " + MANUAL_ENACTS_NEEDED;
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java
new file mode 100644
index 0000000000..8a84e3c83c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective3.java
@@ -0,0 +1,10 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import info.nightscout.androidaps.R;
+
+public class Objective3 extends Objective {
+
+ public Objective3() {
+ super(2, R.string.objectives_2_objective, R.string.objectives_2_gate);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective4.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective4.java
new file mode 100644
index 0000000000..36a98babc1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective4.java
@@ -0,0 +1,27 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.Constraint;
+import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
+
+public class Objective4 extends Objective {
+
+ public Objective4() {
+ super(3, R.string.objectives_3_objective, R.string.objectives_3_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(5L * 24L * 60L * 60L * 1000L));
+ tasks.add(new Task(R.string.closedmodeenabled) {
+ @Override
+ public boolean isCompleted() {
+ Constraint closedLoopEnabled = new Constraint<>(true);
+ SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
+ return closedLoopEnabled.value();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective5.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective5.java
new file mode 100644
index 0000000000..563a114e05
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective5.java
@@ -0,0 +1,25 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+
+public class Objective5 extends Objective {
+
+ public Objective5() {
+ super(4, R.string.objectives_4_objective, R.string.objectives_4_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(24L * 60L * 60L * 1000L));
+ tasks.add(new Task(R.string.maxiobset) {
+ @Override
+ public boolean isCompleted() {
+ double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value();
+ return maxIOB > 0;
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java
new file mode 100644
index 0000000000..7106d7522b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective6.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+
+public class Objective6 extends Objective {
+
+ public Objective6() {
+ super(5, R.string.objectives_5_objective, R.string.objectives_5_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(7L * 24L * 60L * 60L * 1000L));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java
new file mode 100644
index 0000000000..cfd041bf13
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective7.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+
+public class Objective7 extends Objective {
+
+ public Objective7() {
+ super(6, R.string.objectives_6_objective, 0);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(28L * 24L * 60L * 60L * 1000L));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective8.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective8.java
new file mode 100644
index 0000000000..376d5fb7a2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/objectives/Objective8.java
@@ -0,0 +1,17 @@
+package info.nightscout.androidaps.plugins.ConstraintsObjectives.objectives;
+
+import java.util.List;
+
+import info.nightscout.androidaps.R;
+
+public class Objective8 extends Objective {
+
+ public Objective8() {
+ super(7, R.string.objectives_7_objective, R.string.objectives_7_gate);
+ }
+
+ @Override
+ protected void setupTasks(List tasks) {
+ tasks.add(new MinimumDurationTask(28L * 24L * 60L * 60L * 1000L));
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
index 6a9613e92a..3d17970edc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java
@@ -49,7 +49,7 @@ public class SafetyPlugin extends PluginBase implements ConstraintsInterface {
* Constraints interface
**/
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
if (!ConfigBuilderPlugin.getActivePump().getPumpDescription().isTempBasalCapable)
value.set(false, MainApp.gs(R.string.pumpisnottempbasalcapable), this);
return value;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java
index 14eb318af4..84996f1a37 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Food/FoodPlugin.java
@@ -26,6 +26,7 @@ public class FoodPlugin extends PluginBase {
.fragmentClass(FoodFragment.class.getName())
.pluginName(R.string.food)
.shortName(R.string.food_short)
+ .description(R.string.description_food)
);
this.service = new FoodService();
}
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 2c46cd7bb6..5d4d1187ac 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
@@ -29,6 +29,7 @@ public abstract class InsulinOrefBasePlugin extends PluginBase implements Insuli
.fragmentClass(InsulinFragment.class.getName())
.pluginName(R.string.fastactinginsulin)
.shortName(R.string.insulin_shortname)
+ .visibleByDefault(false)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java
index a710f742a7..c1fc44438f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefFreePeakPlugin.java
@@ -24,7 +24,8 @@ public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin {
super();
pluginDescription
.pluginName(R.string.free_peak_oref)
- .preferencesId(R.xml.pref_insulinoreffreepeak);
+ .preferencesId(R.xml.pref_insulinoreffreepeak)
+ .description(R.string.description_insulin_free_peak);
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java
index a8f9761771..c275aef3fd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefRapidActingPlugin.java
@@ -22,7 +22,8 @@ public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin {
private InsulinOrefRapidActingPlugin() {
super();
pluginDescription
- .pluginName(R.string.rapid_acting_oref);
+ .pluginName(R.string.rapid_acting_oref)
+ .description(R.string.description_insulin_rapid);
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java
index ba5fc99011..94e5910470 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefUltraRapidActingPlugin.java
@@ -22,7 +22,8 @@ public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin {
private InsulinOrefUltraRapidActingPlugin() {
super();
pluginDescription
- .pluginName(R.string.ultrarapid_oref);
+ .pluginName(R.string.ultrarapid_oref)
+ .description(R.string.description_insulin_ultra_rapid);
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
index 79ab63e2ac..dd2c50d8c9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java
@@ -16,8 +16,8 @@ import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries;
import info.nightscout.androidaps.plugins.Overview.graphExtensions.Scale;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.utils.SP;
@@ -26,7 +26,7 @@ import info.nightscout.utils.SP;
*/
public class AutosensData implements DataPointWithLabelInterface {
- private static Logger log = LoggerFactory.getLogger(AutosensData.class);
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
public void setChartTime(long chartTime) {
this.chartTime = chartTime;
@@ -56,11 +56,11 @@ public class AutosensData implements DataPointWithLabelInterface {
}
public long time = 0L;
- long chartTime;
+ public double bg = 0; // mgdl
+ private long chartTime;
public String pastSensitivity = "";
public double deviation = 0d;
- boolean nonCarbsDeviation = false;
- public boolean nonEqualDeviation = false;
+ public boolean validDeviation = false;
List activeCarbsList = new ArrayList<>();
double absorbed = 0d;
public double carbsFromBolus = 0d;
@@ -70,15 +70,23 @@ public class AutosensData implements DataPointWithLabelInterface {
public double avgDelta = 0d;
public double avgDeviation = 0d;
- public double autosensRatio = 1d;
+ public AutosensResult autosensResult = new AutosensResult();
public double slopeFromMaxDeviation = 0;
public double slopeFromMinDeviation = 999;
public double usedMinCarbsImpact = 0d;
public boolean failoverToMinAbsorbtionRate = false;
+ // Oref1
+ public boolean absorbing = false;
+ public double mealCarbs = 0;
+ public int mealStartCounter = 999;
+ public String type = "";
+ public boolean uam = false;
+ public List extraDeviation = new ArrayList<>();
+
@Override
public String toString() {
- return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation =" + slopeFromMinDeviation;
+ return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " avgDelta=" + avgDelta + " Bgi=" + bgi + " Deviation=" + deviation + " avgDeviation=" + avgDeviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensResult.ratio + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation;
}
public int minOld() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java
index 4e0f8ef107..c83095e620 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java
@@ -9,12 +9,12 @@ import org.slf4j.LoggerFactory;
* Created by mike on 06.01.2017.
*/
public class AutosensResult {
- private static Logger log = LoggerFactory.getLogger(AutosensResult.class);
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
//default values to show when autosens algorithm is not called
public double ratio = 1d;
public double carbsAbsorbed = 0d;
- public String sensResult = "autosens deactivated";
+ public String sensResult = "autosens not available";
public String pastSensitivity = "";
public String ratioLimit = "";
@@ -32,4 +32,8 @@ public class AutosensResult {
return ret;
}
+ @Override
+ public String toString() {
+ return json().toString();
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
index 89d66fd891..096668b996 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java
@@ -35,9 +35,11 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.T;
import static info.nightscout.utils.DateUtil.now;
@@ -46,7 +48,7 @@ import static info.nightscout.utils.DateUtil.now;
*/
public class IobCobCalculatorPlugin extends PluginBase {
- private Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
+ private Logger log = LoggerFactory.getLogger("AUTOSENS");
private static IobCobCalculatorPlugin plugin = null;
@@ -68,7 +70,7 @@ public class IobCobCalculatorPlugin extends PluginBase {
final Object dataLock = new Object();
boolean stopCalculationTrigger = false;
- private IobCobThread thread = null;
+ private Thread thread = null;
public IobCobCalculatorPlugin() {
super(new PluginDescription()
@@ -130,11 +132,15 @@ public class IobCobCalculatorPlugin extends PluginBase {
public static long roundUpTime(long time) {
if (time % 60000 == 0)
return time;
- long rouded = (time / 60000 + 1) * 60000;
- return rouded;
+ long rounded = (time / 60000 + 1) * 60000;
+ return rounded;
}
void loadBgData(long start) {
+ if (start < oldestDataAvailable()) {
+ start = oldestDataAvailable();
+ log.debug("Limiting BG data to oldest data available: " + DateUtil.dateAndTimeString(start));
+ }
bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (start - 60 * 60 * 1000L * (24 + dia)), false);
log.debug("BG data loaded. Size: " + bgReadings.size() + " Start date: " + DateUtil.dateAndTimeString(start));
}
@@ -292,7 +298,7 @@ public class IobCobCalculatorPlugin extends PluginBase {
long now = System.currentTimeMillis();
long oldestDataAvailable = TreatmentsPlugin.getPlugin().oldestDataAvailable();
- long getBGDataFrom = Math.max(oldestDataAvailable, (long) (now - 60 * 60 * 1000L * (24 + MainApp.getConfigBuilder().getProfile().getDia())));
+ long getBGDataFrom = Math.max(oldestDataAvailable, (long) (now - T.hours(1).msecs() * (24 + MainApp.getConfigBuilder().getProfile().getDia())));
log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString());
return getBGDataFrom;
}
@@ -347,13 +353,12 @@ public class IobCobCalculatorPlugin extends PluginBase {
return null;
}
- public BasalData getBasalData(long time) {
+ public BasalData getBasalData(Profile profile, long time) {
long now = System.currentTimeMillis();
time = roundUpTime(time);
BasalData retval = basalDataTable.get(time);
if (retval == null) {
retval = new BasalData();
- Profile profile = MainApp.getConfigBuilder().getProfile(time);
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(time);
retval.basal = profile.getBasal(time);
if (tb != null) {
@@ -377,22 +382,20 @@ public class IobCobCalculatorPlugin extends PluginBase {
public AutosensData getAutosensData(long time) {
synchronized (dataLock) {
long now = System.currentTimeMillis();
- if (time > now)
+ if (time > now) {
return null;
+ }
Long previous = findPreviousTimeFromBucketedData(time);
- if (previous == null)
+ if (previous == null) {
return null;
+ }
time = roundUpTime(previous);
AutosensData data = autosensDataTable.get(time);
if (data != null) {
- //log.debug(">>> getAutosensData Cache hit " + data.log(time));
+ //log.debug(">>> AUTOSENSDATA Cache hit " + data.toString());
return data;
} else {
- if (time > now) {
- // data may not be calculated yet, use last data
- return getLastAutosensData("getAutosensData");
- }
- //log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString());
+ //log.debug(">>> AUTOSENSDATA Cache miss " + new Date(time).toLocaleString());
return null;
}
}
@@ -400,6 +403,14 @@ public class IobCobCalculatorPlugin extends PluginBase {
@Nullable
public AutosensData getLastAutosensDataSynchronized(String reason) {
+ if (thread != null && thread.isAlive()) {
+ log.debug("AUTOSENSDATA is waiting for calculation thread: " + reason);
+ try {
+ thread.join(5000);
+ } catch (InterruptedException ignored) {
+ }
+ log.debug("AUTOSENSDATA finished waiting for calculation thread: " + reason);
+ }
synchronized (dataLock) {
return getLastAutosensData(reason);
}
@@ -453,10 +464,18 @@ public class IobCobCalculatorPlugin extends PluginBase {
log.debug("AUTOSENSDATA null: data is old (" + reason + ") size()=" + autosensDataTable.size() + " lastdata=" + DateUtil.dateAndTimeString(data.time));
return null;
} else {
+ log.debug("AUTOSENSDATA (" + reason + ") " + data.toString());
return data;
}
}
+ public String lastDataTime() {
+ if (autosensDataTable.size() > 0)
+ return DateUtil.dateAndTimeString(autosensDataTable.valueAt(autosensDataTable.size() - 1).time);
+ else
+ return "autosensDataTable empty";
+ }
+
public IobTotal[] calculateIobArrayInDia(Profile profile) {
// predict IOB out to DIA plus 30m
long time = System.currentTimeMillis();
@@ -491,14 +510,10 @@ public class IobCobCalculatorPlugin extends PluginBase {
public AutosensResult detectSensitivityWithLock(long fromTime, long toTime) {
synchronized (dataLock) {
- return detectSensitivity(fromTime, toTime);
+ return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
}
}
- static AutosensResult detectSensitivity(long fromTime, long toTime) {
- return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime);
- }
-
public static JSONArray convertToJSONArray(IobTotal[] iobArray) {
JSONArray array = new JSONArray();
for (int i = 0; i < iobArray.length; i++) {
@@ -542,7 +557,10 @@ public class IobCobCalculatorPlugin extends PluginBase {
public void runCalculation(String from, long start, boolean bgDataReload, Event cause) {
log.debug("Starting calculation thread: " + from);
if (thread == null || thread.getState() == Thread.State.TERMINATED) {
- thread = new IobCobThread(this, from, start, bgDataReload, cause);
+ if (SensitivityOref1Plugin.getPlugin().isEnabled(PluginType.SENSITIVITY))
+ thread = new IobCobOref1Thread(this, from, start, bgDataReload, cause);
+ else
+ thread = new IobCobThread(this, from, start, bgDataReload, cause);
thread.start();
}
}
@@ -581,7 +599,9 @@ public class IobCobCalculatorPlugin extends PluginBase {
ev.isChanged(R.string.key_age) ||
ev.isChanged(R.string.key_absorption_maxtime) ||
ev.isChanged(R.string.key_openapsama_min_5m_carbimpact) ||
- ev.isChanged(R.string.key_absorption_cutoff)
+ ev.isChanged(R.string.key_absorption_cutoff) ||
+ ev.isChanged(R.string.key_openapsama_autosens_max) ||
+ ev.isChanged(R.string.key_openapsama_autosens_min)
) {
stopCalculation("onEventPreferenceChange");
synchronized (dataLock) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
new file mode 100644
index 0000000000..d10d0ebe29
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobOref1Thread.java
@@ -0,0 +1,362 @@
+package info.nightscout.androidaps.plugins.IobCobCalculator;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.support.v4.util.LongSparseArray;
+
+import com.crashlytics.android.answers.CustomEvent;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import info.nightscout.androidaps.BuildConfig;
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.Constants;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.IobTotal;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.BgReading;
+import info.nightscout.androidaps.db.TempTarget;
+import info.nightscout.androidaps.events.Event;
+import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
+import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
+import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.FabricPrivacy;
+import info.nightscout.utils.SP;
+
+import static info.nightscout.utils.DateUtil.now;
+import static java.util.Calendar.MINUTE;
+
+/**
+ * Created by mike on 23.01.2018.
+ */
+
+public class IobCobOref1Thread extends Thread {
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
+ private final Event cause;
+
+ private IobCobCalculatorPlugin iobCobCalculatorPlugin;
+ private boolean bgDataReload;
+ private String from;
+ private long start;
+
+ private PowerManager.WakeLock mWakeLock;
+
+ public IobCobOref1Thread(IobCobCalculatorPlugin plugin, String from, long start, boolean bgDataReload, Event cause) {
+ super();
+
+ this.iobCobCalculatorPlugin = plugin;
+ this.bgDataReload = bgDataReload;
+ this.from = from;
+ this.cause = cause;
+ this.start = start;
+
+ PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "iobCobThread");
+ }
+
+ @Override
+ public final void run() {
+ mWakeLock.acquire();
+ try {
+ log.debug("AUTOSENSDATA thread started: " + from);
+ if (MainApp.getConfigBuilder() == null) {
+ log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
+ return; // app still initializing
+ }
+ if (!MainApp.getConfigBuilder().isProfileValid("IobCobThread")) {
+ log.debug("Aborting calculation thread (No profile): " + from);
+ return; // app still initializing
+ }
+ //log.debug("Locking calculateSensitivityData");
+
+ long oldestTimeWithData = iobCobCalculatorPlugin.oldestDataAvailable();
+
+ synchronized (iobCobCalculatorPlugin.dataLock) {
+ if (bgDataReload) {
+ iobCobCalculatorPlugin.loadBgData(start);
+ iobCobCalculatorPlugin.createBucketedData();
+ }
+ List bucketed_data = iobCobCalculatorPlugin.getBucketedData();
+ LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
+
+ if (bucketed_data == null || bucketed_data.size() < 3) {
+ log.debug("Aborting calculation thread (No bucketed data available): " + from);
+ return;
+ }
+
+ long prevDataTime = IobCobCalculatorPlugin.roundUpTime(bucketed_data.get(bucketed_data.size() - 3).date);
+ log.debug("Prev data time: " + new Date(prevDataTime).toLocaleString());
+ AutosensData previous = autosensDataTable.get(prevDataTime);
+ // start from oldest to be able sub cob
+ for (int i = bucketed_data.size() - 4; i >= 0; i--) {
+ String progress = i + (MainApp.isDev() ? " (" + from + ")" : "");
+ MainApp.bus().post(new EventIobCalculationProgress(progress));
+
+ if (iobCobCalculatorPlugin.stopCalculationTrigger) {
+ iobCobCalculatorPlugin.stopCalculationTrigger = false;
+ log.debug("Aborting calculation thread (trigger): " + from);
+ return;
+ }
+ // check if data already exists
+ long bgTime = bucketed_data.get(i).date;
+ bgTime = IobCobCalculatorPlugin.roundUpTime(bgTime);
+ if (bgTime > IobCobCalculatorPlugin.roundUpTime(now()))
+ continue;
+
+ AutosensData existing;
+ if ((existing = autosensDataTable.get(bgTime)) != null) {
+ previous = existing;
+ continue;
+ }
+
+ Profile profile = MainApp.getConfigBuilder().getProfile(bgTime);
+ if (profile == null) {
+ log.debug("Aborting calculation thread (no profile): " + from);
+ return; // profile not set yet
+ }
+
+ if (Config.logAutosensData)
+ log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
+
+ double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits());
+
+ AutosensData autosensData = new AutosensData();
+ autosensData.time = bgTime;
+ if (previous != null)
+ autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList);
+ else
+ autosensData.activeCarbsList = new ArrayList<>();
+
+ //console.error(bgTime , bucketed_data[i].glucose);
+ double bg;
+ double avgDelta;
+ double delta;
+ bg = bucketed_data.get(i).value;
+ if (bg < 39 || bucketed_data.get(i + 3).value < 39) {
+ log.error("! value < 39");
+ continue;
+ }
+ autosensData.bg = bg;
+ delta = (bg - bucketed_data.get(i + 1).value);
+ avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
+
+ IobTotal iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile);
+
+ double bgi = -iob.activity * sens * 5;
+ double deviation = delta - bgi;
+ double avgDeviation = Math.round((avgDelta - bgi) * 1000) / 1000;
+
+ double slopeFromMaxDeviation = 0;
+ double slopeFromMinDeviation = 999;
+ double maxDeviation = 0;
+ double minDeviation = 999;
+
+ // https://github.com/openaps/oref0/blob/master/lib/determine-basal/cob-autosens.js#L169
+ if (i < bucketed_data.size() - 16) { // we need 1h of data to calculate minDeviationSlope
+ long hourago = bgTime + 10 * 1000 - 60 * 60 * 1000L;
+ AutosensData hourAgoData = IobCobCalculatorPlugin.getPlugin().getAutosensData(hourago);
+ if (hourAgoData != null) {
+ int initialIndex = autosensDataTable.indexOfKey(hourAgoData.time);
+ if (Config.logAutosensData)
+ log.debug(">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString());
+ int past = 1;
+ try {
+ for (; past < 12; past++) {
+ AutosensData ad = autosensDataTable.valueAt(initialIndex + past);
+ double deviationSlope = (ad.avgDeviation - avgDeviation) / (ad.time - bgTime) * 1000 * 60 * 5;
+ if (ad.avgDeviation > maxDeviation) {
+ slopeFromMaxDeviation = Math.min(0, deviationSlope);
+ maxDeviation = ad.avgDeviation;
+ }
+ if (ad.avgDeviation < minDeviation) {
+ slopeFromMinDeviation = Math.max(0, deviationSlope);
+ minDeviation = ad.avgDeviation;
+ }
+
+ //if (Config.logAutosensData)
+ // log.debug("Deviations: " + new Date(bgTime) + new Date(ad.time) + " avgDeviation=" + avgDeviation + " deviationSlope=" + deviationSlope + " slopeFromMaxDeviation=" + slopeFromMaxDeviation + " slopeFromMinDeviation=" + slopeFromMinDeviation);
+ }
+ } catch (Exception e) {
+ log.error("Unhandled exception", e);
+ FabricPrivacy.logException(e);
+ FabricPrivacy.getInstance().logCustom(new CustomEvent("CatchedError")
+ .putCustomAttribute("buildversion", BuildConfig.BUILDVERSION)
+ .putCustomAttribute("version", BuildConfig.VERSION)
+ .putCustomAttribute("autosensDataTable", iobCobCalculatorPlugin.getAutosensDataTable().toString())
+ .putCustomAttribute("for_data", ">>>>> bucketed_data.size()=" + bucketed_data.size() + " i=" + i + "hourAgoData=" + hourAgoData.toString())
+ .putCustomAttribute("past", past)
+ );
+ }
+ }
+ }
+
+ List recentTreatments = TreatmentsPlugin.getPlugin().getTreatments5MinBackFromHistory(bgTime);
+ for (int ir = 0; ir < recentTreatments.size(); ir++) {
+ autosensData.carbsFromBolus += recentTreatments.get(ir).carbs;
+ autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir)));
+ }
+
+
+ // if we are absorbing carbs
+ if (previous != null && previous.cob > 0) {
+ // calculate sum of min carb impact from all active treatments
+ double totalMinCarbsImpact = 0d;
+// if (SensitivityAAPSPlugin.getPlugin().isEnabled(PluginType.SENSITIVITY) || SensitivityWeightedAveragePlugin.getPlugin().isEnabled(PluginType.SENSITIVITY)) {
+ //when the impact depends on a max time, sum them up as smaller carb sizes make them smaller
+// for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) {
+// AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii);
+// totalMinCarbsImpact += c.min5minCarbImpact;
+// }
+// } else {
+ //Oref sensitivity
+ totalMinCarbsImpact = SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact);
+// }
+
+ // figure out how many carbs that represents
+ // but always assume at least 3mg/dL/5m (default) absorption per active treatment
+ double ci = Math.max(deviation, totalMinCarbsImpact);
+ if (ci != deviation)
+ autosensData.failoverToMinAbsorbtionRate = true;
+ autosensData.absorbed = ci * profile.getIc(bgTime) / sens;
+ // and add that to the running total carbsAbsorbed
+ autosensData.cob = Math.max(previous.cob - autosensData.absorbed, 0d);
+ autosensData.mealCarbs = previous.mealCarbs;
+ autosensData.substractAbosorbedCarbs();
+ autosensData.usedMinCarbsImpact = totalMinCarbsImpact;
+ autosensData.absorbing = previous.absorbing;
+ autosensData.mealStartCounter = previous.mealStartCounter;
+ autosensData.type = previous.type;
+ autosensData.uam = previous.uam;
+ }
+
+ autosensData.removeOldCarbs(bgTime);
+ autosensData.cob += autosensData.carbsFromBolus;
+ autosensData.mealCarbs += autosensData.carbsFromBolus;
+ autosensData.deviation = deviation;
+ autosensData.bgi = bgi;
+ autosensData.delta = delta;
+ autosensData.avgDelta = avgDelta;
+ autosensData.avgDeviation = avgDeviation;
+ autosensData.slopeFromMaxDeviation = slopeFromMaxDeviation;
+ autosensData.slopeFromMinDeviation = slopeFromMinDeviation;
+
+
+ // If mealCOB is zero but all deviations since hitting COB=0 are positive, exclude from autosens
+ if (autosensData.cob > 0 || autosensData.absorbing || autosensData.mealCarbs > 0) {
+ if (deviation > 0)
+ autosensData.absorbing = true;
+ else
+ autosensData.absorbing = false;
+ // stop excluding positive deviations as soon as mealCOB=0 if meal has been absorbing for >5h
+ if (autosensData.mealStartCounter > 60 && autosensData.cob < 0.5) {
+ autosensData.absorbing = false;
+ }
+ if (!autosensData.absorbing && autosensData.cob < 0.5) {
+ autosensData.mealCarbs = 0;
+ }
+ // check previous "type" value, and if it wasn't csf, set a mealAbsorption start flag
+ if (!autosensData.type.equals("csf")) {
+// process.stderr.write("(");
+ autosensData.mealStartCounter = 0;
+ }
+ autosensData.mealStartCounter++;
+ autosensData.type = "csf";
+ } else {
+ // check previous "type" value, and if it was csf, set a mealAbsorption end flag
+ if (autosensData.type.equals("csf")) {
+// process.stderr.write(")");
+ }
+
+ double currentBasal = profile.getBasal(bgTime);
+ // always exclude the first 45m after each carb entry
+ //if (iob.iob > currentBasal || uam ) {
+ if (iob.iob > 2 * currentBasal || autosensData.uam || autosensData.mealStartCounter < 9) {
+ autosensData.mealStartCounter++;
+ if (deviation > 0)
+ autosensData.uam = true;
+ else
+ autosensData.uam = false;
+ if (!autosensData.type.equals("uam")) {
+// process.stderr.write("u(");
+ }
+ autosensData.type = "uam";
+ } else {
+ if (autosensData.type.equals("uam")) {
+// process.stderr.write(")");
+ }
+ autosensData.type = "non-meal";
+ }
+ }
+
+ // Exclude meal-related deviations (carb absorption) from autosens
+ if (autosensData.type.equals("non-meal")) {
+ if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
+ autosensData.pastSensitivity = "=";
+ autosensData.validDeviation = true;
+ } else if (deviation > 0) {
+ autosensData.pastSensitivity = "+";
+ autosensData.validDeviation = true;
+ } else {
+ autosensData.pastSensitivity = "-";
+ autosensData.validDeviation = true;
+ }
+ } else if (autosensData.type.equals("uam")) {
+ autosensData.pastSensitivity = "u";
+ } else {
+ autosensData.pastSensitivity = "x";
+ }
+ //log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
+
+ // add an extra negative deviation if a high temptarget is running and exercise mode is set
+ if (SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)) {
+ TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(bgTime);
+ if (tempTarget != null && tempTarget.target() >= 100) {
+ autosensData.extraDeviation.add(-(tempTarget.target() - 100) / 20);
+ }
+ }
+
+ // add one neutral deviation every 2 hours to help decay over long exclusion periods
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeInMillis(bgTime);
+ int min = calendar.get(MINUTE);
+ int hours = calendar.get(Calendar.HOUR_OF_DAY);
+ if (min >= 0 && min < 5 && hours % 2 == 0)
+ autosensData.extraDeviation.add(0d);
+
+ previous = autosensData;
+ if (bgTime < now())
+ autosensDataTable.put(bgTime, autosensData);
+ if (Config.logAutosensData)
+ log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + IobCobCalculatorPlugin.getPlugin().lastDataTime());
+ AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivityWithLock(oldestTimeWithData, bgTime);
+ if (Config.logAutosensData)
+ log.debug("Sensitivity result: " + sensitivity.toString());
+ autosensData.autosensResult = sensitivity;
+ if (Config.logAutosensData)
+ log.debug(autosensData.toString());
+ }
+ }
+ new Thread(() -> {
+ SystemClock.sleep(1000);
+ MainApp.bus().post(new EventAutosensCalculationFinished(cause));
+ }).start();
+ } finally {
+ mWakeLock.release();
+ MainApp.bus().post(new EventIobCalculationProgress(""));
+ log.debug("AUTOSENSDATA thread ended: " + from);
+ }
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
index 9818ed17e4..d60efb5bc6 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobThread.java
@@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.IobCobCalculator;
import android.content.Context;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.support.v4.util.LongSparseArray;
import com.crashlytics.android.answers.CustomEvent;
@@ -26,8 +27,8 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.plugins.OpenAPSSMB.SMBDefaults;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
@@ -41,7 +42,7 @@ import static info.nightscout.utils.DateUtil.now;
*/
public class IobCobThread extends Thread {
- private static Logger log = LoggerFactory.getLogger(IobCobThread.class);
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
private final Event cause;
private IobCobCalculatorPlugin iobCobCalculatorPlugin;
@@ -68,6 +69,7 @@ public class IobCobThread extends Thread {
public final void run() {
mWakeLock.acquire();
try {
+ log.debug("AUTOSENSDATA thread started: " + from);
if (MainApp.getConfigBuilder() == null) {
log.debug("Aborting calculation thread (ConfigBuilder not ready): " + from);
return; // app still initializing
@@ -145,6 +147,7 @@ public class IobCobThread extends Thread {
log.error("! value < 39");
continue;
}
+ autosensData.bg = bg;
delta = (bg - bucketed_data.get(i + 1).value);
avgDelta = (bg - bucketed_data.get(i + 3).value) / 3;
@@ -245,35 +248,41 @@ public class IobCobThread extends Thread {
// calculate autosens only without COB
if (autosensData.cob <= 0) {
if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) {
- autosensData.pastSensitivity += "=";
- autosensData.nonEqualDeviation = true;
+ autosensData.pastSensitivity = "=";
+ autosensData.validDeviation = true;
} else if (deviation > 0) {
- autosensData.pastSensitivity += "+";
- autosensData.nonEqualDeviation = true;
+ autosensData.pastSensitivity = "+";
+ autosensData.validDeviation = true;
} else {
- autosensData.pastSensitivity += "-";
- autosensData.nonEqualDeviation = true;
+ autosensData.pastSensitivity = "-";
+ autosensData.validDeviation = true;
}
- autosensData.nonCarbsDeviation = true;
} else {
- autosensData.pastSensitivity += "C";
+ autosensData.pastSensitivity = "C";
}
//log.debug("TIME: " + new Date(bgTime).toString() + " BG: " + bg + " SENS: " + sens + " DELTA: " + delta + " AVGDELTA: " + avgDelta + " IOB: " + iob.iob + " ACTIVITY: " + iob.activity + " BGI: " + bgi + " DEVIATION: " + deviation);
previous = autosensData;
- autosensDataTable.put(bgTime, autosensData);
+ if (bgTime < now())
+ autosensDataTable.put(bgTime, autosensData);
if (Config.logAutosensData)
- log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime));
- autosensData.autosensRatio = iobCobCalculatorPlugin.detectSensitivity(oldestTimeWithData, bgTime).ratio;
+ log.debug("Running detectSensitivity from: " + DateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + DateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + IobCobCalculatorPlugin.getPlugin().lastDataTime());
+ AutosensResult sensitivity = iobCobCalculatorPlugin.detectSensitivityWithLock(oldestTimeWithData, bgTime);
+ if (Config.logAutosensData)
+ log.debug("Sensitivity result: " + sensitivity.toString());
+ autosensData.autosensResult = sensitivity;
if (Config.logAutosensData)
log.debug(autosensData.toString());
}
}
- MainApp.bus().post(new EventAutosensCalculationFinished(cause));
- log.debug("Finishing calculation thread: " + from);
+ new Thread(() -> {
+ SystemClock.sleep(1000);
+ MainApp.bus().post(new EventAutosensCalculationFinished(cause));
+ }).start();
} finally {
mWakeLock.release();
MainApp.bus().post(new EventIobCalculationProgress(""));
+ log.debug("AUTOSENSDATA thread ended: " + from);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
index 87e55c7dc6..ce63ad67e5 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java
@@ -10,7 +10,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
@@ -28,7 +27,7 @@ import info.nightscout.utils.DecimalFormatter;
public class APSResult {
private static Logger log = LoggerFactory.getLogger(APSResult.class);
- public Date date;
+ public long date = 0;
public String reason;
public double rate;
public int duration;
@@ -133,8 +132,8 @@ public class APSResult {
public List getPredictions() {
List array = new ArrayList<>();
try {
- long startTime = date.getTime();
- if (json.has("predBGs")) {
+ long startTime = date;
+ if (json != null && json.has("predBGs")) {
JSONObject predBGs = json.getJSONObject("predBGs");
if (predBGs.has("IOB")) {
JSONArray iob = predBGs.getJSONArray("IOB");
@@ -196,8 +195,8 @@ public class APSResult {
public long getLatestPredictionsTime() {
long latest = 0;
try {
- long startTime = date != null ? date.getTime() : 0;
- if (json.has("predBGs")) {
+ long startTime = date;
+ if (json != null && json.has("predBGs")) {
JSONObject predBGs = json.getJSONObject("predBGs");
if (predBGs.has("IOB")) {
JSONArray iob = predBGs.getJSONArray("IOB");
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java
index 4ad35c0d02..7fa810f8c0 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopFragment.java
@@ -80,7 +80,7 @@ public class LoopFragment extends SubscriberFragment {
clearGUI();
final Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(() -> lastRunView.setText(ev.text));
+ activity.runOnUiThread(() -> { synchronized (LoopFragment.this) { if (lastRunView != null) lastRunView.setText(ev.text); } });
}
@@ -89,26 +89,29 @@ public class LoopFragment extends SubscriberFragment {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
- LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
- if (lastRun != null) {
- requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : "");
- constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : "");
- sourceView.setText(lastRun.source != null ? lastRun.source : "");
- lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : "");
- lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : "");
- tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : "");
- smbSetByPumpView.setText(lastRun.smbSetByPump != null ? Html.fromHtml(lastRun.smbSetByPump.toHtml()) : "");
+ synchronized (LoopFragment.this) {
+ if (!isBound()) return;
+ LoopPlugin.LastRun lastRun = LoopPlugin.lastRun;
+ if (lastRun != null) {
+ requestView.setText(lastRun.request != null ? lastRun.request.toSpanned() : "");
+ constraintsProcessedView.setText(lastRun.constraintsProcessed != null ? lastRun.constraintsProcessed.toSpanned() : "");
+ sourceView.setText(lastRun.source != null ? lastRun.source : "");
+ lastRunView.setText(lastRun.lastAPSRun != null && lastRun.lastAPSRun.getTime() != 0 ? lastRun.lastAPSRun.toLocaleString() : "");
+ lastEnactView.setText(lastRun.lastEnact != null && lastRun.lastEnact.getTime() != 0 ? lastRun.lastEnact.toLocaleString() : "");
+ tbrSetByPumpView.setText(lastRun.tbrSetByPump != null ? Html.fromHtml(lastRun.tbrSetByPump.toHtml()) : "");
+ smbSetByPumpView.setText(lastRun.smbSetByPump != null ? Html.fromHtml(lastRun.smbSetByPump.toHtml()) : "");
- String constraints = "";
- if (lastRun.constraintsProcessed != null) {
- Constraint allConstraints = new Constraint<>(0d);
- if (lastRun.constraintsProcessed.rateConstraint != null)
- allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint);
- if (lastRun.constraintsProcessed.smbConstraint != null)
- allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint);
- constraints = allConstraints.getMostLimitedReasons();
+ String constraints = "";
+ if (lastRun.constraintsProcessed != null) {
+ Constraint allConstraints = new Constraint<>(0d);
+ if (lastRun.constraintsProcessed.rateConstraint != null)
+ allConstraints.copyReasons(lastRun.constraintsProcessed.rateConstraint);
+ if (lastRun.constraintsProcessed.smbConstraint != null)
+ allConstraints.copyReasons(lastRun.constraintsProcessed.smbConstraint);
+ constraints = allConstraints.getMostLimitedReasons();
+ }
+ constraintsView.setText(constraints);
}
- constraintsView.setText(constraints);
}
});
}
@@ -117,13 +120,29 @@ public class LoopFragment extends SubscriberFragment {
Activity activity = getActivity();
if (activity != null)
activity.runOnUiThread(() -> {
- requestView.setText("");
- constraintsProcessedView.setText("");
- sourceView.setText("");
- lastRunView.setText("");
- lastEnactView.setText("");
- tbrSetByPumpView.setText("");
- smbSetByPumpView.setText("");
+ synchronized (LoopFragment.this) {
+ if (isBound()) {
+ requestView.setText("");
+ constraintsProcessedView.setText("");
+ sourceView.setText("");
+ lastRunView.setText("");
+ lastEnactView.setText("");
+ tbrSetByPumpView.setText("");
+ smbSetByPumpView.setText("");
+ }
+ }
});
}
+
+ boolean isBound() {
+ return requestView != null
+ && constraintsProcessedView != null
+ && sourceView != null
+ && lastRunView != null
+ && lastEnactView != null
+ && tbrSetByPumpView != null
+ && smbSetByPumpView != null
+ && constraintsView != null
+ && runNowButton != null;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
index f6ec0ff7ab..480646ccfc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java
@@ -46,6 +46,7 @@ import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@@ -94,6 +95,7 @@ public class LoopPlugin extends PluginBase {
.pluginName(R.string.loop)
.shortName(R.string.loop_shortname)
.preferencesId(R.xml.pref_closedmode)
+ .description(R.string.description_loop)
);
loopSuspendedTill = SP.getLong("loopSuspendedTill", 0L);
isSuperBolus = SP.getBoolean("isSuperBolus", false);
@@ -331,7 +333,9 @@ public class LoopPlugin extends PluginBase {
Constraint closedLoopEnabled = MainApp.getConstraintChecker().isClosedLoopAllowed();
if (closedLoopEnabled.value()) {
- if (result.isChangeRequested()) {
+ if (result.isChangeRequested()
+ && !ConfigBuilderPlugin.getCommandQueue().bolusInQueue()
+ && !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BOLUS)) {
final PumpEnactResult waiting = new PumpEnactResult();
waiting.queued = true;
if (resultAfterConstraints.tempBasalRequested)
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientPlugin.java
index c43297ccf6..6949cdc8b1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientPlugin.java
@@ -69,6 +69,7 @@ public class NSClientPlugin extends PluginBase {
.pluginName(R.string.nsclientinternal)
.shortName(R.string.nsclientinternal_shortname)
.preferencesId(R.xml.pref_nsclientinternal)
+ .description(R.string.description_ns_client)
);
if (Config.NSCLIENT || Config.G5UPLOADER) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java
index 04b587ca24..ba6ec2c80b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NsClientReceiverDelegate.java
@@ -122,7 +122,8 @@ class NsClientReceiverDelegate {
boolean newAllowedState = true;
if (ev.wifiConnected) {
- if (!allowedSSIDs.trim().isEmpty() && !allowedSSIDs.contains(ev.ssid)) {
+ if (!allowedSSIDs.trim().isEmpty() &&
+ (!allowedSSIDs.contains(ev.getSsid()) && !allowedSSIDs.contains(ev.ssid))) {
newAllowedState = false;
}
} else {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java
index 4ee2427af8..a2b6e64aec 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java
@@ -26,14 +26,24 @@ public class BroadcastStatus {
private static Logger log = LoggerFactory.getLogger(BroadcastStatus.class);
public static void handleNewStatus(NSSettingsStatus status, Context context, boolean isDelta) {
+ LocalBroadcastManager.getInstance(MainApp.instance())
+ .sendBroadcast(createIntent(status, isDelta));
+ if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
+ context.sendBroadcast(createIntent(status, isDelta));
+ }
+ }
+
+ private static Intent createIntent(NSSettingsStatus status, boolean isDelta) {
Bundle bundle = new Bundle();
+
try {
bundle.putString("nsclientversionname", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionName);
bundle.putInt("nsclientversioncode", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode);
} catch (PackageManager.NameNotFoundException e) {
log.error("Unhandled exception", e);
}
+
bundle.putString("nightscoutversionname", NSClientService.nightscoutVersionName);
bundle.putInt("nightscoutversioncode", NSClientService.nightscoutVersionCode);
bundle.putString("status", status.getData().toString());
@@ -41,24 +51,7 @@ public class BroadcastStatus {
Intent intent = new Intent(Intents.ACTION_NEW_STATUS);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
- if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
- bundle = new Bundle();
- try {
- bundle.putString("nsclientversionname", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionName);
- bundle.putInt("nsclientversioncode", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode);
- } catch (PackageManager.NameNotFoundException e) {
- log.error("Unhandled exception", e);
- }
- bundle.putString("nightscoutversionname", NSClientService.nightscoutVersionName);
- bundle.putInt("nightscoutversioncode", NSClientService.nightscoutVersionCode);
- bundle.putString("status", status.getData().toString());
- bundle.putBoolean("delta", isDelta);
- intent = new Intent(Intents.ACTION_NEW_STATUS);
- intent.putExtras(bundle);
- intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- context.sendBroadcast(intent);
- }
+ return intent;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java
index d1755dd4c1..29d1b33467 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java
@@ -13,6 +13,7 @@ import java.util.Iterator;
import java.util.Map;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
@@ -374,7 +375,7 @@ public class NSDeviceStatus {
public String getUploaderStatus() {
Iterator iter = uploaders.entrySet().iterator();
int minBattery = 100;
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
if (minBattery > uploader.battery)
@@ -388,7 +389,7 @@ public class NSDeviceStatus {
StringBuilder string = new StringBuilder();
Iterator iter = uploaders.entrySet().iterator();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
Map.Entry pair = (Map.Entry) iter.next();
Uploader uploader = (Uploader) pair.getValue();
String device = (String) pair.getKey();
@@ -398,4 +399,11 @@ public class NSDeviceStatus {
return Html.fromHtml(string.toString());
}
+ public static APSResult getAPSResult() {
+ APSResult result = new APSResult();
+ result.json = deviceStatusOpenAPSData.suggested;
+ result.date = deviceStatusOpenAPSData.clockSuggested;
+ return result;
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java
index cb2b4a0091..ac7a7c2b49 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java
@@ -6,19 +6,18 @@ import org.mozilla.javascript.NativeObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Date;
-
import info.nightscout.androidaps.plugins.Loop.APSResult;
+import info.nightscout.utils.DateUtil;
public class DetermineBasalResultAMA extends APSResult {
private static Logger log = LoggerFactory.getLogger(DetermineBasalResultAMA.class);
- public double eventualBG;
- public double snoozeBG;
+ private double eventualBG;
+ private double snoozeBG;
- public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
+ DetermineBasalResultAMA(NativeObject result, JSONObject j) {
this();
- date = new Date();
+ date = DateUtil.now();
json = j;
if (result.containsKey("error")) {
reason = result.get("error").toString();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAPlugin.java
index 143456f6fc..74d15cd2a4 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
@@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,6 +63,7 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
.pluginName(R.string.openapsama)
.shortName(R.string.oaps_shortname)
.preferencesId(R.xml.pref_openapsama)
+ .description(R.string.description_ama)
);
}
@@ -172,9 +174,14 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface {
startPart = new Date();
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
- lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
+ AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin");
+ if (autosensData == null) {
+ MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata)));
+ return;
+ }
} else {
lastAutosensResult = new AutosensResult();
+ lastAutosensResult.sensResult = "autosens disabled";
}
Profiler.log(log, "detectSensitivityandCarbAbsorption()", startPart);
Profiler.log(log, "AMA data gathering", start);
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 14dac65625..39d05f8ffb 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
@@ -62,6 +62,7 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface {
.pluginName(R.string.openapsma)
.shortName(R.string.oaps_shortname)
.preferencesId(R.xml.pref_openapsma)
+ .description(R.string.description_ma)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
index da96241e61..48a4c16ccd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalAdapterSMBJS.java
@@ -234,8 +234,8 @@ public class DetermineBasalAdapterSMBJS {
mProfile.put("max_daily_safety_multiplier", SP.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3));
mProfile.put("current_basal_safety_multiplier", SP.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d));
- mProfile.put("high_temptarget_raises_sensitivity", SMBDefaults.high_temptarget_raises_sensitivity);
- mProfile.put("low_temptarget_lowers_sensitivity", SMBDefaults.low_temptarget_lowers_sensitivity);
+ mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
+ mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
mProfile.put("sensitivity_raises_target", SMBDefaults.sensitivity_raises_target);
mProfile.put("resistance_lowers_target", SMBDefaults.resistance_lowers_target);
mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments);
@@ -250,7 +250,7 @@ public class DetermineBasalAdapterSMBJS {
mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact));
}
mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap);
- mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false)&& advancedFiltering);
+ mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable);
mProfile.put("enableSMB_with_COB", SP.getBoolean(R.string.key_enableSMB_with_COB, false));
mProfile.put("enableSMB_with_temptarget", SP.getBoolean(R.string.key_enableSMB_with_temptarget, false));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java
index 59c1dd95e3..d5f108bf4f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/DetermineBasalResultSMB.java
@@ -5,22 +5,20 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Date;
-
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.utils.DateUtil;
public class DetermineBasalResultSMB extends APSResult {
private static final Logger log = LoggerFactory.getLogger(DetermineBasalResultSMB.class);
- public double eventualBG;
- public double snoozeBG;
- public double insulinReq;
- public double carbsReq;
+ private double eventualBG;
+ private double snoozeBG;
+ //public double insulinReq;
+ //public double carbsReq;
- public DetermineBasalResultSMB(JSONObject result) {
+ DetermineBasalResultSMB(JSONObject result) {
this();
- date = new Date();
+ date = DateUtil.now();
json = result;
try {
if (result.has("error")) {
@@ -31,8 +29,8 @@ public class DetermineBasalResultSMB extends APSResult {
reason = result.getString("reason");
if (result.has("eventualBG")) eventualBG = result.getDouble("eventualBG");
if (result.has("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
- if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
- if (result.has("carbsReq")) carbsReq = result.getDouble("carbsReq");
+ //if (result.has("insulinReq")) insulinReq = result.getDouble("insulinReq");
+ //if (result.has("carbsReq")) carbsReq = result.getDouble("carbsReq");
if (result.has("rate") && result.has("duration")) {
tempBasalRequested = true;
@@ -64,7 +62,7 @@ public class DetermineBasalResultSMB extends APSResult {
}
}
- public DetermineBasalResultSMB() {
+ private DetermineBasalResultSMB() {
hasPredictions = true;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java
index 724bfcf86c..20ccd46b40 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBFragment.java
@@ -87,34 +87,37 @@ public class OpenAPSSMBFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin();
- DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult;
- if (lastAPSResult != null) {
- resultView.setText(JSONFormatter.format(lastAPSResult.json));
- requestView.setText(lastAPSResult.toSpanned());
- }
- DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS;
- if (determineBasalAdapterSMBJS != null) {
- glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()).toString().trim());
- currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()).toString().trim());
- try {
- JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam());
- iobDataView.setText((String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0))).trim());
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
- iobDataView.setText("JSONException see log for details");
+ synchronized (OpenAPSSMBFragment.this) {
+ if (!isBound()) return;
+ OpenAPSSMBPlugin plugin = OpenAPSSMBPlugin.getPlugin();
+ DetermineBasalResultSMB lastAPSResult = plugin.lastAPSResult;
+ if (lastAPSResult != null) {
+ resultView.setText(JSONFormatter.format(lastAPSResult.json));
+ requestView.setText(lastAPSResult.toSpanned());
+ }
+ DetermineBasalAdapterSMBJS determineBasalAdapterSMBJS = plugin.lastDetermineBasalAdapterSMBJS;
+ if (determineBasalAdapterSMBJS != null) {
+ glucoseStatusView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getGlucoseStatusParam()).toString().trim());
+ currentTempView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getCurrentTempParam()).toString().trim());
+ try {
+ JSONArray iobArray = new JSONArray(determineBasalAdapterSMBJS.getIobDataParam());
+ iobDataView.setText((String.format(MainApp.gs(R.string.array_of_elements), iobArray.length()) + "\n" + JSONFormatter.format(iobArray.getString(0))).trim());
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ iobDataView.setText("JSONException see log for details");
+ }
+ profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()).toString().trim());
+ mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()).toString().trim());
+ scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug().trim());
+ if (lastAPSResult != null && lastAPSResult.inputConstraints != null)
+ constraintsView.setText(lastAPSResult.inputConstraints.getReasons().trim());
+ }
+ if (plugin.lastAPSRun != null) {
+ lastRunView.setText(plugin.lastAPSRun.toLocaleString().trim());
+ }
+ if (plugin.lastAutosensResult != null) {
+ autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()).toString().trim());
}
- profileView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getProfileParam()).toString().trim());
- mealDataView.setText(JSONFormatter.format(determineBasalAdapterSMBJS.getMealDataParam()).toString().trim());
- scriptdebugView.setText(determineBasalAdapterSMBJS.getScriptDebug().trim());
- if (lastAPSResult != null && lastAPSResult.inputConstraints != null)
- constraintsView.setText(lastAPSResult.inputConstraints.getReasons().trim());
- }
- if (plugin.lastAPSRun != null) {
- lastRunView.setText(plugin.lastAPSRun.toLocaleString().trim());
- }
- if (plugin.lastAutosensResult != null) {
- autosensDataView.setText(JSONFormatter.format(plugin.lastAutosensResult.json()).toString().trim());
}
}
});
@@ -126,17 +129,36 @@ public class OpenAPSSMBFragment extends SubscriberFragment {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- resultView.setText(text);
- glucoseStatusView.setText("");
- currentTempView.setText("");
- iobDataView.setText("");
- profileView.setText("");
- mealDataView.setText("");
- autosensDataView.setText("");
- scriptdebugView.setText("");
- requestView.setText("");
- lastRunView.setText("");
+ synchronized (OpenAPSSMBFragment.this) {
+ if (isBound()) {
+ resultView.setText(text);
+ glucoseStatusView.setText("");
+ currentTempView.setText("");
+ iobDataView.setText("");
+ profileView.setText("");
+ mealDataView.setText("");
+ autosensDataView.setText("");
+ scriptdebugView.setText("");
+ requestView.setText("");
+ lastRunView.setText("");
+ }
+ }
}
});
}
+
+ private boolean isBound() {
+ return run != null
+ && lastRunView != null
+ && constraintsView != null
+ && glucoseStatusView != null
+ && currentTempView != null
+ && iobDataView != null
+ && profileView != null
+ && mealDataView != null
+ && autosensDataView != null
+ && resultView != null
+ && scriptdebugView != null
+ && requestView != null;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java
index 49a81ea612..570b76502f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSSMB/OpenAPSSMBPlugin.java
@@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.OpenAPSSMB;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,6 +66,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface {
.pluginName(R.string.openapssmb)
.shortName(R.string.smb_shortname)
.preferencesId(R.xml.pref_openapssmb)
+ .description(R.string.description_smb)
);
}
@@ -179,9 +181,15 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface {
startPart = new Date();
if (MainApp.getConstraintChecker().isAutosensModeEnabled().value()) {
- lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
+ AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensDataSynchronized("OpenAPSPlugin");
+ if (autosensData == null) {
+ MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.gs(R.string.openaps_noasdata)));
+ return;
+ }
+ lastAutosensResult = autosensData.autosensResult;
} else {
lastAutosensResult = new AutosensResult();
+ lastAutosensResult.sensResult = "autosens disabled";
}
Constraint smbAllowed = new Constraint<>(!tempBasalFallback);
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 8ef6ec2fc6..9974471528 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
@@ -112,7 +112,7 @@ public class BolusProgressDialog extends DialogFragment implements View.OnClickL
stopPressed = true;
stopPressedView.setVisibility(View.VISIBLE);
stopButton.setVisibility(View.INVISIBLE);
- ConfigBuilderPlugin.getActivePump().stopBolusDelivering();
+ ConfigBuilderPlugin.getCommandQueue().cancelAllBoluses();
break;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java
index 4360e2ed34..26f46081ea 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewCarbsDialog.java
@@ -21,6 +21,7 @@ import android.widget.RadioButton;
import com.google.common.base.Joiner;
+import info.nightscout.utils.NSUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,7 +33,9 @@ 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.DatabaseHelper;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.Constraint;
@@ -124,7 +127,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt);
- startHypoTTCheckbox.setOnCheckedChangeListener(this);
editTime = view.findViewById(R.id.newcarbs_time);
editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
@@ -153,6 +155,13 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = view.findViewById(R.id.newcarbs_notes);
+ BgReading bgReading = DatabaseHelper.actualBg();
+ if (bgReading != null && bgReading.value < 72) {
+ startHypoTTCheckbox.setOnCheckedChangeListener(null);
+ startHypoTTCheckbox.setChecked(true);
+ }
+ startHypoTTCheckbox.setOnClickListener(this);
+
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
@@ -221,13 +230,13 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- // Logic to disable a selected radio when pressed. When a checked radio
- // is pressed, no CheckChanged event is trigger, so register a Click event
+ // Logic to disable a selected radio when pressed: when a checked radio
+ // is pressed, no CheckChanged event is triggered, so register a Click event
// when checking a radio. Since Click events come after CheckChanged events,
- // the Click event is triggered immediately after this. Thus, set toggingTT
+ // the Click event is triggered immediately after this. Thus, set togglingTT
// var to true, so that the first Click event fired after this is ignored.
// Radios remove themselves from Click events once unchecked.
- // Since radios are not in a group, manually update their state.
+ // Since radios are not in a group, their state is manually updated here.
switch (buttonView.getId()) {
case R.id.newcarbs_activity_tt:
togglingTT = true;
@@ -303,21 +312,21 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
if (currentProfile.getUnits().equals(Constants.MMOL)) {
unitLabel = "mmol/l";
}
-
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " min)");
-
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " min)");
}
if (startEatingSoonTTCheckbox.isChecked()) {
if (currentProfile.getUnits().equals(Constants.MMOL)) {
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)");
- } else
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)");
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)");
+ } else {
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)");
+ }
}
if (startHypoTTCheckbox.isChecked()) {
if (currentProfile.getUnits().equals(Constants.MMOL)) {
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(hypoTT) + " mmol/l (" + hypoTTDuration + " min)");
- } else
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)");
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(hypoTT) + " mmol/l (" + hypoTTDuration + " min)");
+ } else {
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)");
+ }
}
int timeOffset = editTime.getValue().intValue();
@@ -394,6 +403,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, C
CarbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes);
} else {
CarbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes);
+ NSUpload.uploadEvent(CareportalEvent.NOTE, now() - 2000, MainApp.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset));
}
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java
index 875d207352..2889c8266b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/NewInsulinDialog.java
@@ -148,6 +148,11 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
+ if (savedInstanceState != null) {
+// log.debug("savedInstanceState in onCreate is:" + savedInstanceState.toString());
+ editInsulin.setValue(savedInstanceState.getDouble("editInsulin"));
+ editTime.setValue(savedInstanceState.getDouble("editTime"));
+ }
return view;
}
@@ -156,6 +161,17 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
return value > 0 ? "+" + formatted : formatted;
}
+ @Override
+ public void onSaveInstanceState(Bundle insulinDialogState) {
+ insulinDialogState.putBoolean("startEatingSoonTTCheckbox", startEatingSoonTTCheckbox.isChecked());
+ insulinDialogState.putBoolean("recordOnlyCheckbox", recordOnlyCheckbox.isChecked());
+ insulinDialogState.putDouble("editTime", editTime.getValue());
+ insulinDialogState.putDouble("editInsulin", editInsulin.getValue());
+ insulinDialogState.putString("notesEdit",notesEdit.getText().toString());
+ log.debug("Instance state saved:"+insulinDialogState.toString());
+ super.onSaveInstanceState(insulinDialogState);
+ }
+
@Override
public synchronized void onClick(View view) {
switch (view.getId()) {
@@ -217,9 +233,9 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
if (startEatingSoonTTCheckbox.isChecked()) {
if (currentProfile.getUnits().equals(Constants.MMOL)) {
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)");
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)");
} else
- actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)");
+ actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)");
}
int timeOffset = editTime.getValue().intValue();
@@ -270,7 +286,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener
detailedBolusInfo.notes = notes;
if (recordOnlyCheckbox.isChecked()) {
detailedBolusInfo.date = time;
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
} else {
detailedBolusInfo.date = now();
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
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 a315310dc8..5fb698d1c5 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
@@ -25,7 +25,6 @@ import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.Objects;
-import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
@@ -187,7 +186,7 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
}
});
} else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
}
FabricPrivacy.getInstance().logCustom(new CustomEvent("Bolus"));
}
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 c38f41b825..032104e103 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
@@ -315,6 +315,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
confirmMessage += " " + MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + "";
if (insulinAfterConstraints - calculatedTotalInsulin != 0 || !carbsAfterConstraints.equals(calculatedCarbs)) {
+ okClicked = false;
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.treatmentdeliveryerror));
builder.setMessage(MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput));
@@ -388,7 +389,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
}
});
} else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
}
FabricPrivacy.getInstance().logCustom(new CustomEvent("Wizard"));
}
@@ -408,9 +409,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
private void initDialog() {
Profile profile = MainApp.getConfigBuilder().getProfile();
- ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile();
+ ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface() != null ? MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() : null;
- if (profile == null) {
+ if (profile == null || profileStore == null) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.noprofile));
dismiss();
return;
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 f43a78d64f..2b4ab247b8 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
@@ -24,14 +24,11 @@ import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ContextMenu;
-import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -88,10 +85,12 @@ import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialo
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.CobInfo;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventIobCalculationProgress;
+import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus;
@@ -102,7 +101,6 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.NewInsulinDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog;
import info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity;
-import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Overview.graphData.GraphData;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationRecyclerViewAdapter;
import info.nightscout.androidaps.plugins.Overview.notifications.NotificationStore;
@@ -114,22 +112,29 @@ import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
+import info.nightscout.utils.DefaultValueHelper;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.Profiler;
import info.nightscout.utils.SP;
import info.nightscout.utils.SingleClickButton;
+import info.nightscout.utils.T;
import info.nightscout.utils.ToastUtils;
+import static info.nightscout.utils.DateUtil.now;
+
public class OverviewFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener {
private static Logger log = LoggerFactory.getLogger(OverviewFragment.class);
TextView timeView;
TextView bgView;
TextView arrowView;
+ TextView sensitivityView;
TextView timeAgoView;
+ TextView timeAgoShortView;
TextView deltaView;
+ TextView deltaShortView;
TextView avgdeltaView;
TextView baseBasalView;
TextView extendedBolusView;
@@ -168,8 +173,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
SingleClickButton cgmButton;
SingleClickButton quickWizardButton;
- CheckBox lockScreen;
-
boolean smallWidth;
boolean smallHeight;
@@ -226,8 +229,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (smallWidth) {
arrowView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 35);
}
+ sensitivityView = (TextView) view.findViewById(R.id.overview_sensitivity);
timeAgoView = (TextView) view.findViewById(R.id.overview_timeago);
+ timeAgoShortView = (TextView) view.findViewById(R.id.overview_timeagoshort);
deltaView = (TextView) view.findViewById(R.id.overview_delta);
+ deltaShortView = (TextView) view.findViewById(R.id.overview_deltashort);
avgdeltaView = (TextView) view.findViewById(R.id.overview_avgdelta);
baseBasalView = (TextView) view.findViewById(R.id.overview_basebasal);
extendedBolusView = (TextView) view.findViewById(R.id.overview_extendedbolus);
@@ -281,7 +287,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications);
- notificationsView.setHasFixedSize(true);
+ notificationsView.setHasFixedSize(false);
llm = new LinearLayoutManager(view.getContext());
notificationsView.setLayoutManager(llm);
@@ -307,7 +313,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
bgGraph.getGridLabelRenderer().setLabelVerticalWidth(axisWidth);
iobGraph.getGridLabelRenderer().setLabelVerticalWidth(axisWidth);
- iobGraph.getGridLabelRenderer().setNumVerticalLabels(5);
+ iobGraph.getGridLabelRenderer().setNumVerticalLabels(3);
rangeToDisplay = SP.getInt(R.string.key_rangetodisplay, 6);
@@ -324,18 +330,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
setupChartMenu(view);
- lockScreen = (CheckBox) view.findViewById(R.id.overview_lockscreen);
- if (lockScreen != null) {
- lockScreen.setChecked(SP.getBoolean("lockscreen", false));
- lockScreen.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- SP.putBoolean("lockscreen", isChecked);
- MainApp.bus().post(new EventSetWakeLock(isChecked));
- }
- });
- }
-
return view;
} catch (Exception e) {
FabricPrivacy.logException(e);
@@ -351,7 +345,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public void onClick(View v) {
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
- final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ boolean predictionsAvailable;
+ if (Config.APS)
+ predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ else if (Config.NSCLIENT)
+ predictionsAvailable = true;
+ else
+ predictionsAvailable = false;
MenuItem item;
CharSequence title;
@@ -485,9 +485,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} else if (v == activeProfileView) {
menu.setHeaderTitle(MainApp.gs(R.string.profile));
menu.add(MainApp.gs(R.string.danar_viewprofile));
- if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
+ if (MainApp.getConfigBuilder().getActiveProfileInterface() != null && MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() != null) {
menu.add(MainApp.gs(R.string.careportal_profileswitch));
}
+ } else if (v == tempTargetView) {
+ menu.setHeaderTitle(MainApp.gs(R.string.careportal_temporarytarget));
+ menu.add(MainApp.gs(R.string.custom));
+ menu.add(MainApp.gs(R.string.eatingsoon));
+ menu.add(MainApp.gs(R.string.activity));
+ menu.add(MainApp.gs(R.string.hypo));
+ if (TreatmentsPlugin.getPlugin().getTempTargetFromHistory() != null) {
+ menu.add(MainApp.gs(R.string.cancel));
+ }
}
}
@@ -578,6 +587,53 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(System.currentTimeMillis());
FragmentManager manager = getFragmentManager();
pvd.show(manager, "ProfileViewDialog");
+ } else if (item.getTitle().equals(MainApp.gs(R.string.eatingsoon))) {
+ DefaultValueHelper defHelper = new DefaultValueHelper();
+ double target = defHelper.determineEatingSoonTT(profile.getUnits());
+ TempTarget tempTarget = new TempTarget()
+ .date(System.currentTimeMillis())
+ .duration(defHelper.determineEatingSoonTTDuration())
+ .reason(MainApp.gs(R.string.eatingsoon))
+ .source(Source.USER)
+ .low(target)
+ .high(target);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ } else if (item.getTitle().equals(MainApp.gs(R.string.activity))) {
+ DefaultValueHelper defHelper = new DefaultValueHelper();
+ double target = defHelper.determineActivityTT(profile.getUnits());
+ TempTarget tempTarget = new TempTarget()
+ .date(now())
+ .duration(defHelper.determineActivityTTDuration())
+ .reason(MainApp.gs(R.string.activity))
+ .source(Source.USER)
+ .low(target)
+ .high(target);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ } else if (item.getTitle().equals(MainApp.gs(R.string.hypo))) {
+ DefaultValueHelper defHelper = new DefaultValueHelper();
+ double target = defHelper.determineHypoTT(profile.getUnits());
+ TempTarget tempTarget = new TempTarget()
+ .date(now())
+ .duration(defHelper.determineHypoTTDuration())
+ .reason(MainApp.gs(R.string.activity))
+ .source(Source.USER)
+ .low(target)
+ .high(target);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
+ } else if (item.getTitle().equals(MainApp.gs(R.string.custom))) {
+ NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
+ final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
+ temptarget.executeTempTarget = true;
+ newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
+ newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
+ } else if (item.getTitle().equals(MainApp.gs(R.string.cancel))) {
+ TempTarget tempTarget = new TempTarget()
+ .source(Source.USER)
+ .date(now())
+ .duration(0)
+ .low(0)
+ .high(0);
+ TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
}
return super.onContextItemSelected(item);
@@ -590,6 +646,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
String units = MainApp.getConfigBuilder().getProfileUnits();
FragmentManager manager = getFragmentManager();
+ // try to fix https://fabric.io/nightscout3/android/apps/info.nightscout.androidaps/issues/5aca7a1536c7b23527eb4be7?time=last-seven-days
+ // https://stackoverflow.com/questions/14860239/checking-if-state-is-saved-before-committing-a-fragmenttransaction
+ if (manager.isStateSaved())
+ return;
switch (v.getId()) {
case R.id.overview_accepttempbutton:
onClickAcceptTemp();
@@ -672,12 +732,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
private void onClickAcceptTemp() {
Profile profile = MainApp.getConfigBuilder().getProfile();
+ Context context = getContext();
+
+ if (context == null) return;
if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && profile != null) {
LoopPlugin.getPlugin().invoke("Accept temp button", false);
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
@@ -777,7 +840,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (wizard.superBolus) {
final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (loopPlugin.isEnabled(PluginType.LOOP)) {
- loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
+ loopPlugin.superBolusTo(System.currentTimeMillis() + T.hours(2).msecs());
MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
}
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
@@ -816,7 +879,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
});
} else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
}
FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard"));
}
@@ -836,6 +899,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
sLoopHandler.removeCallbacksAndMessages(null);
unregisterForContextMenu(apsModeView);
unregisterForContextMenu(activeProfileView);
+ unregisterForContextMenu(tempTargetView);
}
@Override
@@ -849,6 +913,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
registerForContextMenu(apsModeView);
registerForContextMenu(activeProfileView);
+ registerForContextMenu(tempTargetView);
updateGUI("onResume");
}
@@ -981,16 +1046,19 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (timeView != null) { //must not exists
timeView.setText(DateUtil.timeString(new Date()));
}
+
+ updateNotifications();
+
+ pumpStatusLayout.setVisibility(View.GONE);
+ loopStatusLayout.setVisibility(View.GONE);
+
if (!MainApp.getConfigBuilder().isProfileValid("Overview")) {
pumpStatusView.setText(R.string.noprofileset);
pumpStatusLayout.setVisibility(View.VISIBLE);
- loopStatusLayout.setVisibility(View.GONE);
return;
}
- pumpStatusLayout.setVisibility(View.GONE);
loopStatusLayout.setVisibility(View.VISIBLE);
- updateNotifications();
CareportalFragment.updateAge(getActivity(), sage, iage, cage, pbage);
BgReading actualBG = DatabaseHelper.actualBg();
BgReading lastBG = DatabaseHelper.lastBg();
@@ -1017,12 +1085,18 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
arrowView.setTextColor(color);
GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData();
if (glucoseStatus != null) {
- deltaView.setText("Δ " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
+ if (deltaView != null)
+ deltaView.setText("Δ " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units);
+ if (deltaShortView != null)
+ deltaShortView.setText(Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units));
if (avgdeltaView != null)
avgdeltaView.setText("øΔ15m: " + Profile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) +
" øΔ40m: " + Profile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units));
} else {
- deltaView.setText("Δ " + MainApp.gs(R.string.notavailable));
+ if (deltaView != null)
+ deltaView.setText("Δ " + MainApp.gs(R.string.notavailable));
+ if (deltaShortView != null)
+ deltaShortView.setText("---");
if (avgdeltaView != null)
avgdeltaView.setText("");
}
@@ -1126,15 +1200,12 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
} else {
basalText = DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h";
}
- baseBasalView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String fullText = MainApp.gs(R.string.pump_basebasalrate_label) + ": " + DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h\n";
- if (activeTemp != null) {
- fullText += MainApp.gs(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull();
- }
- OKDialog.show(getActivity(), MainApp.gs(R.string.basal), fullText, null);
+ baseBasalView.setOnClickListener(v -> {
+ String fullText = MainApp.gs(R.string.pump_basebasalrate_label) + ": " + DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h\n";
+ if (activeTemp != null) {
+ fullText += MainApp.gs(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull();
}
+ OKDialog.show(getActivity(), MainApp.gs(R.string.basal), fullText, null);
});
} else {
@@ -1163,22 +1234,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) {
extendedBolusText = DecimalFormatter.to2Decimal(extendedBolus.absoluteRate()) + "U/h";
}
- extendedBolusView.setText(extendedBolusText);
- extendedBolusView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- OKDialog.show(getActivity(), MainApp.gs(R.string.extendedbolus), extendedBolus.toString(), null);
- }
- });
-
} else {
if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) {
extendedBolusText = extendedBolus.toString();
}
- extendedBolusView.setText(extendedBolusText);
+ }
+ extendedBolusView.setText(extendedBolusText);
+ if (Config.NSCLIENT || Config.G5UPLOADER) {
+ extendedBolusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.extendedbolus), extendedBolus.toString(), null));
}
if (extendedBolusText.equals(""))
- extendedBolusView.setVisibility(View.GONE);
+ extendedBolusView.setVisibility(Config.NSCLIENT || Config.G5UPLOADER ? View.INVISIBLE : View.GONE);
else
extendedBolusView.setVisibility(View.VISIBLE);
}
@@ -1186,17 +1252,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
activeProfileView.setText(MainApp.getConfigBuilder().getProfileName());
activeProfileView.setBackgroundColor(Color.GRAY);
- tempTargetView.setOnLongClickListener(view -> {
- view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
- final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
- temptarget.executeTempTarget = true;
- newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
- newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
- return true;
- });
- tempTargetView.setLongClickable(true);
-
// QuickWizard button
QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive();
if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) {
@@ -1256,7 +1311,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
flag &= ~Paint.STRIKE_THRU_TEXT_FLAG;
bgView.setPaintFlags(flag);
- timeAgoView.setText(DateUtil.minAgo(lastBG.date));
+ if (timeAgoView != null)
+ timeAgoView.setText(DateUtil.minAgo(lastBG.date));
+ if (timeAgoShortView != null)
+ timeAgoShortView.setText("(" + DateUtil.minAgoShort(lastBG.date) + ")");
// iob
TreatmentsPlugin.getPlugin().updateTotalIOBTreatments();
@@ -1297,7 +1355,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
cobView.setText(cobText);
}
- final boolean predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ boolean predictionsAvailable;
+ if (Config.APS)
+ predictionsAvailable = finalLastRun != null && finalLastRun.request.hasPredictions;
+ else if (Config.NSCLIENT)
+ predictionsAvailable = true;
+ else
+ predictionsAvailable = false;
+ final boolean finalPredictionsAvailable = predictionsAvailable;
+
// pump status from ns
if (pumpDeviceStatusView != null) {
pumpDeviceStatusView.setText(NSDeviceStatus.getInstance().getPumpStatus());
@@ -1316,6 +1382,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
uploaderDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus(), null));
}
+ // Sensitivity
+ if (sensitivityView != null) {
+ AutosensResult lastAutosensResult = IobCobCalculatorPlugin.getPlugin().detectSensitivityWithLock(IobCobCalculatorPlugin.getPlugin().oldestDataAvailable(), System.currentTimeMillis());
+ if (lastAutosensResult != null)
+ sensitivityView.setText(String.format("%.0f%%", lastAutosensResult.ratio * 100));
+ else
+ sensitivityView.setText("");
+ }
+
// ****** GRAPH *******
new Thread(() -> {
@@ -1331,18 +1406,25 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final long toTime;
final long fromTime;
final long endTime;
- if (predictionsAvailable && SP.getBoolean("showprediction", false)) {
- int predHours = (int) (Math.ceil(finalLastRun.constraintsProcessed.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
+
+ APSResult apsResult = null;
+
+ if (finalPredictionsAvailable && SP.getBoolean("showprediction", false)) {
+ if (Config.APS)
+ apsResult = finalLastRun.constraintsProcessed;
+ else
+ apsResult = NSDeviceStatus.getAPSResult();
+ int predHours = (int) (Math.ceil(apsResult.getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000));
predHours = Math.min(2, predHours);
predHours = Math.max(0, predHours);
hoursToFetch = rangeToDisplay - predHours;
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific
- fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
- endTime = toTime + predHours * 60 * 60 * 1000L;
+ fromTime = toTime - T.hours(hoursToFetch).msecs();
+ endTime = toTime + T.hours(predHours).msecs();
} else {
hoursToFetch = rangeToDisplay;
toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific
- fromTime = toTime - hoursToFetch * 60 * 60 * 1000L;
+ fromTime = toTime - T.hours(hoursToFetch).msecs();
endTime = toTime;
}
@@ -1358,9 +1440,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
graphData.addInRangeArea(fromTime, endTime, lowLine, highLine);
// **** BG ****
- if (predictionsAvailable && SP.getBoolean("showprediction", false))
+ if (finalPredictionsAvailable && SP.getBoolean("showprediction", false))
graphData.addBgReadings(fromTime, toTime, lowLine, highLine,
- finalLastRun.constraintsProcessed.getPredictions());
+ apsResult.getPredictions());
else
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null);
@@ -1412,7 +1494,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
secondGraphData.addDeviations(fromTime, now, useDevForScale, 1d);
if (SP.getBoolean("showratios", false))
secondGraphData.addRatio(fromTime, now, useRatioForScale, 1d);
- if (SP.getBoolean("showdevslope", false))
+ if (SP.getBoolean("showdevslope", false) && MainApp.devBranch)
secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1d);
// **** NOW line ****
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java
index 67e494a76d..3b787fd768 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
@@ -50,6 +50,7 @@ public class OverviewPlugin extends PluginBase {
.pluginName(R.string.overview)
.shortName(R.string.overview_shortname)
.preferencesId(R.xml.pref_overview)
+ .description(R.string.description_overview)
);
String storedData = SP.getString("QuickWizard", "[]");
try {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java
deleted file mode 100644
index 49ccf9fbfb..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package info.nightscout.androidaps.plugins.Overview.events;
-
-import info.nightscout.androidaps.events.Event;
-
-/**
- * Created by mike on 02.07.2017.
- */
-
-public class EventSetWakeLock extends Event {
- public boolean lock = false;
-
- public EventSetWakeLock(boolean val) {
- lock = val;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java
index 1c8b27c113..20feb76124 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphData/GraphData.java
@@ -49,7 +49,8 @@ import info.nightscout.utils.Round;
public class GraphData {
private GraphView graph;
- public double maxY = 0;
+ public double maxY = Double.MIN_VALUE;
+ public double minY = Double.MAX_VALUE;
private List bgReadingsArray;
private String units;
private List series = new ArrayList<>();
@@ -63,7 +64,7 @@ public class GraphData {
}
public void addBgReadings(long fromTime, long toTime, double lowLine, double highLine, List predictions) {
- double maxBgValue = 0d;
+ double maxBgValue = Double.MIN_VALUE;
bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true);
List bgListArray = new ArrayList<>();
@@ -93,10 +94,8 @@ public class GraphData {
maxY = maxBgValue;
+ minY = 0;
// set manual y bounds to have nice steps
- graph.getViewport().setMaxY(maxY);
- graph.getViewport().setMinY(0);
- graph.getViewport().setYAxisBoundsManual(true);
graph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines);
addSeries(new PointsWithLabelGraphSeries<>(bg));
@@ -136,7 +135,9 @@ public class GraphData {
double lastBaseBasal = 0;
double lastTempBasal = 0;
for (long time = fromTime; time < toTime; time += 60 * 1000L) {
- BasalData basalData = IobCobCalculatorPlugin.getPlugin().getBasalData(time);
+ Profile profile = MainApp.getConfigBuilder().getProfile(time);
+ if (profile == null) continue;
+ BasalData basalData = IobCobCalculatorPlugin.getPlugin().getBasalData(profile, time);
double baseBasalValue = basalData.basal;
double absoluteLineValue = baseBasalValue;
double tempBasalValue = 0;
@@ -333,7 +334,7 @@ public class GraphData {
public void addIob(long fromTime, long toTime, boolean useForScale, double scale) {
FixedLineGraphSeries iobSeries;
List iobArray = new ArrayList<>();
- Double maxIobValueFound = 0d;
+ Double maxIobValueFound = Double.MIN_VALUE;
double lastIob = 0;
Scale iobScale = new Scale();
@@ -359,8 +360,10 @@ public class GraphData {
iobSeries.setColor(MainApp.gc(R.color.iob));
iobSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = maxIobValueFound;
+ minY = -maxIobValueFound;
+ }
iobScale.setMultiplier(maxY * scale / maxIobValueFound);
@@ -404,8 +407,10 @@ public class GraphData {
cobSeries.setColor(MainApp.gc(R.color.cob));
cobSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = maxCobValueFound;
+ minY = 0;
+ }
cobScale.setMultiplier(maxY * scale / maxCobValueFound);
@@ -436,9 +441,18 @@ public class GraphData {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
int color = MainApp.gc(R.color.deviationblack); // "="
- if (autosensData.pastSensitivity.equals("C")) color = MainApp.gc(R.color.deviationgrey);
- if (autosensData.pastSensitivity.equals("+")) color = MainApp.gc(R.color.deviationgreen);
- if (autosensData.pastSensitivity.equals("-")) color = MainApp.gc(R.color.deviationred);
+ if (autosensData.type.equals("") || autosensData.type.equals("non-meal")) {
+ if (autosensData.pastSensitivity.equals("C"))
+ color = MainApp.gc(R.color.deviationgrey);
+ if (autosensData.pastSensitivity.equals("+"))
+ color = MainApp.gc(R.color.deviationgreen);
+ if (autosensData.pastSensitivity.equals("-"))
+ color = MainApp.gc(R.color.deviationred);
+ } else if (autosensData.type.equals("uam")) {
+ color = MainApp.gc(R.color.uam);
+ } else if (autosensData.type.equals("csf")) {
+ color = MainApp.gc(R.color.deviationgrey);
+ }
devArray.add(new DeviationDataPoint(time, autosensData.deviation, color, devScale));
maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation));
}
@@ -455,8 +469,10 @@ public class GraphData {
}
});
- if (useForScale)
+ if (useForScale) {
maxY = maxDevValueFound;
+ minY = -maxY;
+ }
devScale.setMultiplier(maxY * scale / maxDevValueFound);
@@ -467,14 +483,16 @@ public class GraphData {
public void addRatio(long fromTime, long toTime, boolean useForScale, double scale) {
LineGraphSeries ratioSeries;
List ratioArray = new ArrayList<>();
- Double maxRatioValueFound = 0d;
- Scale ratioScale = new Scale(-1d);
+ Double maxRatioValueFound = Double.MIN_VALUE;
+ Double minRatioValueFound = Double.MAX_VALUE;
+ Scale ratioScale = new Scale();
for (long time = fromTime; time <= toTime; time += 5 * 60 * 1000L) {
AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getAutosensData(time);
if (autosensData != null) {
- ratioArray.add(new ScaledDataPoint(time, autosensData.autosensRatio, ratioScale));
- maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio));
+ ratioArray.add(new ScaledDataPoint(time, autosensData.autosensResult.ratio - 1, ratioScale));
+ maxRatioValueFound = Math.max(maxRatioValueFound, autosensData.autosensResult.ratio - 1);
+ minRatioValueFound = Math.min(minRatioValueFound, autosensData.autosensResult.ratio - 1);
}
}
@@ -485,8 +503,10 @@ public class GraphData {
ratioSeries.setColor(MainApp.gc(R.color.ratio));
ratioSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = maxRatioValueFound;
+ minY = minRatioValueFound;
+ }
ratioScale.setMultiplier(maxY * scale / maxRatioValueFound);
@@ -527,8 +547,10 @@ public class GraphData {
dsMinSeries.setColor(MainApp.gc(R.color.devslopeneg));
dsMinSeries.setThickness(3);
- if (useForScale)
+ if (useForScale) {
maxY = Math.max(maxFromMaxValueFound, maxFromMinValueFound);
+ minY = -maxY;
+ }
dsMaxScale.setMultiplier(maxY * scale / maxFromMaxValueFound);
dsMinScale.setMultiplier(maxY * scale / maxFromMinValueFound);
@@ -582,6 +604,10 @@ public class GraphData {
}
}
+ graph.getViewport().setMaxY(Round.ceilTo(maxY, 1d));
+ graph.getViewport().setMinY(Round.floorTo(minY, 1d));
+ graph.getViewport().setYAxisBoundsManual(true);
+
// draw it
graph.onDataChanged(false, false);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java
index 5f39cedafe..4a87a8508e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/PointsWithLabelGraphSeries.java
@@ -312,20 +312,20 @@ public class PointsWithLabelGraphSeries e
mPaint.setStrokeWidth(5);
canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint);
}
- } else if (value.getShape() == Shape.OPENAPSOFFLINE) {
+ } else if (value.getShape() == Shape.OPENAPSOFFLINE && value.getDuration() != 0) {
mPaint.setStrokeWidth(0);
if (value.getLabel() != null) {
- mPaint.setStrokeWidth(0);
- mPaint.setTextSize(scaledTextSize);
- mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
+ //mPaint.setStrokeWidth(0);
+ //mPaint.setTextSize(scaledTextSize);
+ //mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
Rect bounds = new Rect();
- mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
- mPaint.setStyle(Paint.Style.STROKE);
+ //mPaint.getTextBounds(value.getLabel(), 0, value.getLabel().length(), bounds);
+ mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
float px = endX;
float py = graphTop + 50;
- canvas.drawText(value.getLabel(), px, py, mPaint);
+ //canvas.drawText(value.getLabel(), px, py, mPaint);
mPaint.setStrokeWidth(5);
- canvas.drawRect(px - 3, bounds.top + py - 3, xpluslength + 3, bounds.bottom + py + 3, mPaint);
+ canvas.drawRect(px - 3, graphTop, xpluslength + 3, graphTop + graphHeight, mPaint);
}
} else if (value.getShape() == Shape.GENERALWITHDURATION) {
mPaint.setStrokeWidth(0);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java
index 787545965c..8c91e2896b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java
@@ -42,6 +42,8 @@ public class Notification {
public static final int APPROACHING_DAILY_LIMIT = 11;
public static final int NSCLIENT_NO_WRITE_PERMISSION = 12;
public static final int MISSING_SMS_PERMISSION = 13;
+ public static final int PUMPERROR = 14;
+ public static final int WRONGSERIALNUMBER = 15;
public static final int NSANNOUNCEMENT = 18;
public static final int NSALARM = 19;
@@ -59,6 +61,13 @@ public class Notification {
public static final int ZERO_VALUE_IN_PROFILE = 31;
public static final int PROFILE_SWITCH_MISSING = 32;
public static final int NOT_ENG_MODE_OR_RELEASE = 33;
+ public static final int WRONG_PUMP_PASSWORD = 34;
+ public static final int PERMISSION_STORAGE = 35;
+ public static final int PERMISSION_LOCATION = 36;
+ public static final int PERMISSION_BATTERY = 37;
+ public static final int PERMISSION_SMS = 38;
+ public static final int MAXIMUM_BASAL_VALUE_REPLACED = 39;
+
public int id;
public Date date;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java
index 1b1487bbaa..895b99a43e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/NotificationRecyclerViewAdapter.java
@@ -42,9 +42,12 @@ public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.O)
+ .description(R.string.description_persistent_notification)
);
this.ctx = ctx;
}
@@ -65,7 +75,7 @@ public class PersistentNotificationPlugin extends PluginBase {
protected void onStart() {
MainApp.bus().register(this);
createNotificationChannel();
- updateNotification();
+ triggerNotificationUpdate();
super.onStart();
}
@@ -84,20 +94,22 @@ public class PersistentNotificationPlugin extends PluginBase {
@Override
protected void onStop() {
MainApp.bus().unregister(this);
- NotificationManager mNotificationManager =
- (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
- mNotificationManager.cancel(ONGOING_NOTIFICATION_ID);
+ MainApp.instance().stopService(new Intent(MainApp.instance(), DummyService.class));
}
- private void updateNotification() {
+ private void triggerNotificationUpdate() {
+ MainApp.instance().startService(new Intent(MainApp.instance(), DummyService.class));
+ }
+
+ Notification updateNotification() {
if (!isEnabled(PluginType.GENERAL)) {
- return;
+ return null;
}
String line1 = "";
if (MainApp.getConfigBuilder().getActiveProfileInterface() == null || !MainApp.getConfigBuilder().isProfileValid("Notificiation"))
- return;
+ return null;
String units = MainApp.getConfigBuilder().getProfileUnits();
@@ -142,9 +154,15 @@ public class PersistentNotificationPlugin extends PluginBase {
builder.setOngoing(true);
builder.setOnlyAlertOnce(true);
builder.setCategory(NotificationCompat.CATEGORY_STATUS);
- builder.setSmallIcon(R.drawable.ic_notification);
- Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), R.mipmap.blueowl);
- builder.setLargeIcon(largeIcon);
+ if (Config.NSCLIENT || Config.G5UPLOADER){
+ builder.setSmallIcon(R.drawable.nsclient_smallicon);
+ Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), R.mipmap.yellowowl);
+ builder.setLargeIcon(largeIcon);
+ } else {
+ builder.setSmallIcon(R.drawable.ic_notification);
+ Bitmap largeIcon = BitmapFactory.decodeResource(ctx.getResources(), R.mipmap.blueowl);
+ builder.setLargeIcon(largeIcon);
+ }
builder.setContentTitle(line1);
builder.setContentText(line2);
builder.setSubText(line3);
@@ -165,7 +183,7 @@ public class PersistentNotificationPlugin extends PluginBase {
android.app.Notification notification = builder.build();
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, notification);
-
+ return notification;
}
private String deltastring(double deltaMGDL, double deltaMMOL, String units) {
@@ -187,42 +205,42 @@ public class PersistentNotificationPlugin extends PluginBase {
@Subscribe
public void onStatusEvent(final EventPreferenceChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventTreatmentChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventTempBasalChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventExtendedBolusChange ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventNewBG ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventNewBasalProfile ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventInitializationChanged ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
@Subscribe
public void onStatusEvent(final EventRefreshOverview ev) {
- updateNotification();
+ triggerNotificationUpdate();
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java
index 6c22a2e9ce..18060ba1ec 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java
@@ -4,7 +4,6 @@ package info.nightscout.androidaps.plugins.ProfileLocal;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
-import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
@@ -23,7 +22,6 @@ 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.ProfileStore;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.interfaces.PumpDescription;
@@ -109,41 +107,32 @@ public class LocalProfileFragment extends SubscriberFragment {
mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
- mgdlView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
- LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl;
- mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
- doEdit();
- }
+ mgdlView.setOnClickListener(v -> {
+ LocalProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
+ LocalProfilePlugin.getPlugin().mmol = !LocalProfilePlugin.getPlugin().mgdl;
+ mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
+ doEdit();
});
- mmolView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked();
- LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol;
- mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
- doEdit();
- }
+ mmolView.setOnClickListener(v -> {
+ LocalProfilePlugin.getPlugin().mmol = mmolView.isChecked();
+ LocalProfilePlugin.getPlugin().mgdl = !LocalProfilePlugin.getPlugin().mmol;
+ mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
+ doEdit();
});
- profileswitchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
- profileswitch.executeProfileSwitch = true;
- newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
- newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
- }
+ profileswitchButton.setOnClickListener(view -> {
+ NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
+ profileswitch.executeProfileSwitch = true;
+ newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
+ newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
});
resetButton.setOnClickListener(view -> {
LocalProfilePlugin.getPlugin().loadSettings();
mgdlView.setChecked(LocalProfilePlugin.getPlugin().mgdl);
mmolView.setChecked(LocalProfilePlugin.getPlugin().mmol);
- diaView.setParams(LocalProfilePlugin.getPlugin().dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch);
+ diaView.setParams(LocalProfilePlugin.getPlugin().dia, 5d, 12d, 0.1d, new DecimalFormat("0.0"), false, textWatch);
icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.gs(R.string.nsprofileview_ic_label) + ":", LocalProfilePlugin.getPlugin().ic, null, 0.5, 50d, 0.1d, new DecimalFormat("0.0"), save);
isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.gs(R.string.nsprofileview_isf_label) + ":", LocalProfilePlugin.getPlugin().isf, null, 0.5, 500d, 0.1d, new DecimalFormat("0.0"), save);
basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.gs(R.string.nsprofileview_basal_label) + ": " + getSumLabel(), LocalProfilePlugin.getPlugin().basal, null, pumpDescription.basalMinimumRate, 10, 0.01d, new DecimalFormat("0.00"), save);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java
index c132196228..8d4e2d6a36 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java
@@ -13,6 +13,7 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -63,6 +64,7 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface {
.fragmentClass(LocalProfileFragment.class.getName())
.pluginName(R.string.localprofile)
.shortName(R.string.localprofile_shortname)
+ .description(R.string.description_profile_local)
);
loadSettings();
}
@@ -81,6 +83,7 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface {
edited = false;
if (Config.logPrefsChange)
log.debug("Storing settings: " + getRawProfile().getData().toString());
+ MainApp.bus().post(new EventProfileStoreChanged());
}
public synchronized void loadSettings() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java
index dca9b183a3..6cc9fdf98e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java
@@ -79,11 +79,14 @@ public class NSProfileFragment extends SubscriberFragment {
public void onStatusEvent(final EventNSProfileUpdateGUI ev) {
Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(() -> updateGUI());
+ activity.runOnUiThread(() -> { synchronized (NSProfileFragment.this) { updateGUI(); } });
}
@Override
protected void updateGUI() {
+ if (noProfile == null || profileSpinner == null)
+ return;
+
ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile();
if (profileStore != null) {
ArrayList profileList = profileStore.getProfileList();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java
index dfd62cda70..404aff0608 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
@@ -16,6 +16,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -43,11 +44,12 @@ public class NSProfilePlugin extends PluginBase implements ProfileInterface {
super(new PluginDescription()
.mainType(PluginType.PROFILE)
.fragmentClass(NSProfileFragment.class.getName())
- .pluginName(R.string.profileviewer)
+ .pluginName(R.string.nsprofile)
.shortName(R.string.profileviewer_shortname)
.alwaysEnabled(Config.NSCLIENT)
.alwayVisible(Config.NSCLIENT)
.showInList(!Config.NSCLIENT)
+ .description(R.string.description_profile_nightscout)
);
loadNSProfile();
}
@@ -68,6 +70,7 @@ public class NSProfilePlugin extends PluginBase implements ProfileInterface {
profile = new ProfileStore(newProfile.getData());
storeNSProfile();
MainApp.bus().post(new EventNSProfileUpdateGUI());
+ MainApp.bus().post(new EventProfileStoreChanged());
}
private void storeNSProfile() {
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 b3b2226705..1315413e38 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
@@ -73,34 +73,25 @@ public class SimpleProfileFragment extends SubscriberFragment {
targetlowView.setText(SimpleProfilePlugin.getPlugin().targetLow.toString());
targethighView.setText(SimpleProfilePlugin.getPlugin().targetHigh.toString());
- mgdlView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SimpleProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
- SimpleProfilePlugin.getPlugin().mmol = !SimpleProfilePlugin.getPlugin().mgdl;
- mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol);
- SimpleProfilePlugin.getPlugin().storeSettings();
- }
+ mgdlView.setOnClickListener(v -> {
+ SimpleProfilePlugin.getPlugin().mgdl = mgdlView.isChecked();
+ SimpleProfilePlugin.getPlugin().mmol = !SimpleProfilePlugin.getPlugin().mgdl;
+ mmolView.setChecked(SimpleProfilePlugin.getPlugin().mmol);
+ SimpleProfilePlugin.getPlugin().storeSettings();
});
- mmolView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SimpleProfilePlugin.getPlugin().mmol = mmolView.isChecked();
- SimpleProfilePlugin.getPlugin().mgdl = !SimpleProfilePlugin.getPlugin().mmol;
- mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl);
- SimpleProfilePlugin.getPlugin().storeSettings();
- }
+ mmolView.setOnClickListener(v -> {
+ SimpleProfilePlugin.getPlugin().mmol = mmolView.isChecked();
+ SimpleProfilePlugin.getPlugin().mgdl = !SimpleProfilePlugin.getPlugin().mmol;
+ mgdlView.setChecked(SimpleProfilePlugin.getPlugin().mgdl);
+ SimpleProfilePlugin.getPlugin().storeSettings();
});
- profileswitchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
- profileswitch.executeProfileSwitch = true;
- newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
- newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
- }
+ profileswitchButton.setOnClickListener(view -> {
+ NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
+ profileswitch.executeProfileSwitch = true;
+ newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
+ newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
});
TextWatcher textWatch = new TextWatcher() {
@@ -152,20 +143,17 @@ public class SimpleProfileFragment extends SubscriberFragment {
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- boolean isValid = SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile));
- if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) {
- profileswitchButton.setVisibility(View.GONE);
- } else {
- profileswitchButton.setVisibility(View.VISIBLE);
- }
- if (isValid)
- invalidProfile.setVisibility(View.GONE);
- else
- invalidProfile.setVisibility(View.VISIBLE);
+ activity.runOnUiThread(() -> {
+ boolean isValid = SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid(MainApp.gs(R.string.simpleprofile));
+ if (!ConfigBuilderPlugin.getActivePump().isInitialized() || ConfigBuilderPlugin.getActivePump().isSuspended() || !isValid) {
+ profileswitchButton.setVisibility(View.GONE);
+ } else {
+ profileswitchButton.setVisibility(View.VISIBLE);
}
+ if (isValid)
+ invalidProfile.setVisibility(View.GONE);
+ else
+ invalidProfile.setVisibility(View.VISIBLE);
});
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java
index adff378819..bb669289ee 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java
@@ -14,6 +14,7 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.androidaps.events.EventProfileStoreChanged;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -51,6 +52,7 @@ public class SimpleProfilePlugin extends PluginBase implements ProfileInterface
.fragmentClass(SimpleProfileFragment.class.getName())
.pluginName(R.string.simpleprofile)
.shortName(R.string.simpleprofile_shortname)
+ .description(R.string.description_profile_simple)
);
loadSettings();
}
@@ -73,6 +75,7 @@ public class SimpleProfilePlugin extends PluginBase implements ProfileInterface
createConvertedProfile();
if (Config.logPrefsChange)
log.debug("Storing settings: " + getRawProfile().getData().toString());
+ MainApp.bus().post(new EventProfileStoreChanged());
}
private void loadSettings() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
index 3cf4557e54..a16ffbda05 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java
@@ -1,8 +1,11 @@
package info.nightscout.androidaps.plugins.PumpCombo;
+import android.content.DialogInterface;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.crashlytics.android.answers.CustomEvent;
@@ -28,6 +31,7 @@ import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventRefreshOverview;
@@ -57,8 +61,6 @@ import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHi
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistoryRequest;
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Tdd;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
-import info.nightscout.androidaps.queue.Callback;
-import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
@@ -166,6 +168,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
.fragmentClass(ComboFragment.class.getName())
.pluginName(R.string.combopump)
.shortName(R.string.combopump_shortname)
+ .description(R.string.description_pump_combo)
);
ruffyScripter = new RuffyScripter(MainApp.instance().getApplicationContext());
}
@@ -192,6 +195,32 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return MainApp.gs(R.string.combo_pump_state_running);
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
+
@Override
public boolean isInitialized() {
return pump.initialized;
@@ -352,6 +381,11 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
// trigger a connect, which will update state and check history
CommandResult stateResult = runCommand(null, 1, ruffyScripter::readPumpState);
+ if (stateResult.invalidSetup) {
+ MainApp.bus().post(new EventNewNotification(
+ new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_invalid_setup), Notification.URGENT)));
+ return;
+ }
if (!stateResult.success) {
return;
}
@@ -421,9 +455,6 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return pump.basalProfile.hourlyRates[currentHour];
}
- private static BolusProgressReporter nullBolusProgressReporter = (state, percent, delivered) -> {
- };
-
private static BolusProgressReporter bolusProgressReporter = (state, percent, delivered) -> {
EventOverviewBolusProgress event = EventOverviewBolusProgress.getInstance();
switch (state) {
@@ -464,7 +495,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return deliverBolus(detailedBolusInfo);
} else {
// no bolus required, carb only treatment
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
bolusingEvent.t = new Treatment();
@@ -549,12 +580,14 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
return new PumpEnactResult().success(true).enacted(false);
}
- BolusProgressReporter progressReporter = detailedBolusInfo.isSMB ? nullBolusProgressReporter : bolusProgressReporter;
+ Treatment treatment = new Treatment();
+ treatment.isSMB = detailedBolusInfo.isSMB;
+ EventOverviewBolusProgress.getInstance().t = treatment;
// start bolus delivery
scripterIsBolusing = true;
runCommand(null, 0,
- () -> ruffyScripter.deliverBolus(detailedBolusInfo.insulin, progressReporter));
+ () -> ruffyScripter.deliverBolus(detailedBolusInfo.insulin, bolusProgressReporter));
scripterIsBolusing = false;
// Note that the result of the issued bolus command is not checked. If there was
@@ -653,7 +686,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
dbi.source = Source.PUMP;
dbi.insulin = lastPumpBolus.amount;
try {
- boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi);
+ boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, false);
if (!treatmentCreated) {
log.error("Adding treatment record overrode an existing record: " + dbi);
if (dbi.isSMB) {
@@ -1152,7 +1185,8 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
dbi.source = Source.PUMP;
dbi.insulin = pumpBolus.amount;
dbi.eventType = CareportalEvent.CORRECTIONBOLUS;
- if (TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi)) {
+ if (TreatmentsPlugin.getPlugin().getService().getPumpRecordById(dbi.pumpId) == null) {
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(dbi, false);
updated = true;
}
}
@@ -1356,7 +1390,7 @@ public class ComboPlugin extends PluginBase implements PumpInterface, Constraint
private boolean validBasalRateProfileSelectedOnPump = true;
@Override
- public Constraint isLoopInvokationAllowed(Constraint value) {
+ public Constraint isLoopInvocationAllowed(Constraint value) {
if (!validBasalRateProfileSelectedOnPump)
value.set(false, MainApp.gs(R.string.novalidbasalrate), this);
return value;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java
index 9da5d4d6fa..b595d13d28 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/CommandResult.java
@@ -5,10 +5,11 @@ import android.support.annotation.Nullable;
import java.util.LinkedList;
import java.util.List;
-import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.Bolus;
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.history.PumpHistory;
public class CommandResult {
+ /** True if a condition indicating a broken pump setup/configuration is detected */
+ public boolean invalidSetup;
/** Whether the command was executed successfully. */
public boolean success;
/** State of the pump *after* command execution. */
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java
index 1e7e542e5f..5b569e479e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/RuffyScripter.java
@@ -281,10 +281,10 @@ public class RuffyScripter implements RuffyCommands {
log.debug("Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms");
} catch (CommandException e) {
log.error("CommandException running command", e);
- activeCmd.getResult().success = false;
+ cmd.getResult().success = false;
} catch (Exception e) {
log.error("Unexpected exception running cmd", e);
- activeCmd.getResult().success = false;
+ cmd.getResult().success = false;
}
}, cmd.getClass().getSimpleName());
long executionStart = System.currentTimeMillis();
@@ -328,6 +328,7 @@ public class RuffyScripter implements RuffyCommands {
if (unparsableMenuEncountered) {
log.error("UnparsableMenuEncountered flagged, aborting command");
cmdThread.interrupt();
+ activeCmd.getResult().invalidSetup = true;
activeCmd.getResult().success = false;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java
index e55fb4d010..654861fddb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ruffyscripter/commands/ReadQuickInfoCommand.java
@@ -39,17 +39,19 @@ public class ReadQuickInfoCommand extends BaseCommand {
// read bolus records
int totalRecords = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.TOTAL_RECORD);
int record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
- while (true) {
- bolusHistory.add(readBolusRecord());
- if (bolusHistory.size() == numberOfBolusRecordsToRetrieve || record == totalRecords) {
- break;
+ if (record > 0) {
+ while (true) {
+ bolusHistory.add(readBolusRecord());
+ if (bolusHistory.size() == numberOfBolusRecordsToRetrieve || record == totalRecords) {
+ break;
+ }
+ // advance to next record
+ scripter.pressDownKey();
+ while (record == (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD)) {
+ scripter.waitForScreenUpdate();
+ }
+ record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
}
- // advance to next record
- scripter.pressDownKey();
- while (record == (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD)) {
- scripter.waitForScreenUpdate();
- }
- record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD);
}
if (log.isDebugEnabled()) {
if (!result.history.bolusHistory.isEmpty()) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java
index 903be558b9..1f51979126 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/AbstractDanaRPlugin.java
@@ -59,6 +59,7 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte
.pluginName(R.string.danarspump)
.shortName(R.string.danarpump_shortname)
.preferencesId(R.xml.pref_danars)
+ .description(R.string.description_pump_dana_r)
);
}
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 b11cd87278..7288602d65 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java
@@ -11,6 +11,7 @@ import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -29,11 +30,14 @@ import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.events.EventTempBasalChange;
+import info.nightscout.androidaps.interfaces.PluginType;
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.DanaRUserOptionsActivity;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
+import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.events.EventQueueChanged;
import info.nightscout.utils.DateUtil;
@@ -88,6 +92,8 @@ public class DanaRFragment extends SubscriberFragment {
LinearLayout pumpStatusLayout;
@BindView(R.id.overview_pumpstatus)
TextView pumpStatusView;
+ @BindView(R.id.danar_user_options)
+ Button danar_user_options;
public DanaRFragment() {
}
@@ -138,6 +144,9 @@ public class DanaRFragment extends SubscriberFragment {
startActivity(new Intent(getContext(), TDDStatsActivity.class));
}
+ @OnClick(R.id.danar_user_options)
+ void onUserOptionsClick() { startActivity(new Intent(getContext(), DanaRUserOptionsActivity.class)); }
+
@OnClick(R.id.danar_btconnection)
void onBtConnectionClick() {
log.debug("Clicked connect to pump");
@@ -153,19 +162,24 @@ public class DanaRFragment extends SubscriberFragment {
activity.runOnUiThread(
new Runnable() {
@Override
- public void run() {
- if (c.sStatus == EventPumpStatusChanged.CONNECTING)
- btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s");
- else if (c.sStatus == EventPumpStatusChanged.CONNECTED)
- btConnectionView.setText("{fa-bluetooth}");
- else if (c.sStatus == EventPumpStatusChanged.DISCONNECTED)
- btConnectionView.setText("{fa-bluetooth-b}");
+ public void run() {
+ synchronized(DanaRFragment.this){
- if (!status.equals("")) {
- pumpStatusView.setText(status);
- pumpStatusLayout.setVisibility(View.VISIBLE);
- } else {
- pumpStatusLayout.setVisibility(View.GONE);
+ if(btConnectionView == null || pumpStatusView == null || pumpStatusLayout == null ) return;
+
+ if (c.sStatus == EventPumpStatusChanged.CONNECTING)
+ btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s");
+ else if (c.sStatus == EventPumpStatusChanged.CONNECTED)
+ btConnectionView.setText("{fa-bluetooth}");
+ else if (c.sStatus == EventPumpStatusChanged.DISCONNECTED)
+ btConnectionView.setText("{fa-bluetooth-b}");
+
+ if (!status.equals("")) {
+ pumpStatusView.setText(status);
+ pumpStatusLayout.setVisibility(View.VISIBLE);
+ } else {
+ pumpStatusLayout.setVisibility(View.GONE);
+ }
}
}
}
@@ -202,69 +216,96 @@ public class DanaRFragment extends SubscriberFragment {
@SuppressLint("SetTextI18n")
@Override
public void run() {
- DanaRPump pump = DanaRPump.getInstance();
- if (pump.lastConnection != 0) {
- Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
- int agoMin = (int) (agoMsec / 60d / 1000d);
- lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.gs(R.string.minago), agoMin) + ")");
- SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
- }
- if (pump.lastBolusTime.getTime() != 0) {
- Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
- double agoHours = agoMsec / 60d / 60d / 1000d;
- if (agoHours < 6) // max 6h back
- lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U");
- else lastBolusView.setText("");
- }
+ synchronized(DanaRFragment.this) {
+ if (!isBound()) return;
- dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
- SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
- basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
- // DanaRPlugin, DanaRKoreanPlugin
- if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
- if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
- tempBasalView.setText(TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
- } else {
- tempBasalView.setText("");
+ DanaRPump pump = DanaRPump.getInstance();
+ if (pump.lastConnection != 0) {
+ Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
+ int agoMin = (int) (agoMsec / 60d / 1000d);
+ lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.gs(R.string.minago), agoMin) + ")");
+ SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
}
- } else {
- // v2 plugin
- if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
- tempBasalView.setText(TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
- } else {
- tempBasalView.setText("");
+ if (pump.lastBolusTime.getTime() != 0) {
+ Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
+ double agoHours = agoMsec / 60d / 60d / 1000d;
+ if (agoHours < 6) // max 6h back
+ lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U");
+ else lastBolusView.setText("");
}
- }
- ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
- if (activeExtendedBolus != null) {
- extendedBolusView.setText(activeExtendedBolus.toString());
- } else {
- extendedBolusView.setText("");
- }
- reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U");
- SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
- batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
- SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
- iobView.setText(pump.iob + " U");
- if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) {
- firmwareView.setText(String.format(MainApp.gs(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
- } else {
- firmwareView.setText("OLD");
- }
- basalStepView.setText("" + pump.basalStep);
- bolusStepView.setText("" + pump.bolusStep);
- serialNumberView.setText("" + pump.serialNumber);
- if (queueView != null) {
- Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
- if (status.toString().equals("")) {
- queueView.setVisibility(View.GONE);
+
+ dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
+ SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
+ basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
+ // DanaRPlugin, DanaRKoreanPlugin
+ if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
+ if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
+ tempBasalView.setText(TreatmentsPlugin.getPlugin().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
+ } else {
+ tempBasalView.setText("");
+ }
} else {
- queueView.setVisibility(View.VISIBLE);
- queueView.setText(status);
+ // v2 plugin
+ if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
+ tempBasalView.setText(TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
+ } else {
+ tempBasalView.setText("");
+ }
+ }
+ ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(System.currentTimeMillis());
+ if (activeExtendedBolus != null) {
+ extendedBolusView.setText(activeExtendedBolus.toString());
+ } else {
+ extendedBolusView.setText("");
+ }
+ reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / 300 U");
+ SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
+ batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
+ SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
+ iobView.setText(pump.iob + " U");
+ if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) {
+ firmwareView.setText(String.format(MainApp.gs(R.string.danar_model), pump.model, pump.protocol, pump.productCode));
+ } else {
+ firmwareView.setText("OLD");
+ }
+ basalStepView.setText("" + pump.basalStep);
+ bolusStepView.setText("" + pump.bolusStep);
+ serialNumberView.setText("" + pump.serialNumber);
+ if (queueView != null) {
+ Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
+ if (status.toString().equals("")) {
+ queueView.setVisibility(View.GONE);
+ } else {
+ queueView.setVisibility(View.VISIBLE);
+ queueView.setText(status);
+ }
+ }
+ //hide user options button if not an RS pump
+ boolean isKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class) != null && MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginType.PUMP);
+ if (isKorean) {
+ danar_user_options.setVisibility(View.GONE);
}
}
}
});
}
+ private boolean isBound() {
+ return lastConnectionView != null
+ && lastBolusView != null
+ && dailyUnitsView != null
+ && basaBasalRateView != null
+ && tempBasalView != null
+ && extendedBolusView != null
+ && reservoirView != null
+ && batteryView != null
+ && iobView != null
+ && firmwareView != null
+ && basalStepView != null
+ && bolusStepView != null
+ && serialNumberView != null
+ && danar_user_options != null
+ && queueView != null;
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java
index 279a93340f..144107779d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java
@@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.PumpDanaR;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -18,6 +21,7 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
@@ -78,6 +82,31 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
pumpDescription.needsManualTDDLoad = true;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
@Override
protected void onStart() {
Context context = MainApp.instance().getApplicationContext();
@@ -170,7 +199,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
detailedBolusInfo.insulin = t.insulin;
detailedBolusInfo.date = System.currentTimeMillis();
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
return result;
} else {
PumpEnactResult result = new PumpEnactResult();
@@ -379,4 +408,9 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
public PumpEnactResult loadEvents() {
return null; // no history, not needed
}
+
+ @Override
+ public PumpEnactResult setUserOptions() {
+ return sExecutionService.setUserOptions();
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java
index 1e346695e3..d9bc947b84 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java
@@ -161,7 +161,7 @@ public class DanaRPump {
public int lowReservoirRate;
public int cannulaVolume;
public int refillAmount;
-
+ public byte[] userOptionsFrompump;
public double initialBolusAmount;
// Bolus settings
public int bolusCalculationOption;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRUserOptionsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRUserOptionsActivity.java
new file mode 100644
index 0000000000..b4930a2a1a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRUserOptionsActivity.java
@@ -0,0 +1,202 @@
+package info.nightscout.androidaps.plugins.PumpDanaR.activities;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.Switch;
+
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DecimalFormat;
+
+import info.nightscout.androidaps.Constants;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventInitializationChanged;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
+import info.nightscout.utils.NumberPicker;
+
+/**
+ * Created by Rumen Georgiev on 5/31/2018.
+ */
+
+public class DanaRUserOptionsActivity extends Activity {
+ private static Logger log = LoggerFactory.getLogger(DanaRUserOptionsActivity.class);
+
+ Switch timeFormat;
+ Switch buttonScroll;
+ Switch beep;
+ RadioGroup pumpAlarm;
+ RadioButton pumpAlarmSound;
+ RadioButton pumpAlarmVibrate;
+ RadioButton pumpAlarmBoth;
+ Switch pumpUnits;
+ NumberPicker screenTimeout;
+ NumberPicker backlightTimeout;
+ NumberPicker shutdown;
+ NumberPicker lowReservoir;
+ Button saveToPumpButton;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ MainApp.bus().register(this);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ MainApp.bus().unregister(this);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.danar_user_options);
+
+ timeFormat = (Switch) findViewById(R.id.danar_timeformat);
+ buttonScroll = (Switch) findViewById(R.id.danar_buttonscroll);
+ beep = (Switch) findViewById(R.id.danar_beep);
+ pumpAlarm = (RadioGroup) findViewById(R.id.danar_pumpalarm);
+ pumpAlarmSound = (RadioButton) findViewById(R.id.danar_pumpalarm_sound);
+ pumpAlarmVibrate = (RadioButton) findViewById(R.id.danar_pumpalarm_vibrate);
+ pumpAlarmBoth = (RadioButton) findViewById(R.id.danar_pumpalarm_both);
+ screenTimeout = (NumberPicker) findViewById(R.id.danar_screentimeout);
+ backlightTimeout = (NumberPicker) findViewById(R.id.danar_backlight);
+ pumpUnits = (Switch) findViewById(R.id.danar_units);
+ shutdown = (NumberPicker) findViewById(R.id.danar_shutdown);
+ lowReservoir = (NumberPicker) findViewById(R.id.danar_lowreservoir);
+ saveToPumpButton = (Button) findViewById(R.id.save_user_options);
+
+ saveToPumpButton.setOnClickListener(v -> onSaveClick());
+
+ DanaRPump pump = DanaRPump.getInstance();
+ //used for debugging
+ log.debug("UserOptionsLoaded:" + (System.currentTimeMillis() - pump.lastConnection) / 1000 + " s ago"
+ + "\ntimeDisplayType:" + pump.timeDisplayType
+ + "\nbuttonScroll:" + pump.buttonScrollOnOff
+ + "\ntimeDisplayType:" + pump.timeDisplayType
+ + "\nlcdOnTimeSec:" + pump.lcdOnTimeSec
+ + "\nbacklight:" + pump.backlightOnTimeSec
+ + "\npumpUnits:" + pump.units
+ + "\nlowReservoir:" + pump.lowReservoirRate);
+
+ screenTimeout.setParams((double) pump.lcdOnTimeSec, 5d, 240d, 5d, new DecimalFormat("1"), false);
+ backlightTimeout.setParams((double) pump.backlightOnTimeSec, 1d, 60d, 1d, new DecimalFormat("1"), false);
+ shutdown.setParams((double) pump.shutdownHour, 0d, 24d, 1d, new DecimalFormat("1"), true);
+ lowReservoir.setParams((double) pump.lowReservoirRate, 10d, 60d, 10d, new DecimalFormat("10"), false);
+ switch (pump.beepAndAlarm) {
+ case 0x01:
+ pumpAlarmSound.setChecked(true);
+ break;
+ case 0x02:
+ pumpAlarmVibrate.setChecked(true);
+ break;
+ case 0x11:
+ pumpAlarmBoth.setChecked(true);
+ break;
+ case 0x101:
+ pumpAlarmSound.setChecked(true);
+ beep.setChecked(true);
+ break;
+ case 0x110:
+ pumpAlarmVibrate.setChecked(true);
+ beep.setChecked(true);
+ break;
+ case 0x111:
+ pumpAlarmBoth.setChecked(true);
+ beep.setChecked(true);
+ break;
+ }
+ if (pump.lastSettingsRead == 0)
+ log.debug("No settings loaded from pump!");
+ else
+ setData();
+ }
+
+ public void setData() {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ timeFormat.setChecked(pump.timeDisplayType != 0);
+ buttonScroll.setChecked(pump.buttonScrollOnOff != 0);
+ beep.setChecked(pump.beepAndAlarm > 4);
+ screenTimeout.setValue((double) pump.lcdOnTimeSec);
+ backlightTimeout.setValue((double) pump.backlightOnTimeSec);
+ pumpUnits.setChecked(pump.getUnits() != null && pump.getUnits().equals(Constants.MMOL));
+ shutdown.setValue((double) pump.shutdownHour);
+ lowReservoir.setValue((double) pump.lowReservoirRate);
+ }
+
+ @Subscribe
+ public void onEventInitializationChanged(EventInitializationChanged ignored) {
+ runOnUiThread(this::setData);
+ }
+
+ public void onSaveClick() {
+ boolean isRS = MainApp.getSpecificPlugin(DanaRSPlugin.class) != null && MainApp.getSpecificPlugin(DanaRSPlugin.class).isEnabled(PluginType.PUMP);
+ boolean isDanaR = MainApp.getSpecificPlugin(DanaRPlugin.class) != null && MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginType.PUMP);
+ boolean isDanaRv2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class) != null && MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginType.PUMP);
+ if (!isRS && !isDanaR && !isDanaRv2) {
+ //exit if pump is not DanaRS, Dana!, or DanaR with upgraded firmware
+ return;
+ }
+ DanaRPump pump = DanaRPump.getInstance();
+
+ if (timeFormat.isChecked())
+ pump.timeDisplayType = 1;
+ else
+ pump.timeDisplayType = 0;
+ if (buttonScroll.isChecked())
+ pump.buttonScrollOnOff = 1;
+ else
+ pump.buttonScrollOnOff = 0;
+
+ pump.beepAndAlarm = 1; // default
+ if (pumpAlarmSound.isChecked()) pump.beepAndAlarm = 1;
+ else if (pumpAlarmVibrate.isChecked()) pump.beepAndAlarm = 2;
+ else if (pumpAlarmBoth.isChecked()) pump.beepAndAlarm = 3;
+ if (beep.isChecked()) pump.beepAndAlarm += 4;
+
+
+ // step is 5 seconds
+ int screenTimeoutValue = !screenTimeout.getText().isEmpty() ? (Integer.parseInt(screenTimeout.getText().toString()) / 5) * 5: 5;
+ if (screenTimeoutValue > 4 && screenTimeoutValue < 241) {
+ pump.lcdOnTimeSec = screenTimeoutValue;
+ } else {
+ pump.lcdOnTimeSec = 5;
+ }
+ int backlightTimeoutValue = !backlightTimeout.getText().isEmpty() ? Integer.parseInt(backlightTimeout.getText().toString()): 1;
+ if (backlightTimeoutValue > 0 && backlightTimeoutValue < 61) {
+ pump.backlightOnTimeSec = backlightTimeoutValue;
+ }
+ if (pumpUnits.isChecked()) {
+ pump.units = 1;
+ } else {
+ pump.units = 0;
+ }
+ int shutDownValue = !shutdown.getText().isEmpty() ? Integer.parseInt(shutdown.getText().toString()) : 0;
+ if (shutDownValue > -1 && shutDownValue < 25) {
+ pump.shutdownHour = shutDownValue;
+ } else {
+ pump.shutdownHour = 0;
+ }
+ int lowReservoirValue = !lowReservoir.getText().isEmpty() ? (Integer.parseInt(lowReservoir.getText().toString()) * 10) / 10 : 10;
+ if (lowReservoirValue > 9 && lowReservoirValue < 51) {
+ pump.lowReservoirRate = lowReservoirValue;
+ } else
+ pump.lowReservoirRate = 10;
+
+ MainApp.getConfigBuilder().getCommandQueue().setUserOptions(null);
+ finish();
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java
index 10d2c0b091..4b90b8f02d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java
@@ -60,6 +60,7 @@ public class MessageHashTable {
put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE
put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S
put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S
+ put(new MsgSetUserOptions()); // 0x330B CMD_SETTING_USER_OPTIONS_S
put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S
put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE
put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetUserOptions.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetUserOptions.java
new file mode 100644
index 0000000000..407b19da8d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetUserOptions.java
@@ -0,0 +1,52 @@
+package info.nightscout.androidaps.plugins.PumpDanaR.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import android.support.v4.internal.view.SupportMenu;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+/**
+ * Created by mike on 05.07.2016.
+ */
+public class MsgSetUserOptions extends MessageBase {
+
+ private static Logger log = LoggerFactory.getLogger(MsgSetUserOptions.class);
+
+ public boolean done;
+
+ public MsgSetUserOptions() {
+ SetCommand(0x330B);
+ DanaRPump pump = DanaRPump.getInstance();
+ if (pump.userOptionsFrompump == null) {
+ // No options set -> Exitting
+ log.debug("NO USER OPTIONS LOADED EXITTING!");
+ return;
+ }
+ pump.userOptionsFrompump[0] = (byte) (pump.timeDisplayType == 1 ? 0 : 1);
+ pump.userOptionsFrompump[1] = (byte) pump.buttonScrollOnOff;
+ pump.userOptionsFrompump[2] = (byte) pump.beepAndAlarm;
+ pump.userOptionsFrompump[3] = (byte) pump.lcdOnTimeSec;
+ pump.userOptionsFrompump[4] = (byte) pump.backlightOnTimeSec;
+ pump.userOptionsFrompump[5] = (byte) pump.selectedLanguage;
+ pump.userOptionsFrompump[8] = (byte) pump.units;
+ pump.userOptionsFrompump[9] = (byte) pump.shutdownHour;
+ pump.userOptionsFrompump[27] = (byte) pump.lowReservoirRate;
+ for(int i=0; i 24h 0 -> 12h
+ pump.buttonScrollOnOff = bytes[1] == (byte) 1 ? 1 : 0; // 1 -> ON, 0-> OFF
+ pump.beepAndAlarm = bytes[2]; // 1 -> Sound on alarm 2-> Vibrate on alarm 3-> Both on alarm 5-> Sound + beep 6-> vibrate + beep 7-> both + beep Beep adds 4
+ pump.lcdOnTimeSec = bytes[3] & 255;
+ pump.backlightOnTimeSec = bytes[4] & 255;
+ pump.selectedLanguage = bytes[5]; // on DanaRv2 is that needed ?
+ pump.units = bytes[8];
+ pump.shutdownHour = bytes[9];
+ pump.lowReservoirRate = bytes[32] & 255;
+ /* int selectableLanguage1 = bytes[10];
+ int selectableLanguage2 = bytes[11];
+ int selectableLanguage3 = bytes[12];
+ int selectableLanguage4 = bytes[13];
+ int selectableLanguage5 = bytes[14];
+ */
+ if (Config.logDanaMessageDetail) {
+
+ log.debug("timeDisplayType: " + pump.timeDisplayType);
+ log.debug("Button scroll: " + pump.buttonScrollOnOff);
+ log.debug("BeepAndAlarm: " + pump.beepAndAlarm);
+ log.debug("screen timeout: " + pump.lcdOnTimeSec);
+ log.debug("Backlight: " + pump.backlightOnTimeSec);
+ log.debug("Selected language: " + pump.selectedLanguage);
+ log.debug("Units: " + pump.getUnits());
+ log.debug("Shutdown: " + pump.shutdownHour);
+ log.debug("Low reservoir: " + pump.lowReservoirRate);
+ }
}
+ public static byte[] getDataBytes(byte[] bytes, int start, int len) {
+ if (bytes == null) {
+ return null;
+ }
+ byte[] ret = new byte[len];
+ System.arraycopy(bytes, start + 6, ret, 0, len);
+ return ret;
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java
index b7201c1163..e4c2933d43 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/AbstractDanaRExecutionService.java
@@ -65,6 +65,11 @@ public abstract class AbstractDanaRExecutionService extends Service {
protected final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
+ protected long lastWrongPumpPassword = 0;
+
+ protected long lastApproachingDailyLimit = 0;
+
+
public abstract boolean updateBasalsInPump(final Profile profile);
public abstract void connect();
@@ -87,6 +92,7 @@ public abstract class AbstractDanaRExecutionService extends Service {
public abstract boolean extendedBolusStop();
+ public abstract PumpEnactResult setUserOptions();
protected BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
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 65a5d22d36..ea4dec25fb 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
@@ -18,17 +18,17 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
-import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventPreferenceChange;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
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.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
-import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
@@ -45,6 +45,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetUserOptions;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose;
@@ -54,15 +55,17 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingUserOptions;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
-import info.nightscout.utils.ToastUtils;
public class DanaRExecutionService extends AbstractDanaRExecutionService{
@@ -97,7 +100,11 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService{
public void connect() {
if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.wrongpumppassword), R.raw.error);
+ if(System.currentTimeMillis() > lastWrongPumpPassword + 30 * 1000) {
+ Notification notification = new Notification(Notification.WRONG_PUMP_PASSWORD, MainApp.gs(R.string.wrongpumppassword), Notification.URGENT);
+ notification.soundId = R.raw.error;
+ lastWrongPumpPassword = System.currentTimeMillis();
+ }
return;
}
@@ -161,7 +168,19 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService{
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus)));
long now = System.currentTimeMillis();
- if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) {
+ mDanaRPump.lastConnection = now;
+
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+ PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
+ if (profile != null && Math.abs(mDanaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
+ mSerialIOThread.sendMessage(new MsgSettingBasal());
+ if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
+ MainApp.bus().post(new EventProfileSwitchChange());
+ }
+ }
+
+ if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
@@ -173,6 +192,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService{
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
+ mSerialIOThread.sendMessage(new MsgSettingUserOptions());
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
@@ -186,15 +206,17 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService{
mDanaRPump.lastSettingsRead = now;
}
- mDanaRPump.lastConnection = now;
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
NSUpload.uploadDeviceStatus();
if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
- Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ if(System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
+ Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(reportFail));
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ lastApproachingDailyLimit = System.currentTimeMillis();
+ }
}
} catch (Exception e) {
log.error("Unhandled exception", e);
@@ -390,4 +412,13 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService{
log.debug("EventAppExit finished");
}
+ public PumpEnactResult setUserOptions() {
+ if (!isConnected())
+ return new PumpEnactResult().success(false);
+ SystemClock.sleep(300);
+ MsgSetUserOptions msg = new MsgSetUserOptions();
+ mSerialIOThread.sendMessage(msg);
+ SystemClock.sleep(200);
+ return new PumpEnactResult().success(!msg.failed);
+ }
}
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 092febec61..49edb6b096 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java
@@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.PumpDanaRKorean;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -23,6 +26,7 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
@@ -45,7 +49,8 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
}
public DanaRKoreanPlugin() {
- super();
+ pluginDescription.description(R.string.description_pump_dana_r_korean);
+
log = LoggerFactory.getLogger(DanaRKoreanPlugin.class);
useExtendedBoluses = SP.getBoolean("danar_useextended", false);
@@ -79,6 +84,32 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
pumpDescription.needsManualTDDLoad = true;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
+
@Override
protected void onStart() {
Context context = MainApp.instance().getApplicationContext();
@@ -171,7 +202,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
detailedBolusInfo.insulin = t.insulin;
detailedBolusInfo.date = System.currentTimeMillis();
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
return result;
} else {
PumpEnactResult result = new PumpEnactResult();
@@ -380,4 +411,9 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
public PumpEnactResult loadEvents() {
return null; // no history, not needed
}
+
+ @Override
+ public PumpEnactResult setUserOptions() {
+ return null;
+ }
}
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 b9cc704aba..0f4afa4314 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
@@ -18,11 +18,12 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
-import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventPreferenceChange;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
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.Dialogs.BolusProgressDialog;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@@ -38,6 +39,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetSingleBasalProfil
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal;
@@ -53,9 +55,10 @@ import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread;
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.plugins.Treatments.Treatment;
+import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
-import info.nightscout.utils.ToastUtils;
public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
@@ -105,7 +108,11 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
public void connect() {
if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.wrongpumppassword), R.raw.error);
+ if(System.currentTimeMillis() > lastWrongPumpPassword + 30 * 1000) {
+ Notification notification = new Notification(Notification.WRONG_PUMP_PASSWORD, MainApp.gs(R.string.wrongpumppassword), Notification.URGENT);
+ notification.soundId = R.raw.error;
+ lastWrongPumpPassword = System.currentTimeMillis();
+ }
return;
}
@@ -169,7 +176,19 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingbolusstatus)));
long now = System.currentTimeMillis();
- if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) {
+ mDanaRPump.lastConnection = now;
+
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+ PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
+ if (profile != null && Math.abs(mDanaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
+ mSerialIOThread.sendMessage(new MsgSettingBasal());
+ if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
+ MainApp.bus().post(new EventProfileSwitchChange());
+ }
+ }
+
+ if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingMeal());
@@ -191,15 +210,17 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
mDanaRPump.lastSettingsRead = now;
}
- mDanaRPump.lastConnection = now;
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
NSUpload.uploadDeviceStatus();
if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
- Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ if(System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
+ Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(reportFail));
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ lastApproachingDailyLimit = System.currentTimeMillis();
+ }
}
} catch (Exception e) {
log.error("Unhandled exception", e);
@@ -320,4 +341,9 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
return true;
}
+ @Override
+ public PumpEnactResult setUserOptions() {
+ return null;
+ }
+
}
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 1cbb256c1e..36edf1e94f 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
@@ -2,10 +2,13 @@ package info.nightscout.androidaps.plugins.PumpDanaRS;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -26,8 +29,6 @@ import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
-import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start;
-import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
@@ -38,6 +39,7 @@ import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@@ -46,13 +48,16 @@ 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.PumpDanaR.comm.RecordTypes;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start;
import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSDeviceChange;
import info.nightscout.androidaps.plugins.PumpDanaRS.services.DanaRSService;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
+import info.nightscout.utils.T;
/**
* Created by mike on 03.09.2017.
@@ -83,6 +88,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
.pluginName(R.string.danarspump)
.shortName(R.string.danarspump_shortname)
.preferencesId(R.xml.pref_danars)
+ .description(R.string.description_pump_dana_rs)
);
pumpDescription.isBolusCapable = true;
@@ -146,6 +152,31 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
MainApp.bus().unregister(this);
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
@@ -223,6 +254,11 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
return danaRSService.loadEvents();
}
+ @Override
+ public PumpEnactResult setUserOptions() {
+ return danaRSService.setUserSettings();
+ }
+
// Constraints interface
@Override
@@ -376,6 +412,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
double carbs = detailedBolusInfo.carbs;
detailedBolusInfo.carbs = 0;
int carbTime = detailedBolusInfo.carbTime;
+ if (carbTime == 0) carbTime--; // better set 1 min back to prevents clash with insulin
detailedBolusInfo.carbTime = 0;
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
@@ -384,7 +421,7 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
t.isSMB = detailedBolusInfo.isSMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0)
- connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + carbTime * 60 * 1000, t);
+ connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t);
PumpEnactResult result = new PumpEnactResult();
result.success = connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep;
result.bolusDelivered = t.insulin;
@@ -480,8 +517,12 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
// Convert duration from minutes to hours
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
- // use special APS temp basal call ... 100+/15min .... 100-/30min
- result = setHighTempBasalPercent(percentRate);
+ if (percentRate == 0 && durationInMinutes > 30) {
+ result = setTempBasalPercent(percentRate, durationInMinutes, profile, false);
+ } else {
+ // use special APS temp basal call ... 100+/15min .... 100-/30min
+ result = setHighTempBasalPercent(percentRate);
+ }
if (!result.success) {
log.error("setTempBasalAbsolute: Failed to set hightemp basal");
return result;
@@ -758,4 +799,5 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte
public PumpEnactResult loadTDDs() {
return loadHistory(RecordTypes.RECORD_TYPE_DAILY);
}
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java
index 319a64f713..3b6bcaf099 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java
@@ -62,13 +62,15 @@ public class BLEScanActivity extends AppCompatActivity {
super.onResume();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
-
- if (mBluetoothLeScanner == null) {
- mBluetoothAdapter.enable();
+ if (mBluetoothAdapter != null) {
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
+
+ if (mBluetoothLeScanner == null) {
+ mBluetoothAdapter.enable();
+ mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
+ }
+ startScan();
}
- startScan();
}
@Override
@@ -79,11 +81,13 @@ public class BLEScanActivity extends AppCompatActivity {
}
private void startScan() {
- mBluetoothLeScanner.startScan(mBleScanCallback);
+ if (mBluetoothLeScanner != null)
+ mBluetoothLeScanner.startScan(mBleScanCallback);
}
private void stopScan() {
- mBluetoothLeScanner.stopScan(mBleScanCallback);
+ if (mBluetoothLeScanner != null)
+ mBluetoothLeScanner.stopScan(mBleScanCallback);
}
private void addBleDevice(BluetoothDevice device) {
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 181584df8e..b8c8aaf2b4 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
@@ -133,14 +133,14 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet {
break;
case DanaRPump.BOLUS:
detailedBolusInfo.insulin = param1 / 100d;
- boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
status = "BOLUS " + DateUtil.timeString(datetime);
break;
case DanaRPump.DUALBOLUS:
detailedBolusInfo.insulin = param1 / 100d;
- newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
status = "DUALBOLUS " + DateUtil.timeString(datetime);
@@ -183,7 +183,7 @@ public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet {
emptyCarbsInfo.date = datetime.getTime();
emptyCarbsInfo.source = Source.PUMP;
emptyCarbsInfo.pumpId = datetime.getTime();
- newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo);
+ newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo, false);
log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g");
status = "CARBS " + DateUtil.timeString(datetime);
break;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java
index e5d9374f32..40577aaa5d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java
@@ -23,7 +23,14 @@ public class DanaRS_Packet_Option_Set_User_Option extends DanaRS_Packet {
@Override
public byte[] getRequestParams() {
DanaRPump pump = DanaRPump.getInstance();
-
+ log.debug("UserOptions:"+(System.currentTimeMillis() - pump.lastConnection)/1000+" s ago"
+ +"\ntimeDisplayType:"+pump.timeDisplayType
+ +"\nbuttonScroll:"+pump.buttonScrollOnOff
+ +"\ntimeDisplayType:"+pump.timeDisplayType
+ +"\nlcdOnTimeSec:"+pump.lcdOnTimeSec
+ +"\nbacklight:"+pump.backlightOnTimeSec
+ +"\npumpUnits:"+pump.units
+ +"\nlowReservoir:"+pump.lowReservoirRate);
byte[] request = new byte[13];
request[0] = (byte) (pump.timeDisplayType & 0xff);
request[1] = (byte) (pump.buttonScrollOnOff & 0xff);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
index b552026279..9df2ebc0a1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
@@ -20,13 +20,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
+import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingHelperActivity;
@@ -34,6 +34,7 @@ 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;
import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPairingSuccess;
+import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
/**
@@ -45,11 +46,11 @@ public class BLEComm {
private static final long WRITE_DELAY_MILLIS = 50;
- public static String UART_READ_UUID = "0000fff1-0000-1000-8000-00805f9b34fb";
- public static String UART_WRITE_UUID = "0000fff2-0000-1000-8000-00805f9b34fb";
+ private static String UART_READ_UUID = "0000fff1-0000-1000-8000-00805f9b34fb";
+ private static String UART_WRITE_UUID = "0000fff2-0000-1000-8000-00805f9b34fb";
- private byte PACKET_START_BYTE = (byte) 0xA5;
- private byte PACKET_END_BYTE = (byte) 0x5A;
+ private final byte PACKET_START_BYTE = (byte) 0xA5;
+ private final byte PACKET_END_BYTE = (byte) 0x5A;
private static BLEComm instance = null;
public static BLEComm getInstance(DanaRSService service) {
@@ -58,16 +59,13 @@ public class BLEComm {
return instance;
}
- private final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture> scheduledDisconnection = null;
private DanaRS_Packet processsedMessage = null;
- private ArrayList mSendQueue = new ArrayList<>();
+ private final ArrayList mSendQueue = new ArrayList<>();
private BluetoothManager mBluetoothManager = null;
private BluetoothAdapter mBluetoothAdapter = null;
- private BluetoothDevice mBluetoothDevice = null;
- private String mBluetoothDeviceAddress = null;
private String mBluetoothDeviceName = null;
private BluetoothGatt mBluetoothGatt = null;
@@ -79,7 +77,7 @@ public class BLEComm {
private DanaRSService service;
- BLEComm(DanaRSService service) {
+ private BLEComm(DanaRSService service) {
this.service = service;
initialize();
}
@@ -138,15 +136,13 @@ public class BLEComm {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
- log.debug("Device not found. Unable to connect.");
+ log.debug("Device not found. Unable to connect from: " + from);
return false;
}
- log.debug("Trying to create a new connection.");
+ log.debug("Trying to create a new connection from: " + from);
mBluetoothGatt = device.connectGatt(service.getApplicationContext(), false, mGattCallback);
setCharacteristicNotification(getUARTReadBTGattChar(), true);
- mBluetoothDevice = device;
- mBluetoothDeviceAddress = address;
mBluetoothDeviceName = device.getName();
return true;
}
@@ -174,7 +170,7 @@ public class BLEComm {
SystemClock.sleep(2000);
}
- public void close() {
+ public synchronized void close() {
log.debug("BluetoothAdapter close");
if (mBluetoothGatt == null) {
return;
@@ -184,15 +180,8 @@ public class BLEComm {
mBluetoothGatt = null;
}
- public BluetoothDevice getConnectDevice() {
- return mBluetoothDevice;
- }
- public String getConnectDeviceAddress() {
- return mBluetoothDeviceAddress;
- }
-
- public String getConnectDeviceName() {
+ private String getConnectDeviceName() {
return mBluetoothDeviceName;
}
@@ -229,33 +218,25 @@ public class BLEComm {
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
log.debug("onCharacteristicChanged" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
addToReadBuffer(characteristic.getValue());
- new Thread(new Runnable() {
- @Override
- public void run() {
- readDataParsing();
- }
- }).start();
+ new Thread(() -> readDataParsing()).start();
}
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
log.debug("onCharacteristicWrite" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
- new Thread(new Runnable() {
- @Override
- public void run() {
- synchronized (mSendQueue) {
- // after message sent, check if there is the rest of the message waiting and send it
- if (mSendQueue.size() > 0) {
- byte[] bytes = mSendQueue.get(0);
- mSendQueue.remove(0);
- writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
- }
+ new Thread(() -> {
+ synchronized (mSendQueue) {
+ // after message sent, check if there is the rest of the message waiting and send it
+ if (mSendQueue.size() > 0) {
+ byte[] bytes = mSendQueue.get(0);
+ mSendQueue.remove(0);
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
}
}
}).start();
}
};
- public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
+ private synchronized void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
log.debug("setCharacteristicNotification");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR");
@@ -266,7 +247,7 @@ public class BLEComm {
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
- public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
+ public synchronized void readCharacteristic(BluetoothGattCharacteristic characteristic) {
log.debug("readCharacteristic");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR");
@@ -277,41 +258,39 @@ public class BLEComm {
mBluetoothGatt.readCharacteristic(characteristic);
}
- public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
- new Thread(new Runnable() {
- public void run() {
- SystemClock.sleep(WRITE_DELAY_MILLIS);
+ private synchronized void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
+ new Thread(() -> {
+ SystemClock.sleep(WRITE_DELAY_MILLIS);
- if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
- log.debug("BluetoothAdapter not initialized_ERROR");
- isConnecting = false;
- isConnected = false;
- return;
- }
-
- characteristic.setValue(data);
- characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
- log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
- mBluetoothGatt.writeCharacteristic(characteristic);
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ log.debug("BluetoothAdapter not initialized_ERROR");
+ isConnecting = false;
+ isConnected = false;
+ return;
}
+
+ characteristic.setValue(data);
+ characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
+ log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
+ mBluetoothGatt.writeCharacteristic(characteristic);
}).start();
}
- public BluetoothGattCharacteristic getUARTReadBTGattChar() {
+ private BluetoothGattCharacteristic getUARTReadBTGattChar() {
if (UART_Read == null) {
UART_Read = new BluetoothGattCharacteristic(UUID.fromString(UART_READ_UUID), BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, 0);
}
return UART_Read;
}
- public BluetoothGattCharacteristic getUARTWriteBTGattChar() {
+ private BluetoothGattCharacteristic getUARTWriteBTGattChar() {
if (UART_Write == null) {
UART_Write = new BluetoothGattCharacteristic(UUID.fromString(UART_WRITE_UUID), BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, 0);
}
return UART_Write;
}
- public List getSupportedGattServices() {
+ private List getSupportedGattServices() {
log.debug("getSupportedGattServices");
if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
log.debug("BluetoothAdapter not initialized_ERROR");
@@ -329,7 +308,7 @@ public class BLEComm {
if (gattServices == null) {
return;
}
- String uuid = null;
+ String uuid;
for (BluetoothGattService gattService : gattServices) {
List gattCharacteristics = gattService.getCharacteristics();
@@ -346,7 +325,7 @@ public class BLEComm {
}
}
- private byte[] readBuffer = new byte[1024];
+ private final byte[] readBuffer = new byte[1024];
private int bufferLength = 0;
private void addToReadBuffer(byte[] buffer) {
@@ -445,14 +424,25 @@ public class BLEComm {
SendPairingRequest();
}
+ } else if (inputBuffer.length == 6 && inputBuffer[2] == 'P' && inputBuffer[3] == 'U' && inputBuffer[4] == 'M' && inputBuffer[5] == 'P') {
+ log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(inputBuffer));
+ mSendQueue.clear();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.gs(R.string.pumperror)));
+ NSUpload.uploadError(MainApp.gs(R.string.pumperror));
+ Notification n = new Notification(Notification.PUMPERROR, MainApp.gs(R.string.pumperror), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(n));
} else if (inputBuffer.length == 6 && inputBuffer[2] == 'B' && inputBuffer[3] == 'U' && inputBuffer[4] == 'S' && inputBuffer[5] == 'Y') {
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(inputBuffer));
mSendQueue.clear();
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.gs(R.string.pumpbusy)));
} else {
+ // ERROR in response, wrong serial number
log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(inputBuffer));
mSendQueue.clear();
MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.gs(R.string.connectionerror)));
+ SP.remove(MainApp.gs(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName);
+ Notification n = new Notification(Notification.WRONGSERIALNUMBER, MainApp.gs(R.string.wrongpassword), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(n));
}
break;
// 2nd packet, pairing key
@@ -634,7 +624,7 @@ public class BLEComm {
writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
}
- protected void SendPumpCheck() {
+ private void SendPumpCheck() {
// 1st message sent to pump after connect
byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, getConnectDeviceName());
log.debug(">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes));
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
index a6afd0aeb0..fae0430adc 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
@@ -19,15 +19,17 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
-import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventInitializationChanged;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
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.Dialogs.BolusProgressDialog;
-import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
+import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
+import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
@@ -69,8 +71,12 @@ import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_
import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_Delivery_Complete;
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_Get_User_Option;
import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_Pump_Time;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_User_Option;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@@ -87,6 +93,7 @@ public class DanaRSService extends Service {
private Treatment bolusingTreatment = null;
private long lastHistoryFetched = 0;
+ private long lastApproachingDailyLimit = 0;
public DanaRSService() {
try {
@@ -133,8 +140,51 @@ public class DanaRSService extends Service {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingtempbasalstatus)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+ danaRPump.lastConnection = System.currentTimeMillis();
+
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+ PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
+ if (profile != null && Math.abs(danaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate()); // basal profile, basalStep, maxBasal
+ if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
+ MainApp.bus().post(new EventProfileSwitchChange());
+ }
+ }
+
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
+
+ long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ if (Math.abs(timeDiff) > 3) {
+ if (Math.abs(timeDiff) > 60*60*1.5) {
+ log.debug("Pump time difference: " + timeDiff + " seconds - large difference");
+ //If time-diff is very large, warn user until we can synchronize history readings properly
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.error);
+ i.putExtra("status", MainApp.gs(R.string.largetimediff));
+ i.putExtra("title", MainApp.gs(R.string.largetimedifftitle));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+
+ //deinitialize pump
+ danaRPump.lastConnection = 0;
+ MainApp.bus().post(new EventDanaRNewStatus());
+ MainApp.bus().post(new EventInitializationChanged());
+ return;
+ } else {
+ waitForWholeMinute(); // Dana can set only whole minute
+ // add 10sec to be sure we are over minute (will be cutted off anyway)
+ bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date(DateUtil.now() + T.secs(10).msecs())));
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
+ timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ }
+ }
+
long now = System.currentTimeMillis();
- if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) {
+ if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information()); // serial no
bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware
@@ -143,18 +193,7 @@ public class DanaRSService extends Service {
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate()); // basal profile, basalStep, maxBasal
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Calculation_Information()); // target
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_CIR_CF_Array());
- MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
- bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
- long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- if (Math.abs(timeDiff) > 3) {
- waitForWholeMinute(); // Dana can set only whole minute
- // add 10sec to be sure we are over minute (will be cutted off anyway)
- bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date(DateUtil.now() + T.secs(10).msecs())));
- bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
- timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- }
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_User_Option()); // Getting user options
danaRPump.lastSettingsRead = now;
}
@@ -165,9 +204,12 @@ public class DanaRSService extends Service {
NSUpload.uploadDeviceStatus();
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.gs(R.string.approachingdailylimit), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
+ if(System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
+ Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(reportFail));
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U");
+ lastApproachingDailyLimit = System.currentTimeMillis();
+ }
}
} catch (Exception e) {
log.error("Unhandled exception", e);
@@ -176,6 +218,15 @@ public class DanaRSService extends Service {
}
public PumpEnactResult loadEvents() {
+
+ if(!MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()){
+ PumpEnactResult result = new PumpEnactResult().success(false);
+ result.comment = "pump not initialized";
+ return result;
+ }
+
+ SystemClock.sleep(1000);
+
DanaRS_Packet_APS_History_Events msg;
if (lastHistoryFetched == 0) {
msg = new DanaRS_Packet_APS_History_Events(0);
@@ -189,7 +240,7 @@ public class DanaRSService extends Service {
SystemClock.sleep(100);
}
if (DanaRS_Packet_APS_History_Events.lastEventTimeLoaded != 0)
- lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded - 45 * 60 * 1000L; // always load last 45 min
+ lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded - T.mins(1).msecs();
else
lastHistoryFetched = 0;
log.debug("Events loaded");
@@ -198,6 +249,13 @@ public class DanaRSService extends Service {
}
+ public PumpEnactResult setUserSettings() {
+ bleComm.sendMessage(new DanaRS_Packet_Option_Set_User_Option());
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_User_Option());
+ return new PumpEnactResult().success(true);
+ }
+
+
public boolean bolus(final double insulin, int carbs, long carbtime, Treatment t) {
if (!isConnected()) return false;
if (BolusProgressDialog.stopPressed) return false;
@@ -214,7 +272,7 @@ public class DanaRSService extends Service {
// bleComm.sendMessage(msg);
DanaRS_Packet_APS_Set_Event_History msgSetHistoryEntry_v2 = new DanaRS_Packet_APS_Set_Event_History(DanaRPump.CARBS, carbtime, carbs, 0);
bleComm.sendMessage(msgSetHistoryEntry_v2);
- lastHistoryFetched = carbtime - 60000;
+ lastHistoryFetched = Math.min(lastHistoryFetched, carbtime - T.mins(1).msecs());
}
final long bolusStart = System.currentTimeMillis();
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 7c13707949..e83f9d9435 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
@@ -2,9 +2,12 @@ package info.nightscout.androidaps.plugins.PumpDanaRv2;
import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
import com.squareup.otto.Subscribe;
@@ -20,6 +23,7 @@ import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.PumpDanaR.AbstractDanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
@@ -29,6 +33,7 @@ import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.Round;
import info.nightscout.utils.SP;
+import info.nightscout.utils.T;
/**
* Created by mike on 05.08.2016.
@@ -44,6 +49,8 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
}
private DanaRv2Plugin() {
+ pluginDescription.description(R.string.description_pump_dana_r_v2);
+
log = LoggerFactory.getLogger(DanaRv2Plugin.class);
useExtendedBoluses = false;
@@ -138,6 +145,31 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
return pump.lastConnection > 0 && pump.maxBasal > 0;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
// Pump interface
@Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
@@ -164,6 +196,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
double carbs = detailedBolusInfo.carbs;
detailedBolusInfo.carbs = 0;
int carbTime = detailedBolusInfo.carbTime;
+ if (carbTime == 0) carbTime--; // better set 1 man back to prevent clash with insulin
detailedBolusInfo.carbTime = 0;
DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
@@ -172,7 +205,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
t.isSMB = detailedBolusInfo.isSMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0)
- connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + carbTime * 60 * 1000, t);
+ connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t);
PumpEnactResult result = new PumpEnactResult();
result.success = connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep;
result.bolusDelivered = t.insulin;
@@ -266,8 +299,12 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
// Convert duration from minutes to hours
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
- // use special APS temp basal call ... 100+/15min .... 100-/30min
- result = setHighTempBasalPercent(percentRate);
+ if (percentRate == 0 && durationInMinutes > 30) {
+ result = setTempBasalPercent(percentRate, durationInMinutes, profile, false);
+ } else {
+ // use special APS temp basal call ... 100+/15min .... 100-/30min
+ result = setHighTempBasalPercent(percentRate);
+ }
if (!result.success) {
log.error("setTempBasalAbsolute: Failed to set hightemp basal");
return result;
@@ -389,4 +426,8 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
return sExecutionService.loadEvents();
}
+ @Override
+ public PumpEnactResult setUserOptions() {
+ return sExecutionService.setUserOptions();
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java
index cafba32239..8d1cd12be1 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java
@@ -66,6 +66,7 @@ public class MessageHashTable_v2 {
put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE
put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S
put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S
+ put(new MsgSetUserOptions()); // 0x330B CMD_SETTING_USER_OPTIONS_S
put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S
put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE
put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java
index 05c4087dcb..91c01ba38c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java
@@ -107,14 +107,14 @@ public class MsgHistoryEvents_v2 extends MessageBase {
break;
case DanaRPump.BOLUS:
detailedBolusInfo.insulin = param1 / 100d;
- boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ boolean newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
status = "BOLUS " + DateUtil.timeString(datetime);
break;
case DanaRPump.DUALBOLUS:
detailedBolusInfo.insulin = param1 / 100d;
- newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min");
DetailedBolusInfoStorage.remove(detailedBolusInfo.date);
status = "DUALBOLUS " + DateUtil.timeString(datetime);
@@ -157,7 +157,7 @@ public class MsgHistoryEvents_v2 extends MessageBase {
emptyCarbsInfo.date = datetime.getTime();
emptyCarbsInfo.source = Source.PUMP;
emptyCarbsInfo.pumpId = datetime.getTime();
- newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo);
+ newRecord = TreatmentsPlugin.getPlugin().addToHistoryTreatment(emptyCarbsInfo, false);
log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g");
status = "CARBS " + DateUtil.timeString(datetime);
break;
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 b9eb8ae655..1229f23f4e 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
@@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.PumpDanaRv2.services;
import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
import android.content.IntentFilter;
import android.os.Binder;
import android.os.SystemClock;
@@ -18,13 +19,15 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
-import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventPreferenceChange;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
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.Dialogs.BolusProgressDialog;
+import info.nightscout.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
@@ -42,6 +45,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetUserOptions;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingActiveProfile;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose;
@@ -51,6 +55,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatiosAll;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingUserOptions;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatus;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBasic;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
@@ -63,12 +68,13 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetAPSTempBasalSta
import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetHistoryEntry_v2;
import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusBolusExtended_v2;
import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusTempBasal_v2;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.queue.Callback;
+import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.T;
-import info.nightscout.utils.ToastUtils;
public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
@@ -120,7 +126,11 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
public void connect() {
if (mDanaRPump.password != -1 && mDanaRPump.password != SP.getInt(R.string.key_danar_password, -1)) {
- ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.wrongpumppassword), R.raw.error);
+ if(System.currentTimeMillis() > lastWrongPumpPassword + 30 * 1000) {
+ Notification notification = new Notification(Notification.WRONG_PUMP_PASSWORD, MainApp.gs(R.string.wrongpumppassword), Notification.URGENT);
+ notification.soundId = R.raw.error;
+ lastWrongPumpPassword = System.currentTimeMillis();
+ }
return;
}
@@ -183,8 +193,50 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingextendedbolusstatus)));
mSerialIOThread.sendMessage(exStatusMsg);
+ mDanaRPump.lastConnection = System.currentTimeMillis();
+
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+ PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
+ if (profile != null && Math.abs(mDanaRPump.currentBasal - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
+ mSerialIOThread.sendMessage(new MsgSettingBasal());
+ if (!pump.isThisProfileSet(profile) && !ConfigBuilderPlugin.getCommandQueue().isRunning(Command.CommandType.BASALPROFILE)) {
+ MainApp.bus().post(new EventProfileSwitchChange());
+ }
+ }
+
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
+ mSerialIOThread.sendMessage(new MsgSettingPumpTime());
+ long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ if (Math.abs(timeDiff) > 3) {
+ if (Math.abs(timeDiff) > 60*60*1.5) {
+ log.debug("Pump time difference: " + timeDiff + " seconds - large difference");
+ //If time-diff is very large, warn user until we can synchronize history readings properly
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.error);
+ i.putExtra("status", MainApp.gs(R.string.largetimediff));
+ i.putExtra("title", MainApp.gs(R.string.largetimedifftitle));
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+
+ //deinitialize pump
+ mDanaRPump.lastConnection = 0;
+ MainApp.bus().post(new EventDanaRNewStatus());
+ MainApp.bus().post(new EventInitializationChanged());
+ return;
+ } else {
+ waitForWholeMinute(); // Dana can set only whole minute
+ // add 10sec to be sure we are over minute (will be cutted off anyway)
+ mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs())));
+ mSerialIOThread.sendMessage(new MsgSettingPumpTime());
+ timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ }
+ }
+
long now = System.currentTimeMillis();
- if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) {
+ if (mDanaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized()) {
MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
@@ -195,19 +247,8 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(new MsgSettingGlucose());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
+ mSerialIOThread.sendMessage(new MsgSettingUserOptions());
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
- MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime)));
- mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- long timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- if (Math.abs(timeDiff) > 3) {
- waitForWholeMinute(); // Dana can set only whole minute
- // add 10sec to be sure we are over minute (will be cutted off anyway)
- mSerialIOThread.sendMessage(new MsgSetTime(new Date(DateUtil.now() + T.secs(10).msecs())));
- mSerialIOThread.sendMessage(new MsgSettingPumpTime());
- timeDiff = (mDanaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
- log.debug("Pump time difference: " + timeDiff + " seconds");
- }
mDanaRPump.lastSettingsRead = now;
}
@@ -218,9 +259,12 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
NSUpload.uploadDeviceStatus();
if (mDanaRPump.dailyTotalUnits > mDanaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
log.debug("Approaching daily limit: " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits);
- Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
- MainApp.bus().post(new EventNewNotification(reportFail));
- NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ if(System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
+ Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.gs(R.string.approachingdailylimit), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(reportFail));
+ NSUpload.uploadError(MainApp.gs(R.string.approachingdailylimit) + ": " + mDanaRPump.dailyTotalUnits + "/" + mDanaRPump.maxDailyTotalUnits + "U");
+ lastApproachingDailyLimit = System.currentTimeMillis();
+ }
}
} catch (Exception e) {
log.error("Unhandled exception", e);
@@ -327,7 +371,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(msg);
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, carbtime, carbs, 0);
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
- lastHistoryFetched = carbtime - 60000;
+ lastHistoryFetched = Math.min(lastHistoryFetched, carbtime - T.mins(1).msecs());
}
final long bolusStart = System.currentTimeMillis();
@@ -411,11 +455,19 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
mSerialIOThread.sendMessage(msg);
MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, time, amount, 0);
mSerialIOThread.sendMessage(msgSetHistoryEntry_v2);
- lastHistoryFetched = time - 1;
+ lastHistoryFetched = Math.min(lastHistoryFetched, time - T.mins(1).msecs());
return true;
}
public PumpEnactResult loadEvents() {
+
+ if(!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()){
+ PumpEnactResult result = new PumpEnactResult().success(false);
+ result.comment = "pump not initialized";
+ return result;
+ }
+
+
if (!isConnected())
return new PumpEnactResult().success(false);
SystemClock.sleep(300);
@@ -433,7 +485,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
}
SystemClock.sleep(200);
if (MsgHistoryEvents_v2.lastEventTimeLoaded != 0)
- lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - 45 * 60 * 1000L; //always load last 45 min;
+ lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded - T.mins(1).msecs();
else
lastHistoryFetched = 0;
mDanaRPump.lastConnection = System.currentTimeMillis();
@@ -464,4 +516,15 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
SystemClock.sleep(Math.min(timeToWholeMinute, 100));
}
}
+
+ public PumpEnactResult setUserOptions() {
+ if (!isConnected())
+ return new PumpEnactResult().success(false);
+ SystemClock.sleep(300);
+ MsgSetUserOptions msg = new MsgSetUserOptions();
+ mSerialIOThread.sendMessage(msg);
+ SystemClock.sleep(200);
+ return new PumpEnactResult().success(!msg.failed);
+ }
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Cstatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Cstatus.java
deleted file mode 100644
index 53c0cf798f..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Cstatus.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package info.nightscout.androidaps.plugins.PumpInsight;
-
-/**
- * Created by jamorham on 25/01/2018.
- *
- * Async command status
- *
- */
-enum Cstatus {
- UNKNOWN,
- PENDING,
- SUCCESS,
- FAILURE,
- TIMEOUT;
-
- boolean success() {
- return this == SUCCESS;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightAsyncAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightAsyncAdapter.java
deleted file mode 100644
index 3759a3f721..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightAsyncAdapter.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package info.nightscout.androidaps.plugins.PumpInsight;
-
-import android.os.PowerManager;
-
-import com.squareup.otto.Subscribe;
-
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-
-import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightCallback;
-
-import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.getWakeLock;
-import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.msSince;
-import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.releaseWakeLock;
-import static info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers.tsl;
-
-/**
- * Created by jamorham on 25/01/2018.
- *
- * Asynchronous adapter
- *
- */
-
-public class InsightAsyncAdapter {
-
- private final ConcurrentHashMap commandResults = new ConcurrentHashMap<>();
-
- InsightAsyncAdapter() {
- MainApp.bus().register(this);
- }
-
- // just log during debugging
- private static void log(String msg) {
- android.util.Log.e("INSIGHTPUMPASYNC", msg);
- }
-
- @Subscribe
- public void onStatusEvent(final EventInsightCallback ev) {
- log("Received callback event: " + ev.toString());
- commandResults.put(ev.request_uuid, ev);
- }
-
- // poll command result
- private Cstatus checkCommandResult(UUID uuid) {
- if (uuid == null) return Cstatus.FAILURE;
- if (commandResults.containsKey(uuid)) {
- if (commandResults.get(uuid).success) {
- return Cstatus.SUCCESS;
- } else {
- return Cstatus.FAILURE;
- }
- } else {
- return Cstatus.PENDING;
- }
- }
-
- // blocking call to wait for result callback
- private Cstatus busyWaitForCommandInternal(final UUID uuid, long wait_time) {
- final PowerManager.WakeLock wl = getWakeLock("insight-wait-cmd", 60000);
- try {
- log("busy wait for command " + uuid);
- if (uuid == null) return Cstatus.FAILURE;
- final long start_time = tsl();
- Cstatus status = checkCommandResult(uuid);
- while ((status == Cstatus.PENDING) && msSince(start_time) < wait_time) {
- //log("command result waiting");
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- log("Got interrupted exception! " + e);
- }
- status = checkCommandResult(uuid);
- }
- if (status == Cstatus.PENDING) {
- return Cstatus.TIMEOUT;
- } else {
- return status;
- }
- } finally {
- releaseWakeLock(wl);
- }
- }
-
- // wait for and then package result, cleanup and return
- Mstatus busyWaitForCommandResult(final UUID uuid, long wait_time) {
- final Mstatus mstatus = new Mstatus();
- mstatus.cstatus = busyWaitForCommandInternal(uuid, wait_time);
- mstatus.event = commandResults.get(uuid);
- commandResults.remove(uuid);
- return mstatus;
- }
-
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
index 824a449f38..5fd8e25f26 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/InsightPlugin.java
@@ -1,5 +1,9 @@
package info.nightscout.androidaps.plugins.PumpInsight;
+import android.content.DialogInterface;
+import android.support.v4.app.FragmentActivity;
+import android.support.v7.app.AlertDialog;
+
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
@@ -9,7 +13,6 @@ import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.UUID;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
@@ -21,7 +24,6 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
-import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
@@ -29,11 +31,13 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
-import info.nightscout.androidaps.plugins.PumpInsight.connector.CancelBolusTaskRunner;
+import info.nightscout.androidaps.plugins.PumpInsight.connector.CancelBolusSilentlyTaskRunner;
+import info.nightscout.androidaps.plugins.PumpInsight.connector.CancelTBRSilentlyTaskRunner;
import info.nightscout.androidaps.plugins.PumpInsight.connector.Connector;
import info.nightscout.androidaps.plugins.PumpInsight.connector.SetTBRTaskRunner;
import info.nightscout.androidaps.plugins.PumpInsight.connector.StatusTaskRunner;
@@ -44,18 +48,19 @@ import info.nightscout.androidaps.plugins.PumpInsight.history.HistoryReceiver;
import info.nightscout.androidaps.plugins.PumpInsight.history.LiveHistory;
import info.nightscout.androidaps.plugins.PumpInsight.utils.Helpers;
import info.nightscout.androidaps.plugins.PumpInsight.utils.StatusItem;
+import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import sugar.free.sightparser.applayer.descriptors.ActiveBolus;
import sugar.free.sightparser.applayer.descriptors.ActiveBolusType;
+import sugar.free.sightparser.applayer.descriptors.MessagePriority;
import sugar.free.sightparser.applayer.descriptors.PumpStatus;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock;
import sugar.free.sightparser.applayer.messages.AppLayerMessage;
import sugar.free.sightparser.applayer.messages.remote_control.BolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage;
-import sugar.free.sightparser.applayer.messages.remote_control.CancelTBRMessage;
import sugar.free.sightparser.applayer.messages.remote_control.ExtendedBolusMessage;
import sugar.free.sightparser.applayer.messages.remote_control.StandardBolusMessage;
import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
@@ -94,7 +99,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
private static boolean initialized = false;
private static volatile boolean update_pending = false;
private static Logger log = LoggerFactory.getLogger(InsightPlugin.class);
- private final InsightAsyncAdapter async = new InsightAsyncAdapter();
private StatusTaskRunner.Result statusResult;
private long statusResultTime = -1;
private Date lastDataTime = new Date(0);
@@ -112,13 +116,14 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
.pluginName(R.string.insightpump)
.shortName(R.string.insightpump_shortname)
.preferencesId(R.xml.pref_insightpump)
+ .description(R.string.description_pump_insight)
);
log("InsightPlugin instantiated");
pumpDescription.isBolusCapable = true;
- pumpDescription.bolusStep = 0.05d; // specification says 0.05U up to 2U then 0.1U @ 2-5U 0.2U @ 10-20U 0.5U 10-20U (are these just UI restrictions?)
+ pumpDescription.bolusStep = 0.01d; // specification says 0.05U up to 2U then 0.1U @ 2-5U 0.2U @ 10-20U 0.5U 10-20U (are these just UI restrictions? Yes, they are!)
pumpDescription.isExtendedBolusCapable = true;
- pumpDescription.extendedBolusStep = 0.05d; // specification probably same as above
+ pumpDescription.extendedBolusStep = 0.01d; // specification probably same as above
pumpDescription.extendedBolusDurationStep = 15; // 15 minutes up to 24 hours
pumpDescription.extendedBolusMaxDuration = 24 * 60;
@@ -138,6 +143,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
pumpDescription.is30minBasalRatesCapable = true;
pumpDescription.basalStep = 0.01d;
pumpDescription.basalMinimumRate = 0.02d;
+ pumpDescription.basalMaximumRate = 25d;
pumpDescription.isRefillingCapable = true;
@@ -191,7 +197,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
@Override
public boolean isFakingTempsByExtendedBoluses() {
- return false;
+ return true;
}
@Override
@@ -201,6 +207,31 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
return result;
}
+ @Override
+ public void switchAllowed(ConfigBuilderFragment.PluginViewHolder.PluginSwitcher pluginSwitcher, FragmentActivity context) {
+ boolean allowHardwarePump = SP.getBoolean("allow_hardware_pump", false);
+ if (allowHardwarePump || context == null){
+ pluginSwitcher.invoke();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(R.string.allow_hardware_pump_text)
+ .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.invoke();
+ SP.putBoolean("allow_hardware_pump", true);
+ log.debug("First time HW pump allowed!");
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ pluginSwitcher.cancel();
+ log.debug("User does not allow switching to HW pump!");
+ }
+ });
+ builder.create().show();
+ }
+ }
+
@Override
public boolean isInitialized() {
return initialized;
@@ -287,17 +318,15 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
log("getPumpStatus");
if (Connector.get().isPumpConnected()) {
log("is connected.. requesting status");
- final UUID uuid = aSyncTaskRunner(new StatusTaskRunner(connector.getServiceConnector()), "Status");
- Mstatus mstatus = async.busyWaitForCommandResult(uuid, BUSY_WAIT_TIME);
- if (mstatus.success()) {
+ try {
+ setStatusResult(fetchTaskRunner(new StatusTaskRunner(connector.getServiceConnector()), StatusTaskRunner.Result.class));
log("GOT STATUS RESULT!!! PARTY WOOHOO!!!");
- setStatusResult((StatusTaskRunner.Result) mstatus.getResponseObject());
statusResultTime = Helpers.tsl();
processStatusResult();
updateGui();
connector.requestHistoryReSync();
connector.requestHistorySync();
- } else {
+ } catch (Exception e) {
log("StatusTaskRunner wasn't successful.");
if (connector.getServiceConnector().isConnectedToService() && connector.getServiceConnector().getStatus() != Status.CONNECTED) {
if (Helpers.ratelimit("insight-reconnect", 2)) {
@@ -313,6 +342,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
public void setStatusResult(StatusTaskRunner.Result result) {
this.statusResult = result;
+ this.pumpDescription.basalMinimumRate = result.minimumBasalAmount;
+ this.pumpDescription.basalMaximumRate = result.maximumBasalAmount;
}
@Override
@@ -335,9 +366,8 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
profileBlocks.add(new BRProfileBlock.ProfileBlock((((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60), Helpers.roundDouble(basalValue.value, 2)));
log("setNewBasalProfile: " + basalValue.value + " for " + Integer.toString(((nextValue != null ? nextValue.timeAsSeconds : 24 * 60 * 60) - basalValue.timeAsSeconds) / 60));
}
- final UUID uuid = aSyncTaskRunner(new WriteBasalProfileTaskRunner(connector.getServiceConnector(), profileBlocks), "Write basal profile");
- final Mstatus ms = async.busyWaitForCommandResult(uuid, BUSY_WAIT_TIME);
- if (ms.success()) {
+ try {
+ fetchTaskRunner(new WriteBasalProfileTaskRunner(connector.getServiceConnector(), profileBlocks));
MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.gs(R.string.profile_set_ok), Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification));
@@ -345,7 +375,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
result.enacted = true;
result.comment = "OK";
this.profileBlocks = profileBlocks;
- } else {
+ } catch (Exception e) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
result.comment = MainApp.gs(R.string.failedupdatebasalprofile);
@@ -403,17 +433,13 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
// is there an insulin component to the treatment?
if (detailedBolusInfo.insulin > 0) {
- final UUID cmd = deliverBolus(detailedBolusInfo.insulin); // actually request delivery
- if (cmd == null) {
+ try {
+ bolusId = deliverBolus(detailedBolusInfo.insulin);
+ result.success = true;
+ detailedBolusInfo.pumpId = getRecordUniqueID(bolusId);
+ } catch (Exception e) {
return pumpEnactFailure();
}
- final Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
-
- result.success = ms.success();
- if (ms.success()) {
- detailedBolusInfo.pumpId = getRecordUniqueID(ms.getResponseID());
- bolusId = ms.getResponseID();
- }
} else {
result.success = true; // always true with carb only treatments
}
@@ -429,7 +455,7 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
bolusingEvent.bolusId = bolusId;
bolusingEvent.percent = 0;
MainApp.bus().post(bolusingEvent);
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
} else {
log.debug("Failure to deliver treatment");
}
@@ -440,20 +466,11 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
updateGui();
connector.tryToGetPumpStatusAgain();
- connector.requestHistorySync(30000);
-
if (result.success) while (true) {
try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- break;
- }
- final UUID uuid = aSyncSingleCommand(new ActiveBolusesMessage(), "Active boluses");
- Mstatus mstatus = async.busyWaitForCommandResult(uuid, BUSY_WAIT_TIME);
- if (mstatus.success()) {
+ Thread.sleep(500);
final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
- ActiveBolusesMessage activeBolusesMessage = (ActiveBolusesMessage) mstatus.getResponseObject();
+ ActiveBolusesMessage activeBolusesMessage = fetchSingleMessage(new ActiveBolusesMessage(), ActiveBolusesMessage.class);
ActiveBolus activeBolus = null;
if (activeBolusesMessage.getBolus1() != null && activeBolusesMessage.getBolus1().getBolusID() == bolusingEvent.bolusId)
activeBolus = activeBolusesMessage.getBolus1();
@@ -463,87 +480,60 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
activeBolus = activeBolusesMessage.getBolus3();
if (activeBolus == null) break;
else {
+ int percentBefore = bolusingEvent.percent;
bolusingEvent.percent = (int) (100D / activeBolus.getInitialAmount() * (activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount()));
bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), activeBolus.getInitialAmount() - activeBolus.getLeftoverAmount());
- MainApp.bus().post(bolusingEvent);
+ if (percentBefore != bolusingEvent.percent) MainApp.bus().post(bolusingEvent);
}
- } else break;
+ } catch (Exception e) {
+ break;
+ }
}
+
+ connector.requestHistorySync(2000);
return result;
}
@Override
public void stopBolusDelivering() {
CancelBolusMessage cancelBolusMessage = new CancelBolusMessage();
+ cancelBolusMessage.setMessagePriority(MessagePriority.HIGHEST);
cancelBolusMessage.setBolusId(EventOverviewBolusProgress.getInstance().bolusId);
- final UUID cmd = aSyncSingleCommand(cancelBolusMessage, "Cancel standard bolus");
-
- if (cmd == null) {
- return;
+ try {
+ fetchSingleMessage(cancelBolusMessage);
+ } catch (Exception e) {
}
-
- final Mstatus cs = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
- log("Got command status: " + cs);
}
// Temporary Basals
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
- absoluteRate = Helpers.roundDouble(absoluteRate, 3);
log("Set TBR absolute: " + absoluteRate);
- final double base_basal = getBaseBasalRate();
- if (base_basal == 0) {
+ if (getBaseBasalRate() == 0) {
log("Base basal rate appears to be zero!");
return pumpEnactFailure();
}
- int percent_amount = (int) Math.round(100d / base_basal * absoluteRate);
- log("Calculated requested rate: " + absoluteRate + " base rate: " + base_basal + " percentage: " + percent_amount + "%");
- percent_amount = (int) Math.round(((double) percent_amount) / 10d) * 10;
- log("Calculated final rate: " + percent_amount + "%");
-
- if (percent_amount == 100) {
- return cancelTempBasal(false);
- }
-
- if (percent_amount > 250) percent_amount = 250;
-
-
- final SetTBRTaskRunner task = new SetTBRTaskRunner(connector.getServiceConnector(), percent_amount, durationInMinutes);
- final UUID cmd = aSyncTaskRunner(task, "Set TBR abs: " + absoluteRate + " " + durationInMinutes + "m");
-
- if (cmd == null) {
+ double percent = 100D / getBaseBasalRate() * absoluteRate;
+ log("Calculated requested rate: " + absoluteRate + " base rate: " + getBaseBasalRate() + " percentage: " + percent + "%");
+ try {
+ if (percent > 250) {
+ log ("Calculated rate is above 250%, switching to emulation using extended boluses");
+ cancelTempBasal(true);
+ if (!setExtendedBolus((absoluteRate - getBaseBasalRate()) / 60D * ((double) durationInMinutes), durationInMinutes).success) {
+ //Fallback to TBR if setting an extended bolus didn't work
+ log ("Setting an extended bolus didn't work, falling back to normal TBR");
+ return setTempBasalPercent((int) percent, durationInMinutes, profile, true);
+ }
+ return new PumpEnactResult().success(true).enacted(true).absolute(absoluteRate).duration(durationInMinutes);
+ } else {
+ log ("Calculated rate is below or equal to 250%, using normal TBRs");
+ cancelExtendedBolus();
+ return setTempBasalPercent((int) percent, durationInMinutes, profile, true);
+ }
+ } catch (Exception e) {
return pumpEnactFailure();
}
-
- Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
- log("Got command status: " + ms);
-
- PumpEnactResult pumpEnactResult = new PumpEnactResult().enacted(true).isPercent(true).duration(durationInMinutes);
- pumpEnactResult.percent = percent_amount;
- pumpEnactResult.success = ms.success();
- pumpEnactResult.comment = ms.getCommandComment();
-
-
- if (pumpEnactResult.success) {
- // create log entry
- final TemporaryBasal tempBasal = new TemporaryBasal()
- .date(System.currentTimeMillis())
- .percent(percent_amount)
- .duration(durationInMinutes)
- .source(Source.USER);
- TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
- }
-
- if (Config.logPumpComm)
- log.debug("Setting temp basal absolute: " + pumpEnactResult.success);
-
- updateGui();
-
- connector.requestHistorySync(5000);
- connector.tryToGetPumpStatusAgain();
-
- return pumpEnactResult;
}
@@ -555,42 +545,24 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
if (percent == 100) {
// This would cause a cancel if a tbr is in progress so treat as a cancel
return cancelTempBasal(false);
- }
+ } else if (percent > 250) percent = 250;
-
- final UUID cmd = aSyncTaskRunner(new SetTBRTaskRunner(connector.getServiceConnector(), percent, durationInMinutes), "Set TBR " + percent + "%" + " " + durationInMinutes + "m");
-
- if (cmd == null) {
- return pumpEnactFailure();
- }
-
- final Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
- log("Got command status: " + ms);
-
- PumpEnactResult pumpEnactResult = new PumpEnactResult().enacted(true).isPercent(true).duration(durationInMinutes);
- pumpEnactResult.percent = percent;
- pumpEnactResult.success = ms.success();
- pumpEnactResult.comment = ms.getCommandComment();
-
- if (pumpEnactResult.success) {
- // create log entry
+ try {
+ fetchTaskRunner(new SetTBRTaskRunner(connector.getServiceConnector(), percent, durationInMinutes));
final TemporaryBasal tempBasal = new TemporaryBasal()
.date(System.currentTimeMillis())
.percent(percent)
.duration(durationInMinutes)
- .source(Source.USER); // TODO check this is correct
+ .source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
+ updateGui();
+ if (Config.logPumpComm) log.debug("Set temp basal " + percent + "% for " + durationInMinutes + "m");
+ connector.requestHistorySync(5000);
+ connector.tryToGetPumpStatusAgain();
+ return new PumpEnactResult().success(true).enacted(true).percent(percent);
+ } catch (Exception e) {
+ return pumpEnactFailure();
}
-
- updateGui();
-
- if (Config.logPumpComm)
- log.debug("Set temp basal " + percent + "% for " + durationInMinutes + "m");
-
- connector.requestHistorySync(5000);
- connector.tryToGetPumpStatusAgain();
-
- return pumpEnactResult;
}
@@ -598,35 +570,24 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
log("Cancel TBR");
-
- fauxTBRcancel = !SP.getBoolean("insight_real_tbr_cancel", false);
-
- final UUID cmd;
-
- if (fauxTBRcancel) {
- cmd = aSyncTaskRunner(new SetTBRTaskRunner(connector.getServiceConnector(), 100, 1), "Faux Cancel TBR - setting " + "90%" + " 1m");
- } else {
- cmd = aSyncSingleCommand(new CancelTBRMessage(), "Cancel Temp Basal");
- }
- if (cmd == null) {
+ try {
+ cancelExtendedBolus();
+ realTBRCancel();
+ updateGui();
+ if (Config.logPumpComm) log.debug("Canceling temp basal");
+ connector.requestHistorySync(5000);
+ connector.tryToGetPumpStatusAgain();
+ return new PumpEnactResult().success(true).enacted(true).isTempCancel(true);
+ } catch (Exception e) {
return pumpEnactFailure();
}
+ }
- // TODO isn't conditional on one apparently being in progress only the history change
- final Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
-
- if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
+ private void realTBRCancel() throws Exception {
+ if (fetchTaskRunner(new CancelTBRSilentlyTaskRunner(connector.getServiceConnector()), Boolean.class) && TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop);
}
- updateGui();
- if (Config.logPumpComm)
- log.debug("Canceling temp basal: "); // TODO get more info
-
- connector.requestHistorySync(5000);
- connector.tryToGetPumpStatusAgain();
-
- return new PumpEnactResult().success(ms.success()).enacted(true).isTempCancel(true);
}
@@ -635,88 +596,60 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
log("Set Extended bolus " + insulin + " " + durationInMinutes);
- ExtendedBolusMessage extendedBolusMessage = new ExtendedBolusMessage();
- extendedBolusMessage.setAmount(insulin);
- extendedBolusMessage.setDuration(durationInMinutes);
- final UUID cmd = aSyncSingleCommand(extendedBolusMessage, "Extended bolus U" + insulin + " mins:" + durationInMinutes);
- if (cmd == null) {
- return pumpEnactFailure();
- }
-
- final Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
- log("Got command status: " + ms);
-
- PumpEnactResult pumpEnactResult = new PumpEnactResult().enacted(true).bolusDelivered(insulin).duration(durationInMinutes);
- pumpEnactResult.success = ms.success();
- pumpEnactResult.comment = ms.getCommandComment();
-
- if (pumpEnactResult.success) {
- // create log entry
+ try {
+ ExtendedBolusMessage extendedBolusMessage = new ExtendedBolusMessage();
+ extendedBolusMessage.setAmount(insulin);
+ extendedBolusMessage.setDuration(durationInMinutes);
+ BolusMessage bolusMessage = fetchSingleMessage(extendedBolusMessage, BolusMessage.class);
final ExtendedBolus extendedBolus = new ExtendedBolus();
extendedBolus.date = System.currentTimeMillis();
extendedBolus.insulin = insulin;
extendedBolus.durationInMinutes = durationInMinutes;
extendedBolus.source = Source.USER;
- extendedBolus.pumpId = getRecordUniqueID(ms.getResponseID());
+ extendedBolus.pumpId = getRecordUniqueID(bolusMessage.getBolusId());
TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
+ updateGui();
+ connector.requestHistorySync(30000);
+ connector.tryToGetPumpStatusAgain();
+ if (Config.logPumpComm)
+ log.debug("Setting extended bolus: " + insulin + " mins:" + durationInMinutes);
+ return new PumpEnactResult().success(true).enacted(true).duration(durationInMinutes).bolusDelivered(insulin);
+ } catch (Exception e) {
+ return pumpEnactFailure();
}
-
- if (Config.logPumpComm)
- log.debug("Setting extended bolus: " + insulin + " mins:" + durationInMinutes + " " + pumpEnactResult.comment);
-
- updateGui();
-
- connector.requestHistorySync(30000);
- connector.tryToGetPumpStatusAgain();
-
- return pumpEnactResult;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
-
log("Cancel Extended bolus");
- // TODO note always sends cancel to pump but only changes history if present
+ Integer bolusId = null;
- final UUID cmd = aSyncTaskRunner(new CancelBolusTaskRunner(connector.getServiceConnector(), ActiveBolusType.EXTENDED), "Cancel extended bolus");
-
- if (cmd == null) {
+ try {
+ bolusId = fetchTaskRunner(new CancelBolusSilentlyTaskRunner(connector.getServiceConnector(), ActiveBolusType.EXTENDED), Integer.class);
+ if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
+ ExtendedBolus exStop = new ExtendedBolus(System.currentTimeMillis());
+ exStop.source = Source.USER;
+ TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(exStop);
+ }
+ if (Config.logPumpComm) log.debug("Cancel extended bolus:");
+ if (bolusId != null) connector.requestHistorySync(5000);
+ connector.tryToGetPumpStatusAgain();
+ updateGui();
+ return new PumpEnactResult().success(true).enacted(bolusId != null);
+ } catch (Exception e) {
return pumpEnactFailure();
}
-
- final Mstatus ms = async.busyWaitForCommandResult(cmd, BUSY_WAIT_TIME);
-
- if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
- ExtendedBolus exStop = new ExtendedBolus(System.currentTimeMillis());
- exStop.source = Source.USER;
- TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(exStop);
- }
-
- if (Config.logPumpComm)
- log.debug("Cancel extended bolus:");
-
- updateGui();
-
- connector.requestHistorySync(5000);
- connector.tryToGetPumpStatusAgain();
-
- return new PumpEnactResult().success(ms.success()).enacted(true);
}
- private synchronized UUID deliverBolus(double bolusValue) {
+ private int deliverBolus(double bolusValue) throws Exception {
log("DeliverBolus: " + bolusValue);
- if (bolusValue == 0) return null;
- if (bolusValue < 0) return null;
-
- // TODO check limits here or they already occur via a previous constraint interface?
-
final StandardBolusMessage message = new StandardBolusMessage();
message.setAmount(bolusValue);
- return aSyncSingleCommand(message, "Deliver Bolus " + bolusValue);
+ return fetchSingleMessage(message, BolusMessage.class).getBolusId();
}
@Override
@@ -931,82 +864,34 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
}
}
- // Utility
-
- private synchronized UUID aSyncSingleCommand(final AppLayerMessage msg, final String name) {
- // if (!isConnected()) return false;
- //if (isBusy()) return false;
- log("asyncSinglecommand called: " + name);
- final EventInsightCallback event = new EventInsightCallback();
- new Thread() {
- @Override
- public void run() {
- log("asyncSingleCommand thread");
- final SingleMessageTaskRunner singleMessageTaskRunner = new SingleMessageTaskRunner(connector.getServiceConnector(), msg);
- try {
- singleMessageTaskRunner.fetch(new TaskRunner.ResultCallback() {
- @Override
- public void onResult(Object o) {
- lastDataTime = new Date();
- log(name + " success");
- event.response_object = o;
- if (o instanceof BolusMessage) {
- event.response_id = ((BolusMessage) o).getBolusId();
- }
- event.success = true;
- pushCallbackEvent(event);
- }
-
- @Override
- public void onError(Exception e) {
- log(name + " error");
- event.message = e.getMessage();
- pushCallbackEvent(event);
- }
- });
-
- } catch (Exception e) {
- log("EXCEPTION" + e.toString());
- }
- }
- }.start();
- return event.request_uuid;
+ private void fetchTaskRunner(TaskRunner taskRunner) throws Exception {
+ fetchTaskRunner(taskRunner, Object.class);
}
- private synchronized UUID aSyncTaskRunner(final TaskRunner task, final String name) {
- // if (!isConnected()) return false;
- //if (isBusy()) return false;
- log("asyncTaskRunner called: " + name);
- final EventInsightCallback event = new EventInsightCallback();
- new Thread() {
- @Override
- public void run() {
- log("asyncTaskRunner thread");
- try {
- task.fetch(new TaskRunner.ResultCallback() {
- @Override
- public void onResult(Object o) {
- lastDataTime = new Date();
- log(name + " success");
- event.response_object = o;
- event.success = true;
- pushCallbackEvent(event);
- }
+ private void fetchSingleMessage(AppLayerMessage message) throws Exception {
+ fetchSingleMessage(message, AppLayerMessage.class);
+ }
- @Override
- public void onError(Exception e) {
- log(name + " error");
- event.message = e.getMessage();
- pushCallbackEvent(event);
- }
- });
+ private T fetchTaskRunner(TaskRunner taskRunner, Class resultType) throws Exception {
+ try {
+ T result = (T) taskRunner.fetchAndWaitUsingLatch(BUSY_WAIT_TIME);
+ lastDataTime = new Date();
+ return result;
+ } catch (Exception e) {
+ log("Error while fetching " + taskRunner.getClass().getSimpleName() + ": " + e.getClass().getSimpleName());
+ throw e;
+ }
+ }
- } catch (Exception e) {
- log("EXCEPTION" + e.toString());
- }
- }
- }.start();
- return event.request_uuid;
+ private T fetchSingleMessage(AppLayerMessage message, Class resultType) throws Exception {
+ try {
+ T result = (T) new SingleMessageTaskRunner(connector.getServiceConnector(), message).fetchAndWaitUsingLatch(BUSY_WAIT_TIME);
+ lastDataTime = new Date();
+ return result;
+ } catch (Exception e) {
+ log("Error while fetching " + message.getClass().getSimpleName() + ": " + e.getClass().getSimpleName());
+ throw e;
+ }
}
@@ -1016,14 +901,6 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
// Constraints
- @Override
- public Constraint applyBasalConstraints(Constraint absoluteRate, Profile profile) {
- if (statusResult != null) {
- absoluteRate.setIfSmaller(statusResult.maximumBasalAmount, String.format(MainApp.gs(R.string.limitingbasalratio), statusResult.maximumBasalAmount, MainApp.gs(R.string.pumplimit)), this);
- }
- return absoluteRate;
- }
-
@Override
public Constraint applyBasalPercentConstraints(Constraint percentRate, Profile profile) {
percentRate.setIfGreater(0, String.format(MainApp.gs(R.string.limitingpercentrate), 0, MainApp.gs(R.string.itmustbepositivevalue)), this);
@@ -1034,8 +911,17 @@ public class InsightPlugin extends PluginBase implements PumpInterface, Constrai
@Override
public Constraint applyBolusConstraints(Constraint insulin) {
- if (statusResult != null)
+ if (statusResult != null) {
insulin.setIfSmaller(statusResult.maximumBolusAmount, String.format(MainApp.gs(R.string.limitingbolus), statusResult.maximumBolusAmount, MainApp.gs(R.string.pumplimit)), this);
+ if (insulin.value() < statusResult.minimumBolusAmount) {
+
+ //TODO: Add function to Constraints or use different approach
+ // This only works if the interface of the InsightPlugin is called last.
+ // If not, another contraint could theoretically set the value between 0 and minimumBolusAmount
+
+ insulin.set(0d, String.format(MainApp.gs(R.string.limitingbolus), statusResult.minimumBolusAmount, MainApp.gs(R.string.pumplimit)), this);
+ }
+ }
return insulin;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java
deleted file mode 100644
index 8797325f7c..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/Mstatus.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package info.nightscout.androidaps.plugins.PumpInsight;
-
-import info.nightscout.androidaps.plugins.PumpInsight.events.EventInsightCallback;
-
-/**
- * Created by jamorham on 01/02/2018.
- *
- * Encapsulates results from commands
- */
-
-class Mstatus {
-
- Cstatus cstatus = Cstatus.UNKNOWN;
- EventInsightCallback event;
-
- // comment field preparation for results
- String getCommandComment() {
- if (success()) {
- return "OK";
- } else {
- return (event == null) ? "EVENT DATA IS NULL - ERROR OR FIREWALL ENABLED?" : event.message;
- }
- }
-
- boolean success() {
- return cstatus.success();
- }
-
- int getResponseID() {
- if (success()) {
- return event.response_id;
- } else {
- return -2; // invalid
- }
- }
-
- Object getResponseObject() {
- if (success()) {
- return event.response_object;
- } else {
- return null;
- }
- }
-
- @Override
- public String toString() {
- return cstatus + " " + event;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusSilentlyTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusSilentlyTaskRunner.java
new file mode 100644
index 0000000000..7b3108602e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusSilentlyTaskRunner.java
@@ -0,0 +1,66 @@
+package info.nightscout.androidaps.plugins.PumpInsight.connector;
+
+import sugar.free.sightparser.applayer.descriptors.ActiveBolusType;
+import sugar.free.sightparser.applayer.descriptors.MessagePriority;
+import sugar.free.sightparser.applayer.descriptors.alerts.Warning38BolusCancelled;
+import sugar.free.sightparser.applayer.messages.AppLayerMessage;
+import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage;
+import sugar.free.sightparser.applayer.messages.remote_control.DismissAlertMessage;
+import sugar.free.sightparser.applayer.messages.status.ActiveAlertMessage;
+import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
+import sugar.free.sightparser.handling.SightServiceConnector;
+import sugar.free.sightparser.handling.TaskRunner;
+
+// by Tebbe Ubben
+
+public class CancelBolusSilentlyTaskRunner extends TaskRunner {
+
+ private ActiveBolusType bolusType;
+ private long cancelledAt;
+ private int bolusId;
+
+ public CancelBolusSilentlyTaskRunner(SightServiceConnector serviceConnector, ActiveBolusType bolusType) {
+ super(serviceConnector);
+ this.bolusType = bolusType;
+ }
+
+ @Override
+ protected AppLayerMessage run(AppLayerMessage message) throws Exception {
+ if (message == null) return new ActiveBolusesMessage();
+ else if (message instanceof ActiveBolusesMessage) {
+ ActiveBolusesMessage bolusesMessage = (ActiveBolusesMessage) message;
+ CancelBolusMessage cancelBolusMessage = new CancelBolusMessage();
+ if (bolusesMessage.getBolus1().getBolusType() == bolusType)
+ bolusId = bolusesMessage.getBolus1().getBolusID();
+ else if (bolusesMessage.getBolus2().getBolusType() == bolusType)
+ bolusId = bolusesMessage.getBolus2().getBolusID();
+ else if (bolusesMessage.getBolus3().getBolusType() == bolusType)
+ bolusId = bolusesMessage.getBolus3().getBolusID();
+ else finish(null);
+ cancelBolusMessage.setBolusId(bolusId);
+ return cancelBolusMessage;
+ } else if (message instanceof CancelBolusMessage) {
+ cancelledAt = System.currentTimeMillis();
+ ActiveAlertMessage activeAlertMessage = new ActiveAlertMessage();
+ activeAlertMessage.setMessagePriority(MessagePriority.HIGHER);
+ return activeAlertMessage;
+ } else if (message instanceof ActiveAlertMessage) {
+ ActiveAlertMessage activeAlertMessage = (ActiveAlertMessage) message;
+ if (activeAlertMessage.getAlert() == null) {
+ if (System.currentTimeMillis() - cancelledAt >= 10000) finish(bolusId);
+ else {
+ ActiveAlertMessage activeAlertMessage2 = new ActiveAlertMessage();
+ activeAlertMessage2.setMessagePriority(MessagePriority.HIGHER);
+ return activeAlertMessage2;
+ }
+ } else if (!(activeAlertMessage.getAlert() instanceof Warning38BolusCancelled)) finish(bolusId);
+ else {
+ DismissAlertMessage dismissAlertMessage = new DismissAlertMessage();
+ dismissAlertMessage.setAlertID(activeAlertMessage.getAlertID());
+ dismissAlertMessage.setMessagePriority(MessagePriority.HIGHER);
+ return dismissAlertMessage;
+ }
+ } else if (message instanceof DismissAlertMessage) finish(bolusId);
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusTaskRunner.java
deleted file mode 100644
index f350b80851..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelBolusTaskRunner.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package info.nightscout.androidaps.plugins.PumpInsight.connector;
-
-import sugar.free.sightparser.applayer.messages.AppLayerMessage;
-import sugar.free.sightparser.applayer.descriptors.ActiveBolusType;
-import sugar.free.sightparser.applayer.messages.remote_control.CancelBolusMessage;
-import sugar.free.sightparser.applayer.messages.status.ActiveBolusesMessage;
-import sugar.free.sightparser.handling.SightServiceConnector;
-import sugar.free.sightparser.handling.TaskRunner;
-
-// by Tebbe Ubben
-
-public class CancelBolusTaskRunner extends TaskRunner {
-
- private ActiveBolusType bolusType;
-
- public CancelBolusTaskRunner(SightServiceConnector serviceConnector, ActiveBolusType bolusType) {
- super(serviceConnector);
- this.bolusType = bolusType;
- }
-
- @Override
- protected AppLayerMessage run(AppLayerMessage message) throws Exception {
- if (message == null) return new ActiveBolusesMessage();
- else if (message instanceof ActiveBolusesMessage) {
- ActiveBolusesMessage bolusesMessage = (ActiveBolusesMessage) message;
- CancelBolusMessage cancelBolusMessage = new CancelBolusMessage();
- if (bolusesMessage.getBolus1().getBolusType() == bolusType)
- cancelBolusMessage.setBolusId(bolusesMessage.getBolus1().getBolusID());
- else if (bolusesMessage.getBolus2().getBolusType() == bolusType)
- cancelBolusMessage.setBolusId(bolusesMessage.getBolus2().getBolusID());
- else if (bolusesMessage.getBolus3().getBolusType() == bolusType)
- cancelBolusMessage.setBolusId(bolusesMessage.getBolus3().getBolusID());
- else finish(null);
- return cancelBolusMessage;
- } else if (message instanceof CancelBolusMessage) finish(null);
- return null;
- }
-}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelTBRSilentlyTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelTBRSilentlyTaskRunner.java
new file mode 100644
index 0000000000..9a3068aef9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/CancelTBRSilentlyTaskRunner.java
@@ -0,0 +1,50 @@
+package info.nightscout.androidaps.plugins.PumpInsight.connector;
+
+import sugar.free.sightparser.applayer.descriptors.MessagePriority;
+import sugar.free.sightparser.applayer.descriptors.alerts.Warning36TBRCancelled;
+import sugar.free.sightparser.applayer.messages.AppLayerMessage;
+import sugar.free.sightparser.applayer.messages.remote_control.CancelTBRMessage;
+import sugar.free.sightparser.applayer.messages.remote_control.DismissAlertMessage;
+import sugar.free.sightparser.applayer.messages.status.ActiveAlertMessage;
+import sugar.free.sightparser.applayer.messages.status.CurrentTBRMessage;
+import sugar.free.sightparser.handling.SightServiceConnector;
+import sugar.free.sightparser.handling.TaskRunner;
+
+public class CancelTBRSilentlyTaskRunner extends TaskRunner {
+
+ private long cancelledAt;
+
+ public CancelTBRSilentlyTaskRunner(SightServiceConnector serviceConnector) {
+ super(serviceConnector);
+ }
+
+ @Override
+ protected AppLayerMessage run(AppLayerMessage message) throws Exception {
+ if (message == null) return new CurrentTBRMessage();
+ else if (message instanceof CurrentTBRMessage) {
+ if (((CurrentTBRMessage) message).getPercentage() == 100) finish(false);
+ else return new CancelTBRMessage();
+ } else if (message instanceof CancelTBRMessage) {
+ ActiveAlertMessage activeAlertMessage = new ActiveAlertMessage();
+ activeAlertMessage.setMessagePriority(MessagePriority.HIGHER);
+ return activeAlertMessage;
+ } else if (message instanceof ActiveAlertMessage) {
+ ActiveAlertMessage activeAlertMessage = (ActiveAlertMessage) message;
+ if (activeAlertMessage.getAlert() == null) {
+ if (System.currentTimeMillis() - cancelledAt >= 10000) finish(true);
+ else {
+ ActiveAlertMessage activeAlertMessage2 = new ActiveAlertMessage();
+ activeAlertMessage2.setMessagePriority(MessagePriority.HIGHER);
+ return activeAlertMessage2;
+ }
+ } else if (!(activeAlertMessage.getAlert() instanceof Warning36TBRCancelled)) finish(true);
+ else {
+ DismissAlertMessage dismissAlertMessage = new DismissAlertMessage();
+ dismissAlertMessage.setAlertID(activeAlertMessage.getAlertID());
+ dismissAlertMessage.setMessagePriority(MessagePriority.HIGHER);
+ return dismissAlertMessage;
+ }
+ } else if (message instanceof DismissAlertMessage) finish(true);
+ return null;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java
index 1506ecb4a9..f18bb0d487 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/SetTBRTaskRunner.java
@@ -25,25 +25,15 @@ public class SetTBRTaskRunner extends TaskRunner {
if (message == null) return new CurrentTBRMessage();
else if (message instanceof CurrentTBRMessage) {
if (((CurrentTBRMessage) message).getPercentage() == 100) {
- if (amount == 100) finish(amount);
- else {
- SetTBRMessage setTBRMessage = new SetTBRMessage();
- setTBRMessage.setDuration(duration);
- setTBRMessage.setAmount(amount);
- return setTBRMessage;
- }
+ SetTBRMessage setTBRMessage = new SetTBRMessage();
+ setTBRMessage.setDuration(duration);
+ setTBRMessage.setAmount(amount);
+ return setTBRMessage;
} else {
- if (amount == 100) {
- ChangeTBRMessage changeTBRMessage = new ChangeTBRMessage();
- changeTBRMessage.setDuration(1);
- changeTBRMessage.setAmount(90);
- return changeTBRMessage;
- } else {
- ChangeTBRMessage changeTBRMessage = new ChangeTBRMessage();
- changeTBRMessage.setDuration(duration);
- changeTBRMessage.setAmount(amount);
- return changeTBRMessage;
- }
+ ChangeTBRMessage changeTBRMessage = new ChangeTBRMessage();
+ changeTBRMessage.setDuration(duration);
+ changeTBRMessage.setAmount(amount);
+ return changeTBRMessage;
}
} else if (message instanceof SetTBRMessage) finish(amount);
return null;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java
index 86e01f98f8..1df56be468 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/connector/StatusTaskRunner.java
@@ -12,6 +12,8 @@ import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfil
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfile5Block;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.BRProfileBlock;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.ConfigurationBlock;
+import sugar.free.sightparser.applayer.descriptors.configuration_blocks.FactoryMinBRAmountBlock;
+import sugar.free.sightparser.applayer.descriptors.configuration_blocks.FactoryMinBolusAmountBlock;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.MaxBRAmountBlock;
import sugar.free.sightparser.applayer.descriptors.configuration_blocks.MaxBolusAmountBlock;
import sugar.free.sightparser.applayer.messages.AppLayerMessage;
@@ -102,6 +104,16 @@ public class StatusTaskRunner extends TaskRunner {
return readMessage;
} else if (configurationBlock instanceof MaxBRAmountBlock) {
result.maximumBasalAmount = ((MaxBRAmountBlock) configurationBlock).getMaximumAmount();
+ ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage();
+ readMessage.setConfigurationBlockID(FactoryMinBRAmountBlock.ID);
+ return readMessage;
+ } else if (configurationBlock instanceof FactoryMinBRAmountBlock) {
+ result.minimumBasalAmount = ((FactoryMinBRAmountBlock) configurationBlock).getMinimumAmount();
+ ReadConfigurationBlockMessage readMessage = new ReadConfigurationBlockMessage();
+ readMessage.setConfigurationBlockID(FactoryMinBolusAmountBlock.ID);
+ return readMessage;
+ } else if (configurationBlock instanceof FactoryMinBolusAmountBlock) {
+ result.minimumBolusAmount = ((FactoryMinBolusAmountBlock) configurationBlock).getMinimumAmount();
finish(result);
}
}
@@ -122,5 +134,7 @@ public class StatusTaskRunner extends TaskRunner {
public List basalProfile;
public double maximumBolusAmount;
public double maximumBasalAmount;
+ public double minimumBolusAmount;
+ public double minimumBasalAmount;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java
index e7784287b7..2c2235bf47 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryIntentAdapter.java
@@ -58,13 +58,8 @@ class HistoryIntentAdapter {
final long record_unique_id = getRecordUniqueID(pump_serial_number, pump_record_id);
- // other sanity checks
- if ((pump_tbr_percent == 90) && (pump_tbr_duration <= 1)) {
- log("Not creating TBR record for faux cancel");
- } else {
- log("Creating TBR record: " + pump_tbr_percent + "% " + pump_tbr_duration + "m" + " id:" + record_unique_id);
- logAdapter.createTBRrecord(start_time, pump_tbr_percent, pump_tbr_duration, record_unique_id);
- }
+ log("Creating TBR record: " + pump_tbr_percent + "% " + pump_tbr_duration + "m" + " id:" + record_unique_id);
+ logAdapter.createTBRrecord(start_time, pump_tbr_percent, pump_tbr_duration, record_unique_id);
}
void processDeliveredBolusIntent(Intent intent) {
@@ -160,8 +155,10 @@ class HistoryIntentAdapter {
if (SP.getBoolean("insight_automatic_careportal_events", false)) {
Date date = getDateExtra(intent, HistoryBroadcast.EXTRA_EVENT_TIME);
String alertType = intent.getStringExtra(HistoryBroadcast.EXTRA_ALERT_TYPE);
+ int alertText = getAlertText(alertType);
+ if (alertText == 0) return;
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(date.getTime()) != null) return;
- logNote(date, MainApp.gs(getAlertText(alertType)));
+ logNote(date, MainApp.gs(alertText));
}
}
@@ -231,8 +228,8 @@ class HistoryIntentAdapter {
if (type.equals("Warning32BatteryLow")) return R.string.alert_w32;
if (type.equals("Warning33InvalidDateTime")) return R.string.alert_w33;
if (type.equals("Warning34EndOfWarranty")) return R.string.alert_w34;
- if (type.equals("Warning36TBRCancelled")) return R.string.alert_w36;
- if (type.equals("Warning38BolusCancelled")) return R.string.alert_w38;
+ if (type.equals("Warning36TBRCancelled")) return 0;
+ if (type.equals("Warning38BolusCancelled")) return 0;
if (type.equals("Warning39LoantimeWarning")) return R.string.alert_w39;
return 0;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java
index 689eb9e981..bff37c9fdd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpInsight/history/HistoryLogAdapter.java
@@ -83,6 +83,6 @@ class HistoryLogAdapter {
detailedBolusInfo.source = Source.PUMP;
detailedBolusInfo.pumpId = record_id;
detailedBolusInfo.insulin = insulin;
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
}
}
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 fed0c01c64..fb41a72e88 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
@@ -42,6 +42,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
super(new PluginDescription()
.mainType(PluginType.PUMP)
.pluginName(R.string.mdi)
+ .description(R.string.description_pump_mdi)
);
pumpDescription.isBolusCapable = true;
pumpDescription.bolusStep = 0.5d;
@@ -135,7 +136,7 @@ public class MDIPlugin extends PluginBase implements PumpInterface {
result.bolusDelivered = detailedBolusInfo.insulin;
result.carbsDelivered = detailedBolusInfo.carbs;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
return result;
}
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 34d3fee80b..12977b89bf 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
@@ -77,6 +77,8 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
.pluginName(R.string.virtualpump)
.shortName(R.string.virtualpump_shortname)
.preferencesId(R.xml.pref_virtualpump)
+ .neverVisible(BuildConfig.NSCLIENTOLNY || BuildConfig.G5UPLOADER)
+ .description(R.string.description_pump_virtual)
);
pumpDescription.isBolusCapable = true;
pumpDescription.bolusStep = 0.1d;
@@ -224,7 +226,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface {
log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
lastDataTime = new Date();
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
return result;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java
new file mode 100644
index 0000000000..1d96eeff6b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/AbstractSensitivityPlugin.java
@@ -0,0 +1,68 @@
+package info.nightscout.androidaps.plugins.Sensitivity;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.SensitivityInterface;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
+import info.nightscout.utils.Round;
+import info.nightscout.utils.SP;
+import info.nightscout.utils.SafeParse;
+
+public abstract class AbstractSensitivityPlugin extends PluginBase implements SensitivityInterface {
+
+ private static final Logger log = LoggerFactory.getLogger("AUTOSENS");
+
+ public AbstractSensitivityPlugin(PluginDescription pluginDescription) {
+ super(pluginDescription);
+ }
+
+ @Override
+ public abstract AutosensResult detectSensitivity(long fromTime, long toTime);
+
+ public AutosensResult fillResult(double ratio, double carbsAbsorbed, String pastSensitivity,
+ String ratioLimit, String sensResult, int deviationsArraySize) {
+ return this.fillResult(ratio, carbsAbsorbed, pastSensitivity, ratioLimit, sensResult,
+ deviationsArraySize,
+ SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")),
+ SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
+ }
+
+ public AutosensResult fillResult(double ratio, double carbsAbsorbed, String pastSensitivity,
+ String ratioLimit, String sensResult, int deviationsArraySize,
+ double ratioMin, double ratioMax) {
+ double rawRatio = ratio;
+ ratio = Math.max(ratio, ratioMin);
+ ratio = Math.min(ratio, ratioMax);
+
+ //If not-excluded data <= MIN_HOURS -> don't do Autosens
+ //If not-excluded data >= MIN_HOURS_FULL_AUTOSENS -> full Autosens
+ //Between MIN_HOURS and MIN_HOURS_FULL_AUTOSENS: gradually increase autosens
+ double autosensContrib = (Math.min(Math.max(MIN_HOURS, deviationsArraySize / 12d),
+ MIN_HOURS_FULL_AUTOSENS) - MIN_HOURS) / (MIN_HOURS_FULL_AUTOSENS - MIN_HOURS);
+ ratio = autosensContrib * (ratio - 1) + 1;
+
+ if (autosensContrib != 1d) {
+ ratioLimit += "(" + deviationsArraySize + " of " + MIN_HOURS_FULL_AUTOSENS * 12 + " values) ";
+ }
+
+ if (ratio != rawRatio) {
+ ratioLimit += "Ratio limited from " + rawRatio + " to " + ratio;
+ log.debug(ratioLimit);
+ }
+
+ AutosensResult output = new AutosensResult();
+ output.ratio = Round.roundTo(ratio, 0.01);
+ output.carbsAbsorbed = Round.roundTo(carbsAbsorbed, 0.01);
+ output.pastSensitivity = pastSensitivity;
+ output.ratioLimit = ratioLimit;
+ output.sensResult = sensResult;
+ return output;
+ }
+
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java
similarity index 72%
rename from app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java
rename to app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java
index 75b1ea9675..e5ca522a51 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityAAPSPlugin.java
@@ -1,11 +1,10 @@
-package info.nightscout.androidaps.plugins.SensitivityAAPS;
+package info.nightscout.androidaps.plugins.Sensitivity;
import android.support.v4.util.LongSparseArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@@ -15,23 +14,21 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
-import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
-import info.nightscout.utils.Round;
+import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
-import info.nightscout.utils.SafeParse;
/**
* Created by mike on 24.06.2017.
*/
-public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInterface {
- private static Logger log = LoggerFactory.getLogger(SensitivityAAPSPlugin.class);
+public class SensitivityAAPSPlugin extends AbstractSensitivityPlugin {
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
static SensitivityAAPSPlugin plugin = null;
@@ -47,6 +44,7 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
.pluginName(R.string.sensitivityaaps)
.shortName(R.string.sensitivity_shortname)
.preferencesId(R.xml.pref_absorption_aaps)
+ .description(R.string.description_sensitivity_aaps)
);
}
@@ -69,17 +67,19 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
}
if (autosensDataTable == null || autosensDataTable.size() < 4) {
- log.debug("No autosens data available");
+ log.debug("No autosens data available. lastDataTime=" + IobCobCalculatorPlugin.getPlugin().lastDataTime());
return new AutosensResult();
}
AutosensData current = IobCobCalculatorPlugin.getPlugin().getAutosensData(toTime); // this is running inside lock already
if (current == null) {
- log.debug("No autosens data available");
+ log.debug("No autosens data available. toTime: " + DateUtil.dateAndTimeString(toTime) + " lastDataTime: " + IobCobCalculatorPlugin.getPlugin().lastDataTime());
return new AutosensResult();
}
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
List deviationsArray = new ArrayList<>();
String pastSensitivity = "";
int index = 0;
@@ -96,8 +96,21 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
continue;
}
- if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
- deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ deviationsArray.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
+ if (autosensData.validDeviation)
+ if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
+ deviationsArray.add(deviation);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.remove(0);
@@ -138,26 +151,16 @@ public class SensitivityAAPSPlugin extends PluginBase implements SensitivityInte
if (Config.logAutosensData)
log.debug(sensResult);
- double rawRatio = ratio;
- ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")));
- ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
-
- if (ratio != rawRatio) {
- ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
- log.debug(ratioLimit);
- }
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, deviationsArray.size());
if (Config.logAutosensData) {
- log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio + " mealCOB: " + current.cob);
+ log.debug("Sensitivity to: {}, percentile: {} ratio: {} mealCOB: ",
+ new Date(toTime).toLocaleString(),
+ percentile, output.ratio, ratio, current.cob);
log.debug("Sensitivity to: deviations " + Arrays.toString(deviations));
}
- AutosensResult output = new AutosensResult();
- output.ratio = Round.roundTo(ratio, 0.01);
- output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
- output.pastSensitivity = pastSensitivity;
- output.ratioLimit = ratioLimit;
- output.sensResult = sensResult;
return output;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java
similarity index 69%
rename from app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java
rename to app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java
index 15be72880d..c9086dbfbd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref0Plugin.java
@@ -1,4 +1,4 @@
-package info.nightscout.androidaps.plugins.SensitivityOref0;
+package info.nightscout.androidaps.plugins.Sensitivity;
import android.support.v4.util.LongSparseArray;
@@ -14,23 +14,20 @@ import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
-import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
-import info.nightscout.utils.Round;
-import info.nightscout.utils.SP;
-import info.nightscout.utils.SafeParse;
+import info.nightscout.utils.DateUtil;
/**
* Created by mike on 24.06.2017.
*/
-public class SensitivityOref0Plugin extends PluginBase implements SensitivityInterface {
- private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class);
+public class SensitivityOref0Plugin extends AbstractSensitivityPlugin {
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
static SensitivityOref0Plugin plugin = null;
@@ -46,6 +43,7 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
.pluginName(R.string.sensitivityoref0)
.shortName(R.string.sensitivity_shortname)
.preferencesId(R.xml.pref_absorption_oref0)
+ .description(R.string.description_sensitivity_oref0)
);
}
@@ -53,12 +51,7 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
public AutosensResult detectSensitivity(long fromTime, long toTime) {
LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
- String age = SP.getString(R.string.key_age, "");
- int defaultHours = 24;
- if (age.equals(MainApp.gs(R.string.key_adult))) defaultHours = 24;
- if (age.equals(MainApp.gs(R.string.key_teenage))) defaultHours = 24;
- if (age.equals(MainApp.gs(R.string.key_child))) defaultHours = 24;
- int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours);
+ int hoursForDetection = 24;
long now = System.currentTimeMillis();
Profile profile = MainApp.getConfigBuilder().getProfile();
@@ -69,17 +62,19 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
}
if (autosensDataTable == null || autosensDataTable.size() < 4) {
- log.debug("No autosens data available");
+ log.debug("No autosens data available. lastDataTime=" + IobCobCalculatorPlugin.getPlugin().lastDataTime());
return new AutosensResult();
}
AutosensData current = IobCobCalculatorPlugin.getPlugin().getAutosensData(toTime); // this is running inside lock already
if (current == null) {
- log.debug("No current autosens data available");
+ log.debug("No autosens data available. toTime: " + DateUtil.dateAndTimeString(toTime) + " lastDataTime: " + IobCobCalculatorPlugin.getPlugin().lastDataTime());
return new AutosensResult();
}
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
List deviationsArray = new ArrayList<>();
String pastSensitivity = "";
int index = 0;
@@ -96,8 +91,21 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
continue;
}
- if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
- deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ deviationsArray.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
+ if (autosensData.validDeviation)
+ if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L)
+ deviationsArray.add(deviation);
if (deviationsArray.size() > hoursForDetection * 60 / 5)
deviationsArray.remove(0);
@@ -149,24 +157,13 @@ public class SensitivityOref0Plugin extends PluginBase implements SensitivityInt
ratio = 1 + (basalOff / profile.getMaxDailyBasal());
- double rawRatio = ratio;
- ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")));
- ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
-
- if (ratio != rawRatio) {
- ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
- log.debug(ratioLimit);
- }
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, deviationsArray.size());
if (Config.logAutosensData)
- log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " ratio: " + ratio + " mealCOB: " + current.cob);
+ log.debug("Sensitivity to: {} ratio: {} mealCOB: {}",
+ new Date(toTime).toLocaleString(), output.ratio, current.cob);
- AutosensResult output = new AutosensResult();
- output.ratio = Round.roundTo(ratio, 0.01);
- output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
- output.pastSensitivity = pastSensitivity;
- output.ratioLimit = ratioLimit;
- output.sensResult = sensResult;
return output;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java
new file mode 100644
index 0000000000..214c82db9b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityOref1Plugin.java
@@ -0,0 +1,188 @@
+package info.nightscout.androidaps.plugins.Sensitivity;
+
+import android.support.v4.util.LongSparseArray;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.CareportalEvent;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
+import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
+import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
+import info.nightscout.utils.DateUtil;
+
+/**
+ * Created by mike on 19.06.2018.
+ */
+
+public class SensitivityOref1Plugin extends AbstractSensitivityPlugin {
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
+
+ static SensitivityOref1Plugin plugin = null;
+
+ public static SensitivityOref1Plugin getPlugin() {
+ if (plugin == null)
+ plugin = new SensitivityOref1Plugin();
+ return plugin;
+ }
+
+ public SensitivityOref1Plugin() {
+ super(new PluginDescription()
+ .mainType(PluginType.SENSITIVITY)
+ .pluginName(R.string.sensitivityoref1)
+ .shortName(R.string.sensitivity_shortname)
+ .preferencesId(R.xml.pref_absorption_oref1)
+ .description(R.string.description_sensitivity_oref1)
+ );
+ }
+
+ @Override
+ public AutosensResult detectSensitivity(long fromTime, long toTime) {
+ // todo this method is called from the IobCobCalculatorPlugin, which leads to a circular
+ // dependency, this should be avoided
+ LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getPlugin().getAutosensDataTable();
+
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+
+ if (profile == null) {
+ log.debug("No profile");
+ return new AutosensResult();
+ }
+
+ if (autosensDataTable == null || autosensDataTable.size() < 4) {
+ log.debug("No autosens data available. lastDataTime=" + IobCobCalculatorPlugin.getPlugin().lastDataTime());
+ return new AutosensResult();
+ }
+
+ // the current
+ AutosensData current = IobCobCalculatorPlugin.getPlugin().getAutosensData(toTime); // this is running inside lock already
+ if (current == null) {
+ log.debug("No autosens data available. toTime: " + DateUtil.dateAndTimeString(toTime) + " lastDataTime: " + IobCobCalculatorPlugin.getPlugin().lastDataTime());
+ return new AutosensResult();
+ }
+
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
+ List deviationsArray = new ArrayList<>();
+ String pastSensitivity = "";
+ int index = 0;
+ while (index < autosensDataTable.size()) {
+ AutosensData autosensData = autosensDataTable.valueAt(index);
+
+ if (autosensData.time < fromTime) {
+ index++;
+ continue;
+ }
+
+ if (autosensData.time > toTime) {
+ index++;
+ continue;
+ }
+
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ deviationsArray.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
+ if (autosensData.validDeviation)
+ deviationsArray.add(deviation);
+
+ for (int i = 0; i < autosensData.extraDeviation.size(); i++)
+ deviationsArray.add(autosensData.extraDeviation.get(i));
+ if (deviationsArray.size() > 96)
+ deviationsArray.remove(0);
+
+ pastSensitivity += autosensData.pastSensitivity;
+ int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time);
+ if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) {
+ pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")";
+ }
+ index++;
+ }
+
+ // when we have less than 8h worth of deviation data, add up to 90m of zero deviations
+ // this dampens any large sensitivity changes detected based on too little data, without ignoring them completely
+ if (Config.logAutosensData)
+ log.debug("Using most recent " + deviationsArray.size() + " deviations");
+ if (deviationsArray.size() < 96) {
+ int pad = Math.round((1 - deviationsArray.size() / 96) * 18);
+ if (Config.logAutosensData)
+ log.debug("Adding " + pad + " more zero deviations");
+ for (int d = 0; d < pad; d++) {
+ //process.stderr.write(".");
+ deviationsArray.add(0d);
+ }
+ }
+
+ Double[] deviations = new Double[deviationsArray.size()];
+ deviations = deviationsArray.toArray(deviations);
+
+ double sens = profile.getIsf();
+
+ double ratio = 1;
+ String ratioLimit = "";
+ String sensResult = "";
+
+ if (Config.logAutosensData)
+ log.debug("Records: " + index + " " + pastSensitivity);
+
+ Arrays.sort(deviations);
+
+ for (double i = 0.9; i > 0.1; i = i - 0.01) {
+ if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) {
+ if (Config.logAutosensData)
+ log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = sensitivity)");
+ }
+ if (IobCobCalculatorPlugin.percentile(deviations, (i + 0.01)) > 0 && IobCobCalculatorPlugin.percentile(deviations, i) <= 0) {
+ if (Config.logAutosensData)
+ log.debug(Math.round(100 * i) + "% of non-meal deviations negative (>50% = resistance)");
+ }
+ }
+ double pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50);
+ double pResistant = IobCobCalculatorPlugin.percentile(deviations, 0.50);
+
+ double basalOff = 0;
+
+ if (pSensitive < 0) { // sensitive
+ basalOff = pSensitive * (60 / 5) / Profile.toMgdl(sens, profile.getUnits());
+ sensResult = "Excess insulin sensitivity detected";
+ } else if (pResistant > 0) { // resistant
+ basalOff = pResistant * (60 / 5) / Profile.toMgdl(sens, profile.getUnits());
+ sensResult = "Excess insulin resistance detected";
+ } else {
+ sensResult = "Sensitivity normal";
+ }
+
+ if (Config.logAutosensData)
+ log.debug(sensResult);
+
+ ratio = 1 + (basalOff / profile.getMaxDailyBasal());
+
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, deviationsArray.size());
+
+ if (Config.logAutosensData)
+ log.debug("Sensitivity to: {} ratio: {} mealCOB: {}",
+ new Date(toTime).toLocaleString(), output.ratio, current.cob);
+
+ return output;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java
similarity index 71%
rename from app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java
rename to app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java
index 58f59701d9..0200838d39 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Sensitivity/SensitivityWeightedAveragePlugin.java
@@ -1,4 +1,4 @@
-package info.nightscout.androidaps.plugins.SensitivityWeightedAverage;
+package info.nightscout.androidaps.plugins.Sensitivity;
import android.support.v4.util.LongSparseArray;
@@ -6,28 +6,27 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
+import java.util.List;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
-import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
-import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
-import info.nightscout.utils.Round;
+import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
-import info.nightscout.utils.SafeParse;
/**
* Created by mike on 24.06.2017.
*/
-public class SensitivityWeightedAveragePlugin extends PluginBase implements SensitivityInterface {
- private static Logger log = LoggerFactory.getLogger(SensitivityWeightedAveragePlugin.class);
+public class SensitivityWeightedAveragePlugin extends AbstractSensitivityPlugin {
+ private static Logger log = LoggerFactory.getLogger("AUTOSENS");
private static SensitivityWeightedAveragePlugin plugin = null;
@@ -43,6 +42,7 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
.pluginName(R.string.sensitivityweightedaverage)
.shortName(R.string.sensitivity_shortname)
.preferencesId(R.xml.pref_absorption_aaps)
+ .description(R.string.description_sensitivity_weighted_average)
);
}
@@ -58,15 +58,14 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours);
if (autosensDataTable == null || autosensDataTable.size() < 4) {
- if (Config.logAutosensData)
- log.debug("No autosens data available");
+ log.debug("No autosens data available. lastDataTime=" + IobCobCalculatorPlugin.getPlugin().lastDataTime());
return new AutosensResult();
}
AutosensData current = IobCobCalculatorPlugin.getPlugin().getAutosensData(toTime); // this is running inside lock already
if (current == null) {
if (Config.logAutosensData)
- log.debug("No autosens data available");
+ log.debug("No autosens data available. toTime: " + DateUtil.dateAndTimeString(toTime) + " lastDataTime: " + IobCobCalculatorPlugin.getPlugin().lastDataTime());
return new AutosensResult();
}
@@ -78,6 +77,8 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
return new AutosensResult();
}
+ List siteChanges = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, CareportalEvent.SITECHANGE, true);
+
String pastSensitivity = "";
int index = 0;
LongSparseArray data = new LongSparseArray<>();
@@ -100,11 +101,24 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
continue;
}
+ // reset deviations after site change
+ if (CareportalEvent.isEvent5minBack(siteChanges, autosensData.time)) {
+ data.clear();
+ pastSensitivity += "(SITECHANGE)";
+ }
+
+ double deviation = autosensData.deviation;
+
+ //set positive deviations to zero if bg < 80
+ if (autosensData.bg < 80 && deviation > 0)
+ deviation = 0;
+
//data.append(autosensData.time);
long reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L);
- data.append(reverseWeight, autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ if (autosensData.validDeviation)
+ data.append(reverseWeight, deviation);
//weights += reverseWeight;
- //weightedsum += reverseWeight * (autosensData.nonEqualDeviation ? autosensData.deviation : 0d);
+ //weightedsum += reverseWeight * (autosensData.validDeviation ? autosensData.deviation : 0d);
pastSensitivity += autosensData.pastSensitivity;
@@ -116,7 +130,12 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
}
if (data.size() == 0) {
+ if (Config.logAutosensData)
+ log.debug("Data size: " + data.size() + " fromTime: " + DateUtil.dateAndTimeString(fromTime) + " toTime: " + DateUtil.dateAndTimeString(toTime));
return new AutosensResult();
+ } else {
+ if (Config.logAutosensData)
+ log.debug("Data size: " + data.size() + " fromTime: " + DateUtil.dateAndTimeString(fromTime) + " toTime: " + DateUtil.dateAndTimeString(toTime));
}
double weightedsum = 0;
@@ -158,25 +177,13 @@ public class SensitivityWeightedAveragePlugin extends PluginBase implements Sens
if (Config.logAutosensData)
log.debug(sensResult);
- double rawRatio = ratio;
- ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_min, "0.7")));
- ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString(R.string.key_openapsama_autosens_max, "1.2")));
-
- if (ratio != rawRatio) {
- ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio;
- if (Config.logAutosensData)
- log.debug(ratioLimit);
- }
+ AutosensResult output = fillResult(ratio, current.cob, pastSensitivity, ratioLimit,
+ sensResult, data.size());
if (Config.logAutosensData)
- log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio + " mealCOB: " + current.cob);
+ log.debug("Sensitivity to: {} weightedaverage: {} ratio: {} mealCOB: {}", new Date(toTime).toLocaleString(),
+ average, output.ratio, current.cob);
- AutosensResult output = new AutosensResult();
- output.ratio = Round.roundTo(ratio, 0.01);
- output.carbsAbsorbed = Round.roundTo(current.cob, 0.01);
- output.pastSensitivity = pastSensitivity;
- output.ratioLimit = ratioLimit;
- output.sensResult = sensResult;
return output;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
index 9de6cc6ad6..847ead4482 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
@@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.SmsCommunicator;
import android.content.Intent;
import android.content.pm.ResolveInfo;
+import android.os.SystemClock;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
@@ -47,6 +48,7 @@ import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
+import info.nightscout.utils.T;
import info.nightscout.utils.XdripCalibrations;
/**
@@ -124,6 +126,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
.pluginName(R.string.smscommunicator)
.shortName(R.string.smscommunicator_shortname)
.preferencesId(R.xml.pref_smscommunicator)
+ .description(R.string.description_sms_communicator)
);
processSettings(null);
}
@@ -449,12 +452,14 @@ public class SmsCommunicatorPlugin extends PluginBase {
public void run() {
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
if (result.success) {
+ SystemClock.sleep(T.secs(15).msecs()); // wait some time to get history
String reply = String.format(MainApp.gs(R.string.smscommunicator_bolusdelivered), result.bolusDelivered);
if (pump != null)
reply += "\n" + pump.shortStatus(true);
lastRemoteBolusTime = new Date();
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
} else {
+ SystemClock.sleep(T.secs(60).msecs()); // wait some time to get history
String reply = MainApp.gs(R.string.smscommunicator_bolusfailed);
if (pump != null)
reply += "\n" + pump.shortStatus(true);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java
index d526a12971..af040c8c90 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceDexcomG5Plugin.java
@@ -29,6 +29,7 @@ public class SourceDexcomG5Plugin extends PluginBase implements BgSourceInterfac
.shortName(R.string.dexcomG5_shortname)
.showInList(!Config.NSCLIENT)
.preferencesId(R.xml.pref_dexcomg5)
+ .description(R.string.description_source_dexcom_g5)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java
index 0846885df7..38b891ff65 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceGlimpPlugin.java
@@ -24,6 +24,7 @@ public class SourceGlimpPlugin extends PluginBase implements BgSourceInterface {
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment.class.getName())
.pluginName(R.string.Glimp)
+ .description(R.string.description_source_glimp)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java
index 8df63df1e6..041b084efd 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceMM640gPlugin.java
@@ -23,6 +23,7 @@ public class SourceMM640gPlugin extends PluginBase implements BgSourceInterface
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment.class.getName())
.pluginName(R.string.MM640g)
+ .description(R.string.description_source_mm640g)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java
index 3ba85e97a6..c99fbcb9bb 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceNSClientPlugin.java
@@ -20,6 +20,9 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac
return plugin;
}
+ private long lastBGTimeStamp = 0;
+ private boolean isAdvancedFilteringEnabled = false;
+
private SourceNSClientPlugin() {
super(new PluginDescription()
.mainType(PluginType.BGSOURCE)
@@ -27,11 +30,22 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac
.pluginName(R.string.nsclientbg)
.showInList(!Config.NSCLIENT)
.alwaysEnabled(Config.NSCLIENT)
+ .description(R.string.description_source_ns_client)
);
}
@Override
public boolean advancedFilteringSupported() {
- return true;
+ return isAdvancedFilteringEnabled;
+ }
+
+ public void detectSource(String source, long timeStamp) {
+ if (timeStamp > lastBGTimeStamp) {
+ if (source.contains("G5 Native") || source.contains("AndroidAPS-DexcomG5"))
+ isAdvancedFilteringEnabled = true;
+ else
+ isAdvancedFilteringEnabled = false;
+ lastBGTimeStamp = timeStamp;
+ }
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourcePoctechPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourcePoctechPlugin.java
new file mode 100644
index 0000000000..13cb99d392
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourcePoctechPlugin.java
@@ -0,0 +1,39 @@
+package info.nightscout.androidaps.plugins.Source;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.BgSourceInterface;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginDescription;
+import info.nightscout.androidaps.interfaces.PluginType;
+
+/**
+ * Created by mike on 05.08.2016.
+ */
+public class SourcePoctechPlugin extends PluginBase implements BgSourceInterface {
+
+ private static SourcePoctechPlugin plugin = null;
+
+ public static SourcePoctechPlugin getPlugin() {
+ if (plugin == null)
+ plugin = new SourcePoctechPlugin();
+ return plugin;
+ }
+
+ private SourcePoctechPlugin() {
+ super(new PluginDescription()
+ .mainType(PluginType.BGSOURCE)
+ .fragmentClass(BGSourceFragment.class.getName())
+ .pluginName(R.string.poctech)
+ .showInList(!Config.NSCLIENT)
+ .preferencesId(R.xml.pref_poctech)
+ .description(R.string.description_source_poctech)
+ );
+ }
+
+ @Override
+ public boolean advancedFilteringSupported() {
+ return false;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java
index bd3d96162e..fa61c9ea61 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Source/SourceXdripPlugin.java
@@ -26,6 +26,7 @@ public class SourceXdripPlugin extends PluginBase implements BgSourceInterface {
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment.class.getName())
.pluginName(R.string.xdrip)
+ .description(R.string.description_source_xdrip)
);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java
index 99168a2776..01eeee3662 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/CarbsGenerator.java
@@ -50,7 +50,7 @@ public class CarbsGenerator {
}
});
} else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(carbInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(carbInfo, false);
}
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java
index 997a55b5a4..73423c0eab 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/Treatment.java
@@ -57,7 +57,7 @@ public class Treatment implements DataPointWithLabelInterface {
public boolean isSMB = false;
@DatabaseField
- public int insulinInterfaceID = InsulinInterface.FASTACTINGINSULIN; // currently unused, will be used in the future
+ public int insulinInterfaceID = InsulinInterface.OREF_RAPID_ACTING; // currently unused, will be used in the future
@DatabaseField
public double dia = Constants.defaultDIA; // currently unused, will be used in the future
@@ -132,6 +132,24 @@ public class Treatment implements DataPointWithLabelInterface {
return true;
}
+
+ /*
+ * mealBolus, _id and isSMB cannot be known coming from pump. Only compare rest
+ * TODO: remove debug toasts
+ */
+ public boolean equalsRePumpHistory(Treatment other) {
+ if (date != other.date) {
+ return false;
+ }
+ if (insulin != other.insulin) {
+ return false;
+ }
+ if (carbs != other.carbs) {
+ return false;
+ }
+ return true;
+ }
+
public void copyFrom(Treatment t) {
date = t.date;
_id = t._id;
@@ -142,6 +160,14 @@ public class Treatment implements DataPointWithLabelInterface {
isSMB = t.isSMB;
}
+ public void copyBasics(Treatment t) {
+ date = t.date;
+ insulin = t.insulin;
+ carbs = t.carbs;
+ pumpId = t.pumpId;
+ source = t.source;
+ }
+
// ----------------- DataPointInterface --------------------
@Override
public double getX() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java
index 2a5b798018..e701986e89 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentService.java
@@ -241,28 +241,63 @@ public class TreatmentService extends OrmLiteBaseService {
}
// return true if new record is created
- public boolean createOrUpdate(Treatment treatment) {
+ public UpdateReturn createOrUpdate(Treatment treatment) {
try {
Treatment old;
treatment.date = DatabaseHelper.roundDateToSec(treatment.date);
if (treatment.source == Source.PUMP) {
// check for changed from pump change in NS
- QueryBuilder queryBuilder = getDao().queryBuilder();
- Where where = queryBuilder.where();
- where.eq("pumpId", treatment.pumpId);
- PreparedQuery preparedQuery = queryBuilder.prepare();
- List trList = getDao().query(preparedQuery);
- if (trList.size() > 0) {
- // do nothing, pump history record cannot be changed
- log.debug("TREATMENT: Pump record already found in database: " + treatment.toString());
- return false;
+ Treatment existingTreatment = getPumpRecordById(treatment.pumpId);
+ if (existingTreatment != null) {
+ boolean equalRePumpHistory = existingTreatment.equalsRePumpHistory(treatment);
+ boolean sameSource = existingTreatment.source == treatment.source;
+ if(!equalRePumpHistory) {
+ // another treatment exists. Update it with the treatment coming from the pump
+ log.debug("TREATMENT: Pump record already found in database: " + existingTreatment.toString() + " wanting to add " + treatment.toString());
+ long oldDate = existingTreatment.date;
+
+ //preserve carbs
+ if(existingTreatment.isValid && existingTreatment.carbs > 0 && treatment.carbs == 0){
+ treatment.carbs = existingTreatment.carbs;
+ }
+
+ getDao().delete(existingTreatment); // need to delete/create because date may change too
+ existingTreatment.copyBasics(treatment);
+ getDao().create(existingTreatment);
+ DatabaseHelper.updateEarliestDataChange(oldDate);
+ DatabaseHelper.updateEarliestDataChange(existingTreatment.date);
+ scheduleTreatmentChange(treatment);
+ return new UpdateReturn(sameSource, false); //updating a pump treatment with another one from the pump is not counted as clash
+ }
+ return new UpdateReturn(equalRePumpHistory, false);
+ }
+ existingTreatment = getDao().queryForId(treatment.date);
+ if (existingTreatment != null) {
+ // another treatment exists with different pumpID. Update it with the treatment coming from the pump
+ boolean equalRePumpHistory = existingTreatment.equalsRePumpHistory(treatment);
+ boolean sameSource = existingTreatment.source == treatment.source;
+ long oldDate = existingTreatment.date;
+ log.debug("TREATMENT: Pump record already found in database: " + existingTreatment.toString() + " wanting to add " + treatment.toString());
+
+ //preserve carbs
+ if(existingTreatment.isValid && existingTreatment.carbs > 0 && treatment.carbs == 0){
+ treatment.carbs = existingTreatment.carbs;
+ }
+
+ getDao().delete(existingTreatment); // need to delete/create because date may change too
+ existingTreatment.copyFrom(treatment);
+ getDao().create(existingTreatment);
+ DatabaseHelper.updateEarliestDataChange(oldDate);
+ DatabaseHelper.updateEarliestDataChange(existingTreatment.date);
+ scheduleTreatmentChange(treatment);
+ return new UpdateReturn(equalRePumpHistory || sameSource, false);
}
getDao().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
DatabaseHelper.updateEarliestDataChange(treatment.date);
scheduleTreatmentChange(treatment);
- return true;
+ return new UpdateReturn(true, true);
}
if (treatment.source == Source.NIGHTSCOUT) {
old = getDao().queryForId(treatment.date);
@@ -279,9 +314,9 @@ public class TreatmentService extends OrmLiteBaseService {
DatabaseHelper.updateEarliestDataChange(old.date);
}
scheduleTreatmentChange(treatment);
- return true;
+ return new UpdateReturn(true, true);
}
- return false;
+ return new UpdateReturn(true, false);
}
// find by NS _id
if (treatment._id != null) {
@@ -299,7 +334,7 @@ public class TreatmentService extends OrmLiteBaseService {
DatabaseHelper.updateEarliestDataChange(old.date);
}
scheduleTreatmentChange(treatment);
- return true;
+ return new UpdateReturn(true, true);
}
}
}
@@ -307,19 +342,39 @@ public class TreatmentService extends OrmLiteBaseService {
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
DatabaseHelper.updateEarliestDataChange(treatment.date);
scheduleTreatmentChange(treatment);
- return true;
+ return new UpdateReturn(true, true);
}
if (treatment.source == Source.USER) {
getDao().create(treatment);
log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString());
DatabaseHelper.updateEarliestDataChange(treatment.date);
scheduleTreatmentChange(treatment);
- return true;
+ return new UpdateReturn(true, true);
}
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
- return false;
+ return new UpdateReturn(false, false);
+ }
+
+ /** Returns the record for the given id, null if none, throws RuntimeException
+ * if multiple records with the same pump id exist. */
+ @Nullable
+ public Treatment getPumpRecordById(long pumpId) {
+ try {
+ QueryBuilder queryBuilder = getDao().queryBuilder();
+ Where where = queryBuilder.where();
+ where.eq("pumpId", pumpId);
+ PreparedQuery preparedQuery = queryBuilder.prepare();
+ List result = getDao().query(preparedQuery);
+ switch (result.size()) {
+ case 0: return null;
+ case 1: return result.get(0);
+ default: throw new RuntimeException("Multiple records with the same pump id found: " + result.toString());
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
}
public void deleteNS(JSONObject json) {
@@ -423,4 +478,14 @@ public class TreatmentService extends OrmLiteBaseService {
public IBinder onBind(Intent intent) {
return null;
}
+
+ public class UpdateReturn {
+ public UpdateReturn(boolean success, boolean newRecord){
+ this.success = success;
+ this.newRecord = newRecord;
+ }
+ boolean newRecord;
+ boolean success;
+ }
+
}
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 8ae2e6d7b1..b701f66afc 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
@@ -1,7 +1,9 @@
package info.nightscout.androidaps.plugins.Treatments;
+import android.content.Intent;
import android.support.annotation.Nullable;
+import com.crashlytics.android.answers.CustomEvent;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@@ -38,11 +40,13 @@ 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.androidaps.plugins.Overview.Dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
-import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
-import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
+import info.nightscout.androidaps.plugins.Sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import info.nightscout.utils.T;
@@ -78,8 +82,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
.fragmentClass(TreatmentsFragment.class.getName())
.pluginName(R.string.treatments)
.shortName(R.string.treatments_shortname)
- .preferencesId(R.xml.pref_absorption_oref0)
.alwaysEnabled(true)
+ .description(R.string.description_treatments)
);
this.service = new TreatmentService();
}
@@ -465,7 +469,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
// return true if new record is created
@Override
- public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo) {
+ public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) {
Treatment treatment = new Treatment();
treatment.date = detailedBolusInfo.date;
treatment.source = detailedBolusInfo.source;
@@ -477,7 +481,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
treatment.carbs = detailedBolusInfo.carbs;
treatment.source = detailedBolusInfo.source;
treatment.mealBolus = treatment.carbs > 0;
- boolean newRecordCreated = getService().createOrUpdate(treatment);
+ TreatmentService.UpdateReturn creatOrUpdateResult = getService().createOrUpdate(treatment);
+ boolean newRecordCreated = creatOrUpdateResult.newRecord;
//log.debug("Adding new Treatment record" + treatment.toString());
if (detailedBolusInfo.carbTime != 0) {
Treatment carbsTreatment = new Treatment();
@@ -491,6 +496,24 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
}
if (newRecordCreated && detailedBolusInfo.isValid)
NSUpload.uploadTreatmentRecord(detailedBolusInfo);
+
+ if (!allowUpdate && !creatOrUpdateResult.success) {
+ log.error("Treatment could not be added to DB", new Exception());
+
+ String status = String.format(MainApp.gs(R.string.error_adding_treatment_message), treatment.insulin, (int) treatment.carbs, DateUtil.dateAndTimeString(treatment.date));
+
+ Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
+ i.putExtra("soundid", R.raw.error);
+ i.putExtra("title", MainApp.gs(R.string.error_adding_treatment_title));
+ i.putExtra("status", status);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+
+ CustomEvent customEvent = new CustomEvent("TreatmentClash");
+ customEvent.putCustomAttribute("status", status);
+ FabricPrivacy.getInstance().logCustom(customEvent);
+ }
+
return newRecordCreated;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java
index 57ad6833a9..0faceb2382 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java
@@ -43,6 +43,8 @@ import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
+import static info.nightscout.utils.DateUtil.now;
+
public class TreatmentsBolusFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(TreatmentsBolusFragment.class);
@@ -52,6 +54,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
TextView iobTotal;
TextView activityTotal;
Button refreshFromNS;
+ Button deleteFutureTreatments;
Context context;
@@ -89,7 +92,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
else
holder.iob.setTextColor(holder.carbs.getCurrentTextColor());
- if (t.date > DateUtil.now())
+ if (t.date > now())
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorScheduled));
else
holder.date.setTextColor(holder.carbs.getCurrentTextColor());
@@ -189,6 +192,9 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
refreshFromNS = (Button) view.findViewById(R.id.treatments_reshreshfromnightscout);
refreshFromNS.setOnClickListener(this);
+ deleteFutureTreatments = (Button) view.findViewById(R.id.treatments_delete_future_treatments);
+ deleteFutureTreatments.setOnClickListener(this);
+
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false);
if (nsUploadOnly)
refreshFromNS.setVisibility(View.GONE);
@@ -201,17 +207,37 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
@Override
public void onClick(View view) {
+ AlertDialog.Builder builder;
switch (view.getId()) {
case R.id.treatments_reshreshfromnightscout:
- AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext());
+ builder = new AlertDialog.Builder(this.getContext());
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.refresheventsfromnightscout) + "?");
- builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- TreatmentsPlugin.getPlugin().getService().resetTreatments();
- Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
- MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ TreatmentsPlugin.getPlugin().getService().resetTreatments();
+ Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
+ MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
+ });
+ builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
+ builder.show();
+ break;
+ case R.id.treatments_delete_future_treatments:
+ builder = new AlertDialog.Builder(this.getContext());
+ builder.setTitle(MainApp.gs(R.string.confirmation));
+ builder.setMessage(MainApp.gs(R.string.deletefuturetreatments) + "?");
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ final List futureTreatments = TreatmentsPlugin.getPlugin().getService()
+ .getTreatmentDataFromTime(now() + 1000, true);
+ for (Treatment treatment : futureTreatments) {
+ final String _id = treatment._id;
+ if (NSUpload.isIdValid(_id)) {
+ NSUpload.removeCareportalEntryFromNS(_id);
+ } else {
+ UploadQueue.removeID("dbAdd", _id);
+ }
+ TreatmentsPlugin.getPlugin().getService().delete(treatment);
}
+ updateGUI();
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
@@ -233,14 +259,16 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null)
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTreatmentsFromHistory()), false);
- if (TreatmentsPlugin.getPlugin().getLastCalculationTreatments() != null) {
- iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().iob) + " U");
- activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().activity) + " U");
- }
+ activity.runOnUiThread(() -> {
+ recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.getPlugin().getTreatmentsFromHistory()), false);
+ if (TreatmentsPlugin.getPlugin().getLastCalculationTreatments() != null) {
+ iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().iob) + " " + MainApp.gs(R.string.insulin_unit_shortname));
+ activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.getPlugin().getLastCalculationTreatments().activity) + " " + MainApp.gs(R.string.insulin_unit_shortname));
+ }
+ if (!TreatmentsPlugin.getPlugin().getService().getTreatmentDataFromTime(now() + 1000, true).isEmpty()) {
+ deleteFutureTreatments.setVisibility(View.VISIBLE);
+ } else {
+ deleteFutureTreatments.setVisibility(View.GONE);
}
});
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java
index 97c3a05274..7e69883a3d 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsCareportalFragment.java
@@ -107,16 +107,14 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(careportalEvent.date));
- builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- final String _id = careportalEvent._id;
- if (NSUpload.isIdValid(_id)) {
- NSUpload.removeCareportalEntryFromNS(_id);
- } else {
- UploadQueue.removeID("dbAdd", _id);
- }
- MainApp.getDbHelper().delete(careportalEvent);
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ final String _id = careportalEvent._id;
+ if (NSUpload.isIdValid(_id)) {
+ NSUpload.removeCareportalEntryFromNS(_id);
+ } else {
+ UploadQueue.removeID("dbAdd", _id);
}
+ MainApp.getDbHelper().delete(careportalEvent);
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
@@ -136,12 +134,14 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
- RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false));
+ RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEvents(false));
recyclerView.setAdapter(adapter);
refreshFromNS = (Button) view.findViewById(R.id.careportal_refreshfromnightscout);
refreshFromNS.setOnClickListener(this);
+ view.findViewById(R.id.careportal_removeandroidapsstartedevents).setOnClickListener(this);
+
context = getContext();
boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false);
@@ -169,6 +169,16 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
break;
+ case R.id.careportal_removeandroidapsstartedevents:
+ builder = new AlertDialog.Builder(context);
+ builder.setTitle(MainApp.gs(R.string.confirmation));
+ builder.setMessage(MainApp.gs(R.string.careportal_removestartedevents));
+ builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
+ removeAndroidAPSStatedEvents();
+ });
+ builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
+ builder.show();
+ break;
}
}
@@ -185,8 +195,24 @@ public class TreatmentsCareportalFragment extends SubscriberFragment implements
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEventsFromTime(false)), false);
+ recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getDbHelper().getCareportalEvents(false)), false);
}
});
}
+
+ private void removeAndroidAPSStatedEvents() {
+ List events = MainApp.getDbHelper().getCareportalEvents(false);
+ for (int i = 0; i < events.size(); i++) {
+ CareportalEvent careportalEvent = events.get(i);
+ if (careportalEvent.json.contains(MainApp.gs(R.string.androidaps_start))) {
+ final String _id = careportalEvent._id;
+ if (NSUpload.isIdValid(_id)) {
+ NSUpload.removeCareportalEntryFromNS(_id);
+ } else {
+ UploadQueue.removeID("dbAdd", _id);
+ }
+ MainApp.getDbHelper().delete(careportalEvent);
+ }
+ }
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java
index 5ec2723fa4..fc4728c53c 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
@@ -196,6 +196,7 @@ public class ActionStringHandler {
}
boolean useBG = SP.getBoolean(R.string.key_wearwizard_bg, true);
+ boolean useTT = SP.getBoolean(R.string.key_wearwizard_tt, false);
boolean useBolusIOB = SP.getBoolean(R.string.key_wearwizard_bolusiob, true);
boolean useBasalIOB = SP.getBoolean(R.string.key_wearwizard_basaliob, true);
boolean useCOB = SP.getBoolean(R.string.key_wearwizard_cob, true);
@@ -223,7 +224,9 @@ public class ActionStringHandler {
DecimalFormat format = new DecimalFormat("0.00");
DecimalFormat formatInt = new DecimalFormat("0");
BolusWizard bolusWizard = new BolusWizard();
- bolusWizard.doCalc(profile, null, carbsAfterConstraints, useCOB?cobInfo.displayCob:0d, useBG ? bgReading.valueToUnits(profile.getUnits()) : 0d, 0d, percentage, useBolusIOB, useBasalIOB, false, useTrend);
+ bolusWizard.doCalc(profile, useTT ? TreatmentsPlugin.getPlugin().getTempTargetFromHistory() : null,
+ carbsAfterConstraints, useCOB?cobInfo.displayCob:0d, useBG ? bgReading.valueToUnits(profile.getUnits()) : 0d,
+ 0d, percentage, useBolusIOB, useBasalIOB, false, useTrend);
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolusWizard.calculatedTotalInsulin)).value();
if (insulinAfterConstraints - bolusWizard.calculatedTotalInsulin != 0) {
@@ -716,7 +719,7 @@ public class ActionStringHandler {
}
});
} else {
- TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java
index 7282ac0763..6cb47e1a3a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearPlugin.java
@@ -56,6 +56,7 @@ public class WearPlugin extends PluginBase {
.pluginName(R.string.wear)
.shortName(R.string.wear_shortname)
.preferencesId(R.xml.pref_wear)
+ .description(R.string.description_wear)
);
this.ctx = ctx;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
index 696b8b0b57..b5d30ad071 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
@@ -738,11 +738,14 @@ public class WatchUpdaterService extends WearableListenerService implements
public static int getBatteryLevel(Context context) {
Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
- int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
- if (level == -1 || scale == -1) {
- return 50;
+ if (batteryIntent != null) {
+ int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+ if (level == -1 || scale == -1) {
+ return 50;
+ }
+ return (int) (((float) level / (float) scale) * 100.0f);
}
- return (int) (((float) level / (float) scale) * 100.0f);
+ return 50;
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java
index 03c6c48a1a..d5ac60a626 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java
@@ -70,6 +70,7 @@ public class StatuslinePlugin extends PluginBase {
.shortName(R.string.xdripstatus_shortname)
.neverVisible(true)
.preferencesId(R.xml.pref_xdripstatus)
+ .description(R.string.description_xdrip_status_line)
);
this.ctx = ctx;
this.mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx);
diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java
index d2fd2a5e24..47fe4acd6a 100644
--- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java
+++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java
@@ -26,6 +26,7 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperAc
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
+import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.queue.commands.CommandBolus;
import info.nightscout.androidaps.queue.commands.CommandCancelExtendedBolus;
@@ -37,6 +38,7 @@ import info.nightscout.androidaps.queue.commands.CommandLoadTDDs;
import info.nightscout.androidaps.queue.commands.CommandReadStatus;
import info.nightscout.androidaps.queue.commands.CommandSMBBolus;
import info.nightscout.androidaps.queue.commands.CommandSetProfile;
+import info.nightscout.androidaps.queue.commands.CommandSetUserSettings;
import info.nightscout.androidaps.queue.commands.CommandTempBasalAbsolute;
import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent;
@@ -176,6 +178,18 @@ public class CommandQueue {
public synchronized boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS;
+ if (type == Command.CommandType.SMB_BOLUS) {
+ if (isRunning(Command.CommandType.BOLUS) || bolusInQueue()) {
+ log.debug("Rejecting SMB since a bolus is queue/running");
+ return false;
+ }
+ if (detailedBolusInfo.lastKnownBolusTime < TreatmentsPlugin.getPlugin().getLastBolusTime()) {
+ log.debug("Rejecting bolus, another bolus was issued since request time");
+ return false;
+ }
+ }
+
+
if(type.equals(Command.CommandType.BOLUS) && detailedBolusInfo.carbs > 0 && detailedBolusInfo.insulin == 0){
type = Command.CommandType.CARBS_ONLY_TREATMENT;
//Carbs only can be added in parallel as they can be "in the future".
@@ -213,6 +227,12 @@ public class CommandQueue {
return true;
}
+ public synchronized void cancelAllBoluses() {
+ removeAll(Command.CommandType.BOLUS);
+ removeAll(Command.CommandType.SMB_BOLUS);
+ ConfigBuilderPlugin.getActivePump().stopBolusDelivering();
+ }
+
// returns true if command is queued
public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Profile profile, Callback callback) {
if (!enforceNew && isRunning(Command.CommandType.TEMPBASAL)) {
@@ -397,6 +417,25 @@ public class CommandQueue {
return true;
}
+ // returns true if command is queued
+ public boolean setUserOptions(Callback callback) {
+ if (isRunning(Command.CommandType.SETUSERSETTINGS)) {
+ if (callback != null)
+ callback.result(executingNowError()).run();
+ return false;
+ }
+
+ // remove all unfinished
+ removeAll(Command.CommandType.SETUSERSETTINGS);
+
+ // add new command to queue
+ add(new CommandSetUserSettings(callback));
+
+ notifyAboutNewCommand();
+
+ return true;
+ }
+
// returns true if command is queued
public boolean loadTDDs(Callback callback) {
if (isRunning(Command.CommandType.LOADHISTORY)) {
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
index b865fac86e..7156a72f25 100644
--- a/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java
+++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java
@@ -18,7 +18,8 @@ public abstract class Command {
BASALPROFILE,
READSTATUS,
LOADHISTORY, // TDDs and so far only Dana specific
- LOADEVENTS // so far only Dana specific
+ LOADEVENTS, // so far only Dana specific
+ SETUSERSETTINGS // so far only Dana specific
}
public CommandType commandType;
diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java
new file mode 100644
index 0000000000..f3d9fe2a4b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetUserSettings.java
@@ -0,0 +1,45 @@
+package info.nightscout.androidaps.queue.commands;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.interfaces.DanaRInterface;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
+import info.nightscout.androidaps.queue.Callback;
+
+/**
+ * Created by mike on 10.11.2017.
+ */
+
+public class CommandSetUserSettings extends Command {
+ private static Logger log = LoggerFactory.getLogger(CommandSetUserSettings.class);
+ public CommandSetUserSettings(Callback callback) {
+ commandType = CommandType.SETUSERSETTINGS;
+ this.callback = callback;
+ }
+
+ @Override
+ public void execute() {
+ PumpInterface pump = ConfigBuilderPlugin.getActivePump();
+ if (pump instanceof DanaRInterface) {
+ DanaRInterface danaPump = (DanaRInterface) pump;
+ boolean isDanaRv2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class) != null && MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginType.PUMP);
+ if(isDanaRv2){
+ log.debug("MsgSetUserOptions detected for DanaRv2");
+ }
+ PumpEnactResult r = danaPump.setUserOptions();
+ if (callback != null)
+ callback.result(r).run();
+ }
+ }
+
+ @Override
+ public String status() {
+ return "SETUSERSETTINGS";
+ }
+}
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 af46321901..d574b08f40 100644
--- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
@@ -1,9 +1,5 @@
package info.nightscout.androidaps.receivers;
-/**
- * Created by mike on 07.07.2016.
- */
-
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -11,6 +7,7 @@ import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
+import info.nightscout.utils.FabricPrivacy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,6 +22,10 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.utils.LocalAlertUtils;
+
+/**
+ * Created by mike on 07.07.2016.
+ */
public class KeepAliveReceiver extends BroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(KeepAliveReceiver.class);
public static final long STATUS_UPDATE_FREQUENCY = 15 * 60 * 1000L;
@@ -45,6 +46,7 @@ public class KeepAliveReceiver extends BroadcastReceiver {
LocalAlertUtils.shortenSnoozeInterval();
LocalAlertUtils.checkStaleBGAlert();
checkPump();
+ FabricPrivacy.uploadDailyStats();
log.debug("KeepAlive received");
wl.release();
diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java
index 4e01066bf9..a8bd49f430 100644
--- a/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/receivers/NetworkChangeReceiver.java
@@ -36,7 +36,7 @@ public class NetworkChangeReceiver extends BroadcastReceiver {
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) {
- if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
+ if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI && activeNetwork.isConnected()) {
event.wifiConnected = true;
WifiManager wifiManager = (WifiManager) MainApp.instance().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java
new file mode 100644
index 0000000000..c1669b73d0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java
@@ -0,0 +1,616 @@
+package info.nightscout.androidaps.setupwizard;
+
+import android.Manifest;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.support.v7.app.AppCompatActivity;
+
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.BuildConfig;
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.PreferencesActivity;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventConfigBuilderChange;
+import info.nightscout.androidaps.events.EventPumpStatusChanged;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginType;
+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.ConfigBuilder.ConfigBuilderFragment;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
+import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
+import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
+import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
+import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment;
+import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
+import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment;
+import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
+import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment;
+import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin;
+import info.nightscout.androidaps.setupwizard.elements.SWBreak;
+import info.nightscout.androidaps.setupwizard.elements.SWButton;
+import info.nightscout.androidaps.setupwizard.elements.SWFragment;
+import info.nightscout.androidaps.setupwizard.elements.SWHtmlLink;
+import info.nightscout.androidaps.setupwizard.elements.SWInfotext;
+import info.nightscout.androidaps.setupwizard.elements.SWPlugin;
+import info.nightscout.androidaps.setupwizard.elements.SWRadioButton;
+import info.nightscout.androidaps.setupwizard.elements.SWEditString;
+import info.nightscout.androidaps.setupwizard.elements.SWEditUrl;
+import info.nightscout.androidaps.setupwizard.events.EventSWLabel;
+import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
+import info.nightscout.utils.AndroidPermission;
+import info.nightscout.utils.ImportExportPrefs;
+import info.nightscout.utils.LocaleHelper;
+import info.nightscout.utils.PasswordProtection;
+import info.nightscout.utils.SP;
+import info.nightscout.utils.ToastUtils;
+
+public class SWDefinition {
+ private static Logger log = LoggerFactory.getLogger(SWDefinition.class);
+
+ private String packageName;
+
+ private AppCompatActivity activity;
+ private List screens = new ArrayList<>();
+
+ public void setActivity(AppCompatActivity activity) {
+ this.activity = activity;
+ packageName = activity.getPackageName();
+ }
+
+ public AppCompatActivity getActivity() {
+ return activity;
+ }
+
+ public List getScreens() {
+ return screens;
+ }
+
+ SWDefinition add(SWScreen newScreen) {
+ screens.add(newScreen);
+ return this;
+ }
+
+ SWDefinition() {
+ if (BuildConfig.FLAVOR.equals("full") || BuildConfig.FLAVOR.equals("pumpcontrol"))
+ SWDefinitionFull();
+ else if (BuildConfig.FLAVOR.equals("nsclient"))
+ SWDefinitionNSClient();
+ }
+
+ private void SWDefinitionFull() {
+ // List all the screens here
+ add(new SWScreen(R.string.nav_setupwizard)
+ .add(new SWInfotext()
+ .label(R.string.welcometosetupwizard))
+ )
+ .add(new SWScreen(R.string.language)
+ .skippable(false)
+ .add(new SWRadioButton()
+ .option(R.array.languagesArray, R.array.languagesValues)
+ .preferenceId(R.string.key_language).label(R.string.language)
+ .comment(R.string.setupwizard_language_prompt))
+ .validator(() -> {
+ String lang = SP.getString("language", "en");
+ LocaleHelper.setLocale(MainApp.instance().getApplicationContext(), lang);
+ return SP.contains(R.string.key_language);
+ })
+ )
+ .add(new SWScreen(R.string.end_user_license_agreement)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.end_user_license_agreement_text))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.end_user_license_agreement_i_understand)
+ .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false))
+ .action(() -> {
+ SP.putBoolean(R.string.key_i_understand, true);
+ MainApp.bus().post(new EventSWUpdate(false));
+ }))
+ .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false))
+ .validator(() -> SP.getBoolean(R.string.key_i_understand, false))
+ )
+ .add(new SWScreen(R.string.permission)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name))))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.askforpermission)
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
+ .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY)))
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
+ .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)))
+ )
+ .add(new SWScreen(R.string.permission)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(MainApp.gs(R.string.needlocationpermission)))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.askforpermission)
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION))
+ .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION)))
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION))
+ .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)))
+ )
+ .add(new SWScreen(R.string.permission)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(MainApp.gs(R.string.needstoragepermission)))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.askforpermission)
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
+ .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE)))
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
+ .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
+ )
+ .add(new SWScreen(R.string.nav_import)
+ .add(new SWInfotext()
+ .label(R.string.storedsettingsfound))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.nav_import)
+ .action(() -> ImportExportPrefs.importSharedPreferences(getActivity())))
+ .visibility(() -> ImportExportPrefs.file.exists() && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
+ )
+ .add(new SWScreen(R.string.nsclientinternal_title)
+ .skippable(true)
+ .add(new SWInfotext()
+ .label(R.string.nsclientinfotext))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.enable_nsclient)
+ .action(() -> {
+ NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true);
+ NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true);
+ ConfigBuilderFragment.processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL);
+ ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
+ MainApp.bus().post(new EventConfigBuilderChange());
+ MainApp.bus().post(new EventSWUpdate(true));
+ })
+ .visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL)))
+ .add(new SWEditUrl()
+ .preferenceId(R.string.key_nsclientinternal_url)
+ .label(R.string.nsclientinternal_url_title)
+ .comment(R.string.nsclientinternal_url_dialogmessage))
+ .add(new SWEditString()
+ .validator(text -> text.length() >= 12)
+ .preferenceId(R.string.key_nsclientinternal_api_secret)
+ .label(R.string.nsclientinternal_secret_dialogtitle)
+ .comment(R.string.nsclientinternal_secret_dialogmessage))
+ .add(new SWBreak())
+ .add(new SWEventListener(this)
+ .label(R.string.status)
+ .initialStatus(NSClientPlugin.getPlugin().status)
+ .listener(new Object() {
+ @Subscribe
+ public void onEventNSClientStatus(EventNSClientStatus event) {
+ MainApp.bus().post(new EventSWLabel(event.status));
+ }
+ })
+ )
+ .add(new SWBreak())
+ .validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)
+ .visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth))
+ )
+ .add(new SWScreen(R.string.patientage)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.patientage_summary))
+ .add(new SWBreak())
+ .add(new SWRadioButton()
+ .option(R.array.ageArray, R.array.ageValues)
+ .preferenceId(R.string.key_age)
+ .label(R.string.patientage)
+ .comment(R.string.patientage_summary))
+ .validator(() -> SP.contains(R.string.key_age))
+ )
+ .add(new SWScreen(R.string.configbuilder_insulin)
+ .skippable(false)
+ .add(new SWPlugin()
+ .option(PluginType.INSULIN, R.string.configbuilder_insulin_description)
+ .makeVisible(false)
+ .label(R.string.configbuilder_insulin))
+ .add(new SWBreak())
+ .add(new SWInfotext()
+ .label(R.string.diawarning))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.insulinsourcesetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveInsulin();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> MainApp.getConfigBuilder().getActiveInsulin()!= null && ((PluginBase) MainApp.getConfigBuilder().getActiveInsulin()).getPreferencesId() > 0))
+ .validator(() -> MainApp.getConfigBuilder().getActiveInsulin() != null)
+ )
+ .add(new SWScreen(R.string.configbuilder_bgsource)
+ .skippable(false)
+ .add(new SWPlugin()
+ .option(PluginType.BGSOURCE, R.string.configbuilder_bgsource_description)
+ .label(R.string.configbuilder_bgsource))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.bgsourcesetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveBgSource();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> MainApp.getConfigBuilder().getActiveBgSource()!= null && ((PluginBase) MainApp.getConfigBuilder().getActiveBgSource()).getPreferencesId() > 0))
+ .validator(() -> MainApp.getConfigBuilder().getActiveBgSource() != null)
+ )
+ .add(new SWScreen(R.string.configbuilder_profile)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.setupwizard_profile_description))
+ .add(new SWBreak())
+ .add(new SWPlugin()
+ .option(PluginType.PROFILE, R.string.configbuilder_profile_description)
+ .label(R.string.configbuilder_profile))
+ .validator(() -> MainApp.getConfigBuilder().getActiveProfileInterface() != null)
+ )
+ .add(new SWScreen(R.string.nsprofile)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.adjustprofileinns))
+ .add(new SWFragment(this)
+ .add(new NSProfileFragment()))
+ .validator(() -> NSProfilePlugin.getPlugin().getProfile() != null && NSProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard"))
+ .visibility(() -> NSProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE))
+ )
+ .add(new SWScreen(R.string.localprofile)
+ .skippable(false)
+ .add(new SWFragment(this)
+ .add(new LocalProfileFragment()))
+ .validator(() -> LocalProfilePlugin.getPlugin().getProfile() != null && LocalProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard"))
+ .visibility(() -> LocalProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE))
+ )
+ .add(new SWScreen(R.string.simpleprofile)
+ .skippable(false)
+ .add(new SWFragment(this)
+ .add(new SimpleProfileFragment()))
+ .validator(() -> SimpleProfilePlugin.getPlugin().getProfile() != null && SimpleProfilePlugin.getPlugin().getProfile().getDefaultProfile().isValid("StartupWizard"))
+ .visibility(() -> SimpleProfilePlugin.getPlugin().isEnabled(PluginType.PROFILE))
+ )
+ .add(new SWScreen(R.string.profileswitch)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.profileswitch_ismissing))
+ .add(new SWButton()
+ .text(R.string.profileswitch)
+ .action(() -> {
+ NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
+ profileswitch.executeProfileSwitch = true;
+ newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
+ newDialog.show(getActivity().getSupportFragmentManager(), "NewNSTreatmentDialog");
+ }))
+ .validator(() -> MainApp.getConfigBuilder().getProfile() != null)
+ .visibility(() -> MainApp.getConfigBuilder().getProfile() == null)
+ )
+ .add(new SWScreen(R.string.configbuilder_pump)
+ .skippable(false)
+ .add(new SWPlugin()
+ .option(PluginType.PUMP, R.string.configbuilder_pump_description)
+ .label(R.string.configbuilder_pump))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.pumpsetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActivePump();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> ((PluginBase) MainApp.getConfigBuilder().getActivePump()).getPreferencesId() > 0))
+ .add(new SWButton()
+ .text(R.string.readstatus)
+ .action(() -> ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null))
+ .visibility(() -> MainApp.getConfigBuilder().getActivePump() != null))
+ .add(new SWEventListener(this)
+ .listener(new Object() {
+ @Subscribe
+ public void onEventPumpStatusChanged(EventPumpStatusChanged event) {
+ MainApp.bus().post(new EventSWLabel(event.textStatus()));
+ }
+ })
+ )
+ .validator(() -> MainApp.getConfigBuilder().getActivePump() != null && MainApp.getConfigBuilder().getActivePump().isInitialized())
+ )
+ .add(new SWScreen(R.string.configbuilder_aps)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.setupwizard_aps_description))
+ .add(new SWBreak())
+ .add(new SWHtmlLink()
+ .label("https://openaps.readthedocs.io/en/latest/"))
+ .add(new SWBreak())
+ .add(new SWPlugin()
+ .option(PluginType.APS, R.string.configbuilder_aps_description)
+ .label(R.string.configbuilder_aps))
+ .add(new SWButton()
+ .text(R.string.apssetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveAPS();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> MainApp.getConfigBuilder().getActiveAPS() != null && ((PluginBase) MainApp.getConfigBuilder().getActiveAPS()).getPreferencesId() > 0))
+ .validator(() -> MainApp.getConfigBuilder().getActiveAPS() != null)
+ .visibility(() -> Config.APS)
+ )
+ .add(new SWScreen(R.string.configbuilder_loop)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.setupwizard_loop_description))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.enableloop)
+ .action(() -> {
+ LoopPlugin.getPlugin().setPluginEnabled(PluginType.LOOP, true);
+ LoopPlugin.getPlugin().setFragmentVisible(PluginType.LOOP, true);
+ ConfigBuilderFragment.processOnEnabledCategoryChanged(LoopPlugin.getPlugin(), PluginType.LOOP);
+ ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
+ MainApp.bus().post(new EventConfigBuilderChange());
+ MainApp.bus().post(new EventSWUpdate(true));
+ })
+ .visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)))
+ .validator(() -> LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))
+ .visibility(() -> !LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && Config.APS)
+ )
+ .add(new SWScreen(R.string.configbuilder_sensitivity)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.setupwizard_sensitivity_description))
+ .add(new SWHtmlLink()
+ .label(R.string.setupwizard_sensitivity_url))
+ .add(new SWBreak())
+ .add(new SWPlugin()
+ .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description)
+ .label(R.string.configbuilder_sensitivity))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.sensitivitysetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveSensitivity();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null && ((PluginBase) MainApp.getConfigBuilder().getActiveSensitivity()).getPreferencesId() > 0))
+ .validator(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null)
+ )
+ .add(new SWScreen(R.string.objectives)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.setupwizard_objectives_description))
+ .add(new SWButton()
+ .text(R.string.enableobjectives)
+ .action(() -> {
+ ObjectivesPlugin.getPlugin().setPluginEnabled(PluginType.CONSTRAINTS, true);
+ ObjectivesPlugin.getPlugin().setFragmentVisible(PluginType.CONSTRAINTS, true);
+ ConfigBuilderFragment.processOnEnabledCategoryChanged(ObjectivesPlugin.getPlugin(), PluginType.CONSTRAINTS);
+ ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
+ MainApp.bus().post(new EventConfigBuilderChange());
+ MainApp.bus().post(new EventSWUpdate(true));
+ })
+ .visibility(() -> !ObjectivesPlugin.getPlugin().isFragmentVisible()))
+ .validator(() -> ObjectivesPlugin.getPlugin().isEnabled(PluginType.CONSTRAINTS))
+ .visibility(() -> !ObjectivesPlugin.getPlugin().isFragmentVisible() && Config.APS)
+ )
+ .add(new SWScreen(R.string.objectives)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.startobjective))
+ .add(new SWBreak())
+ .add(new SWFragment(this)
+ .add(new ObjectivesFragment()))
+ .validator(() -> ObjectivesPlugin.getPlugin().objectives.get(0).isStarted())
+ .visibility(() -> !ObjectivesPlugin.getPlugin().objectives.get(0).isStarted() && Config.APS)
+ )
+ ;
+ }
+
+ private void SWDefinitionNSClient() {
+ // List all the screens here
+ add(new SWScreen(R.string.nav_setupwizard)
+ .add(new SWInfotext()
+ .label(R.string.welcometosetupwizard))
+ )
+ .add(new SWScreen(R.string.language)
+ .skippable(false)
+ .add(new SWRadioButton()
+ .option(R.array.languagesArray, R.array.languagesValues)
+ .preferenceId(R.string.key_language).label(R.string.language)
+ .comment(R.string.setupwizard_language_prompt))
+ .validator(() -> {
+ String lang = SP.getString("language", "en");
+ LocaleHelper.setLocale(MainApp.instance().getApplicationContext(), lang);
+ return SP.contains(R.string.key_language);
+ })
+ )
+ .add(new SWScreen(R.string.end_user_license_agreement)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.end_user_license_agreement_text))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.end_user_license_agreement_i_understand)
+ .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false))
+ .action(() -> {
+ SP.putBoolean(R.string.key_i_understand, true);
+ MainApp.bus().post(new EventSWUpdate(false));
+ }))
+ .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false))
+ .validator(() -> SP.getBoolean(R.string.key_i_understand, false))
+ )
+ .add(new SWScreen(R.string.permission)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name))))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.askforpermission)
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
+ .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY)))
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))
+ .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)))
+ )
+ .add(new SWScreen(R.string.permission)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(MainApp.gs(R.string.needstoragepermission)))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.askforpermission)
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
+ .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE)))
+ .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))
+ .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
+ )
+ .add(new SWScreen(R.string.nav_import)
+ .add(new SWInfotext()
+ .label(R.string.storedsettingsfound))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.nav_import)
+ .action(() -> ImportExportPrefs.importSharedPreferences(getActivity())))
+ .visibility(() -> ImportExportPrefs.file.exists() && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)))
+ )
+ .add(new SWScreen(R.string.nsclientinternal_title)
+ .skippable(true)
+ .add(new SWInfotext()
+ .label(R.string.nsclientinfotext))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.enable_nsclient)
+ .action(() -> {
+ NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true);
+ NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true);
+ ConfigBuilderFragment.processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL);
+ ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
+ MainApp.bus().post(new EventConfigBuilderChange());
+ MainApp.bus().post(new EventSWUpdate(true));
+ })
+ .visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL)))
+ .add(new SWEditUrl()
+ .preferenceId(R.string.key_nsclientinternal_url)
+ .label(R.string.nsclientinternal_url_title)
+ .comment(R.string.nsclientinternal_url_dialogmessage))
+ .add(new SWEditString()
+ .validator(text -> text.length() >= 12)
+ .preferenceId(R.string.key_nsclientinternal_api_secret)
+ .label(R.string.nsclientinternal_secret_dialogtitle)
+ .comment(R.string.nsclientinternal_secret_dialogmessage))
+ .add(new SWBreak())
+ .add(new SWEventListener(this)
+ .label(R.string.status)
+ .initialStatus(NSClientPlugin.getPlugin().status)
+ .listener(new Object() {
+ @Subscribe
+ public void onEventNSClientStatus(EventNSClientStatus event) {
+ MainApp.bus().post(new EventSWLabel(event.status));
+ }
+ })
+ )
+ .add(new SWBreak())
+ .validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)
+ .visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth))
+ )
+ .add(new SWScreen(R.string.patientage)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.patientage_summary))
+ .add(new SWBreak())
+ .add(new SWRadioButton()
+ .option(R.array.ageArray, R.array.ageValues)
+ .preferenceId(R.string.key_age)
+ .label(R.string.patientage)
+ .comment(R.string.patientage_summary))
+ .validator(() -> SP.contains(R.string.key_age))
+ )
+ .add(new SWScreen(R.string.configbuilder_insulin)
+ .skippable(false)
+ .add(new SWPlugin()
+ .option(PluginType.INSULIN, R.string.configbuilder_insulin_description)
+ .makeVisible(false)
+ .label(R.string.configbuilder_insulin))
+ .add(new SWBreak())
+ .add(new SWInfotext()
+ .label(R.string.diawarning))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.insulinsourcesetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveInsulin();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> MainApp.getConfigBuilder().getActiveInsulin()!= null && ((PluginBase) MainApp.getConfigBuilder().getActiveInsulin()).getPreferencesId() > 0))
+ .validator(() -> MainApp.getConfigBuilder().getActiveInsulin() != null)
+ )
+ .add(new SWScreen(R.string.configbuilder_sensitivity)
+ .skippable(false)
+ .add(new SWInfotext()
+ .label(R.string.setupwizard_sensitivity_description))
+ .add(new SWHtmlLink()
+ .label(R.string.setupwizard_sensitivity_url))
+ .add(new SWBreak())
+ .add(new SWPlugin()
+ .option(PluginType.SENSITIVITY, R.string.configbuilder_sensitivity_description)
+ .label(R.string.configbuilder_sensitivity))
+ .add(new SWBreak())
+ .add(new SWButton()
+ .text(R.string.sensitivitysetup)
+ .action(() -> {
+ final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveSensitivity();
+ PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
+ Intent i = new Intent(activity, PreferencesActivity.class);
+ i.putExtra("id", plugin.getPreferencesId());
+ activity.startActivity(i);
+ }, null);
+ })
+ .visibility(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null && ((PluginBase) MainApp.getConfigBuilder().getActiveSensitivity()).getPreferencesId() > 0))
+ .validator(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null)
+ )
+ ;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java
new file mode 100644
index 0000000000..487a80d91c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.java
@@ -0,0 +1,72 @@
+package info.nightscout.androidaps.setupwizard;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.setupwizard.elements.SWItem;
+import info.nightscout.androidaps.setupwizard.events.EventSWLabel;
+
+
+public class SWEventListener extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWEventListener.class);
+
+ private int textLabel = 0;
+ private String status = "";
+ TextView textView;
+ Object listener;
+ SWDefinition definition;
+
+ SWEventListener(SWDefinition definition) {
+ super(Type.LISTENER);
+ this.definition = definition;
+ MainApp.bus().register(this);
+ }
+
+ public SWEventListener label(int newLabel) {
+ this.textLabel = newLabel;
+ return this;
+ }
+
+ public SWEventListener initialStatus(String status) {
+ this.status = status;
+ return this;
+ }
+
+ public SWEventListener listener(Object listener) {
+ this.listener = listener;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ textView = new TextView(context);
+ textView.setId(layout.generateViewId());
+ textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status);
+ layout.addView(textView);
+ if (listener != null)
+ try {
+ MainApp.bus().register(listener);
+ } catch (Exception ignored) {}
+ }
+
+ @Subscribe
+ public void onEventSWLabel(final EventSWLabel l) {
+ status = l.label;
+ if (definition != null && definition.getActivity() != null)
+ definition.getActivity().runOnUiThread(() -> {
+ if (textView != null)
+ textView.setText((textLabel != 0 ? MainApp.gs(textLabel) : "") + " " + status);
+ });
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWScreen.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWScreen.java
new file mode 100644
index 0000000000..5c7b10315f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWScreen.java
@@ -0,0 +1,49 @@
+package info.nightscout.androidaps.setupwizard;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.setupwizard.elements.SWItem;
+
+public class SWScreen {
+
+ int header;
+ List items = new ArrayList<>();
+ SWValidator validator;
+ SWValidator visibility;
+ boolean skippable = false;
+
+ public SWScreen(int header) {
+ this.header = header;
+ }
+
+ public String getHeader() {
+ return MainApp.gs(header);
+ }
+
+ public SWScreen skippable(boolean skippable) {
+ this.skippable = skippable;
+ return this;
+ }
+
+ public SWScreen add(SWItem newItem) {
+ items.add(newItem);
+ return this;
+ }
+
+ public SWScreen validator(SWValidator validator) {
+ this.validator = validator;
+ return this;
+ }
+
+ public SWScreen visibility(SWValidator visibility) {
+ this.visibility = visibility;
+ return this;
+ }
+
+ public void processVisibility() {
+ for (SWItem i : items)
+ i.processVisibility();
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWTextValidator.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWTextValidator.java
new file mode 100644
index 0000000000..427afbd45d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWTextValidator.java
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.setupwizard;
+
+public interface SWTextValidator {
+ boolean isValid(String text);
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWValidator.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWValidator.java
new file mode 100644
index 0000000000..3cc8d6b0c1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWValidator.java
@@ -0,0 +1,5 @@
+package info.nightscout.androidaps.setupwizard;
+
+public interface SWValidator {
+ boolean isValid();
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java
new file mode 100644
index 0000000000..5102e36ac6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java
@@ -0,0 +1,226 @@
+package info.nightscout.androidaps.setupwizard;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainActivity;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventProfileStoreChanged;
+import info.nightscout.androidaps.events.EventProfileSwitchChange;
+import info.nightscout.androidaps.events.EventPumpStatusChanged;
+import info.nightscout.androidaps.plugins.ConstraintsObjectives.events.EventObjectivesSaved;
+import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus;
+import info.nightscout.androidaps.setupwizard.elements.SWItem;
+import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
+import info.nightscout.utils.AndroidPermission;
+import info.nightscout.utils.LocaleHelper;
+import info.nightscout.utils.OKDialog;
+import info.nightscout.utils.SP;
+
+public class SetupWizardActivity extends AppCompatActivity {
+ //logging
+ private static Logger log = LoggerFactory.getLogger(SetupWizardActivity.class);
+
+ ScrollView scrollView;
+
+ private SWDefinition swDefinition = new SWDefinition();
+ private List screens = swDefinition.getScreens();
+ private int currentWizardPage = 0;
+ public static final String INTENT_MESSAGE = "WIZZARDPAGE";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LocaleHelper.onCreate(this, "en");
+ setContentView(R.layout.activity_setupwizard);
+
+ scrollView = (ScrollView) findViewById(R.id.sw_scrollview);
+
+ Intent intent = getIntent();
+ currentWizardPage = intent.getIntExtra(SetupWizardActivity.INTENT_MESSAGE, 0);
+ if (screens.size() > 0 && currentWizardPage < screens.size()) {
+ SWScreen currentScreen = screens.get(currentWizardPage);
+
+ //Set screen name
+ TextView screenName = (TextView) findViewById(R.id.sw_content);
+ screenName.setText(currentScreen.getHeader());
+
+ swDefinition.setActivity(this);
+ //Generate layout first
+ generateLayout();
+ updateButtons();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (currentWizardPage == 0) OKDialog.showConfirmation(this, MainApp.gs(R.string.exitwizard), this::finish);
+ else showPreviousPage(null);
+ }
+
+ public void exitPressed(View view) {
+ SP.putBoolean(R.string.key_setupwizard_processed, true);
+ OKDialog.showConfirmation(this, MainApp.gs(R.string.exitwizard), this::finish);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ MainApp.bus().unregister(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ MainApp.bus().register(this);
+ swDefinition.setActivity(this);
+ }
+
+ @Subscribe
+ public void onContentUpdate(EventSWUpdate ev) {
+ if (ev.redraw)
+ generateLayout();
+ updateButtons();
+ }
+
+ @Subscribe
+ public void onEventNSClientStatus(EventNSClientStatus ignored) {
+ updateButtons();
+ }
+
+ @Subscribe
+ public void onEventPumpStatusChanged(EventPumpStatusChanged ignored) {
+ updateButtons();
+ }
+
+ @Subscribe
+ public void onEventProfileStoreChanged(EventProfileStoreChanged ignored) {
+ updateButtons();
+ }
+
+ @Subscribe
+ public void onEventProfileSwitchChange(EventProfileSwitchChange ignored) {
+ updateButtons();
+ }
+
+ @Subscribe
+ public void onEventObjectivesSaved(EventObjectivesSaved ignored) {
+ updateButtons();
+ }
+
+ private void generateLayout() {
+ SWScreen currentScreen = screens.get(currentWizardPage);
+ LinearLayout layout = SWItem.generateLayout(this.findViewById(R.id.sw_content_fields));
+ for (int i = 0; i < currentScreen.items.size(); i++) {
+ SWItem currentItem = currentScreen.items.get(i);
+ currentItem.generateDialog(layout);
+ }
+ scrollView.smoothScrollTo(0,0);
+ }
+
+ private void updateButtons() {
+ runOnUiThread(() -> {
+ SWScreen currentScreen = screens.get(currentWizardPage);
+ if (currentScreen.validator == null || currentScreen.validator.isValid() || currentScreen.skippable) {
+ if (currentWizardPage == nextPage()) {
+ findViewById(R.id.finish_button).setVisibility(View.VISIBLE);
+ findViewById(R.id.next_button).setVisibility(View.GONE);
+ } else {
+ findViewById(R.id.finish_button).setVisibility(View.GONE);
+ findViewById(R.id.next_button).setVisibility(View.VISIBLE);
+ }
+ } else {
+ findViewById(R.id.finish_button).setVisibility(View.GONE);
+ findViewById(R.id.next_button).setVisibility(View.GONE);
+ }
+ if (currentWizardPage == 0)
+ findViewById(R.id.previous_button).setVisibility(View.GONE);
+ else
+ findViewById(R.id.previous_button).setVisibility(View.VISIBLE);
+ currentScreen.processVisibility();
+ });
+ }
+
+ public void showNextPage(View view) {
+ this.finish();
+ Intent intent = new Intent(this, SetupWizardActivity.class);
+ intent.putExtra(INTENT_MESSAGE, nextPage());
+ startActivity(intent);
+ }
+
+ public void showPreviousPage(View view) {
+ this.finish();
+ Intent intent = new Intent(this, SetupWizardActivity.class);
+ intent.putExtra(INTENT_MESSAGE, previousPage());
+ startActivity(intent);
+ }
+
+ // Go back to overview
+ public void finishSetupWizard(View view) {
+ SP.putBoolean(R.string.key_setupwizard_processed, true);
+ Intent intent = new Intent(this, MainActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ finish();
+ }
+
+ private int nextPage() {
+ int page = currentWizardPage + 1;
+ while (page < screens.size()) {
+ if (screens.get(page).visibility == null || screens.get(page).visibility.isValid())
+ return page;
+ page++;
+ }
+ return currentWizardPage;
+ }
+
+ private int previousPage() {
+ int page = currentWizardPage - 1;
+ while (page >= 0) {
+ if (screens.get(page).visibility == null || screens.get(page).visibility.isValid())
+ return page;
+ page--;
+ }
+ return currentWizardPage;
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (permissions.length != 0) {
+ if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
+ switch (requestCode) {
+ case AndroidPermission.CASE_STORAGE:
+ //show dialog after permission is granted
+ AlertDialog.Builder alert = new AlertDialog.Builder(this);
+ alert.setMessage(R.string.alert_dialog_storage_permission_text);
+ alert.setPositiveButton(R.string.ok, null);
+ alert.show();
+ break;
+ case AndroidPermission.CASE_LOCATION:
+ case AndroidPermission.CASE_SMS:
+ case AndroidPermission.CASE_BATTERY:
+ break;
+ }
+ }
+ }
+ updateButtons();
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java
new file mode 100644
index 0000000000..c6a9cf3f86
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWBreak.java
@@ -0,0 +1,47 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.setupwizard.SWValidator;
+
+
+public class SWBreak extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWBreak.class);
+
+ private TextView l;
+ private SWValidator visibilityValidator;
+
+ public SWBreak() {
+ super(Type.TEXT);
+ }
+
+ public SWBreak visibility(SWValidator visibilityValidator) {
+ this.visibilityValidator = visibilityValidator;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ l = new TextView(context);
+ l.setId(View.generateViewId());
+ l.setText("\n");
+ layout.addView(l);
+
+ }
+
+ @Override
+ public void processVisibility() {
+ if (visibilityValidator != null && !visibilityValidator.isValid())
+ l.setVisibility(View.GONE);
+ else
+ l.setVisibility(View.VISIBLE);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java
new file mode 100644
index 0000000000..afa28c1803
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWButton.java
@@ -0,0 +1,63 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.setupwizard.SWValidator;
+
+public class SWButton extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWButton.class);
+
+ private Runnable buttonRunnable;
+ private int buttonText;
+ private SWValidator buttonValidator;
+
+ private Button button;
+
+ public SWButton() {
+ super(Type.BUTTON);
+ }
+
+ public SWButton text(int buttonText) {
+ this.buttonText = buttonText;
+ return this;
+ }
+
+ public SWButton action(Runnable buttonRunnable) {
+ this.buttonRunnable = buttonRunnable;
+ return this;
+ }
+
+ public SWButton visibility(SWValidator buttonValidator) {
+ this.buttonValidator = buttonValidator;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ button = new Button(context);
+ button.setText(buttonText);
+ button.setOnClickListener((v) -> {
+ if (buttonRunnable != null)
+ buttonRunnable.run();
+ });
+ processVisibility();
+ layout.addView(button);
+ super.generateDialog(layout);
+ }
+
+ @Override
+ public void processVisibility() {
+ if (buttonValidator != null && !buttonValidator.isValid())
+ button.setVisibility(View.GONE);
+ else
+ button.setVisibility(View.VISIBLE);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java
new file mode 100644
index 0000000000..ed96b37944
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWCheckbox.java
@@ -0,0 +1,76 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import android.widget.CheckBox;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.utils.SP;
+
+/**
+ * Created by Rumen Georgiev on 5/9/2018.
+ */
+
+public class SWCheckbox extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWCheckbox.class);
+
+ int labelsArray;
+ int valuesArray;
+ String label = "";
+ int preferenceID;
+ private CheckBox checkBox;
+
+ public SWCheckbox() {
+ super(Type.CHECKBOX);
+ }
+
+ public SWCheckbox option(String label, int preferenceID) {
+ this.label = label;
+ this.preferenceID = preferenceID;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+ // Get if there is already value in SP
+ Boolean previousValue;
+ previousValue = SP.getBoolean(preferenceId, false);
+ checkBox = new CheckBox(context);
+ checkBox.setText(label);
+ checkBox.setChecked(previousValue);
+ checkBox.setVisibility(View.VISIBLE);
+ checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ ArrayList pluginsInCategory;
+ pluginsInCategory = MainApp.getSpecificPluginsList(PluginType.PUMP);
+ PluginBase found = null;
+ for (PluginBase p : pluginsInCategory) {
+ if (p.isEnabled(PluginType.PUMP) && found == null) {
+ found = p;
+ } else if (p.isEnabled(PluginType.PUMP)) {
+ // set others disabled
+ p.setPluginEnabled(PluginType.PUMP, false);
+ }
+ }
+ log.debug("Enabled pump plugin:"+found.getClass());
+ save(checkBox.isChecked());
+ }
+ });
+ layout.addView(checkBox);
+ super.generateDialog(layout);
+ }
+ public void save(boolean value){
+ SP.putBoolean(preferenceID, value);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java
new file mode 100644
index 0000000000..d02f10acf0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditString.java
@@ -0,0 +1,79 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.setupwizard.SWTextValidator;
+import info.nightscout.utils.SP;
+
+
+public class SWEditString extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWEditString.class);
+
+ private SWTextValidator validator = null;
+
+ public SWEditString() {
+ super(Type.STRING);
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ TextView l = new TextView(context);
+ l.setId(layout.generateViewId());
+ l.setText(label);
+ l.setTypeface(l.getTypeface(), Typeface.BOLD);
+ layout.addView(l);
+
+ TextView c = new TextView(context);
+ c.setId(layout.generateViewId());
+ c.setText(comment);
+ c.setTypeface(c.getTypeface(), Typeface.ITALIC);
+ layout.addView(c);
+
+ EditText editText = new EditText(context);
+ editText.setId(layout.generateViewId());
+ editText.setInputType(InputType.TYPE_CLASS_TEXT);
+ editText.setMaxLines(1);
+ editText.setText(SP.getString(preferenceId, ""));
+ layout.addView(editText);
+ super.generateDialog(layout);
+
+ editText.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) {
+ if (validator != null && validator.isValid(s.toString()))
+ save(s.toString());
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ });
+ }
+
+ public SWEditString preferenceId(int preferenceId) {
+ this.preferenceId = preferenceId;
+ return this;
+ }
+
+ public SWEditString validator(SWTextValidator validator) {
+ this.validator = validator;
+ return this;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java
new file mode 100644
index 0000000000..04b02a5bc2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWEditUrl.java
@@ -0,0 +1,77 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.Patterns;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+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.setupwizard.events.EventSWLabel;
+import info.nightscout.utils.SP;
+
+public class SWEditUrl extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWEditUrl.class);
+
+ public SWEditUrl() {
+ super(Type.URL);
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ TextView l = new TextView(context);
+ l.setId(View.generateViewId());
+ l.setText(label);
+ l.setTypeface(l.getTypeface(), Typeface.BOLD);
+ layout.addView(l);
+
+ TextView c = new TextView(context);
+ c.setId(View.generateViewId());
+ c.setText(comment);
+ c.setTypeface(c.getTypeface(), Typeface.ITALIC);
+ layout.addView(c);
+
+ EditText editText = new EditText(context);
+ editText.setId(View.generateViewId());
+ editText.setInputType(InputType.TYPE_CLASS_TEXT);
+ editText.setMaxLines(1);
+ editText.setText(SP.getString(preferenceId, ""));
+ layout.addView(editText);
+ super.generateDialog(layout);
+
+ editText.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) {
+ if (Patterns.WEB_URL.matcher(s).matches())
+ save(s.toString());
+ else
+ MainApp.bus().post(new EventSWLabel(MainApp.gs(R.string.error_url_not_valid)));
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ });
+ }
+
+ public SWEditUrl preferenceId(int preferenceId) {
+ this.preferenceId = preferenceId;
+ return this;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java
new file mode 100644
index 0000000000..a061f57eb6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWFragment.java
@@ -0,0 +1,34 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.support.v4.app.Fragment;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.setupwizard.SWDefinition;
+
+
+public class SWFragment extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWFragment.class);
+
+ SWDefinition definition;
+ Fragment fragment;
+
+ public SWFragment(SWDefinition definition) {
+ super(Type.FRAGMENT);
+ this.definition = definition;
+ }
+
+ public SWFragment add(Fragment fragment) {
+ this.fragment = fragment;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ definition.getActivity().getSupportFragmentManager().beginTransaction().add(layout.getId(), fragment, fragment.getTag()).commit();
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java
new file mode 100644
index 0000000000..fd4ffdd524
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWHtmlLink.java
@@ -0,0 +1,63 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.text.util.Linkify;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.setupwizard.SWValidator;
+
+
+public class SWHtmlLink extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWHtmlLink.class);
+ private String textLabel = null;
+
+ private TextView l;
+ private SWValidator visibilityValidator;
+
+ public SWHtmlLink() {
+ super(Type.HTMLLINK);
+ }
+
+ public SWHtmlLink label(int label) {
+ this.label = label;
+ return this;
+ }
+
+ public SWHtmlLink label(String newLabel){
+ this.textLabel = newLabel;
+ return this;
+ }
+
+ public SWHtmlLink visibility(SWValidator visibilityValidator) {
+ this.visibilityValidator = visibilityValidator;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ l = new TextView(context);
+ l.setId(View.generateViewId());
+ l.setAutoLinkMask(Linkify.ALL);
+ if(textLabel != null)
+ l.setText(textLabel);
+ else
+ l.setText(label);
+ layout.addView(l);
+
+ }
+
+ @Override
+ public void processVisibility() {
+ if (visibilityValidator != null && !visibilityValidator.isValid())
+ l.setVisibility(View.GONE);
+ else
+ l.setVisibility(View.VISIBLE);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java
new file mode 100644
index 0000000000..91e5c2da2d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWInfotext.java
@@ -0,0 +1,61 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.setupwizard.SWValidator;
+
+
+public class SWInfotext extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWInfotext.class);
+ private String textLabel = null;
+
+ private TextView l;
+ private SWValidator visibilityValidator;
+
+ public SWInfotext() {
+ super(Type.TEXT);
+ }
+
+ public SWInfotext label(int label) {
+ this.label = label;
+ return this;
+ }
+
+ public SWInfotext label(String newLabel){
+ this.textLabel = newLabel;
+ return this;
+ }
+
+ public SWInfotext visibility(SWValidator visibilityValidator) {
+ this.visibilityValidator = visibilityValidator;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+
+ l = new TextView(context);
+ l.setId(View.generateViewId());
+ if(textLabel != null)
+ l.setText(textLabel);
+ else
+ l.setText(label);
+ layout.addView(l);
+
+ }
+
+ @Override
+ public void processVisibility() {
+ if (visibilityValidator != null && !visibilityValidator.isValid())
+ l.setVisibility(View.GONE);
+ else
+ l.setVisibility(View.VISIBLE);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java
new file mode 100644
index 0000000000..4f454b843d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWItem.java
@@ -0,0 +1,86 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.view.View;
+import android.widget.LinearLayout;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.events.EventPreferenceChange;
+import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
+import info.nightscout.utils.SP;
+
+public class SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWItem.class);
+
+ public enum Type {
+ NONE,
+ TEXT,
+ HTMLLINK,
+ BREAK,
+ LISTENER,
+ URL,
+ STRING,
+ NUMBER,
+ DECIMALNUMBER,
+ CHECKBOX,
+ RADIOBUTTON,
+ PLUGIN,
+ BUTTON,
+ FRAGMENT
+ }
+
+ Type type;
+ Integer label;
+ Integer comment;
+ int preferenceId;
+
+
+ public SWItem(Type type) {
+ this.type = type;
+ }
+
+ String getLabel() {
+ return MainApp.gs(label);
+ }
+
+ String getComment() {
+ if (comment != null)
+ return MainApp.gs(comment);
+ else
+ return "";
+ }
+
+ Type getType() {
+ return type;
+ }
+
+ public SWItem label(int label) {
+ this.label = label;
+ return this;
+ }
+
+ public SWItem comment(int comment) {
+ this.comment = comment;
+ return this;
+ }
+
+ public void save(String value) {
+ SP.putString(preferenceId, value);
+ MainApp.bus().post(new EventPreferenceChange(preferenceId));
+ MainApp.bus().post(new EventSWUpdate());
+ }
+
+ public static LinearLayout generateLayout(View view) {
+ LinearLayout layout = (LinearLayout) view.findViewById(view.getId());
+ layout.removeAllViews();
+ return layout;
+ }
+
+ public void generateDialog(LinearLayout layout) {
+ }
+
+ public void processVisibility() {
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java
new file mode 100644
index 0000000000..80f60eb678
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java
@@ -0,0 +1,97 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.TextView;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.events.EventConfigBuilderChange;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.PluginType;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
+
+public class SWPlugin extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWPlugin.class);
+
+ private PluginType pType;
+ private RadioGroup radioGroup;
+ private int pluginDescription;
+
+ private boolean makeVisible = true;
+
+ public SWPlugin() {
+ super(Type.PLUGIN);
+ }
+
+ public SWPlugin option(PluginType pType, int pluginDescription) {
+ this.pType = pType;
+ this.pluginDescription = pluginDescription;
+ return this;
+ }
+
+ public SWPlugin makeVisible(boolean makeVisible) {
+ this.makeVisible = makeVisible;
+ return this;
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+
+ Context context = layout.getContext();
+ radioGroup = new RadioGroup(context);
+ radioGroup.clearCheck();
+
+ ArrayList pluginsInCategory = MainApp.getSpecificPluginsList(pType);
+
+ radioGroup.setOrientation(LinearLayout.VERTICAL);
+ radioGroup.setVisibility(View.VISIBLE);
+
+ TextView pdesc = new TextView(context);
+ pdesc.setText(pluginDescription);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, 0, 40);
+ pdesc.setLayoutParams(params);
+ layout.addView(pdesc);
+
+ for (int i = 0; i < pluginsInCategory.size(); i++) {
+ RadioButton rdbtn = new RadioButton(context);
+ PluginBase p = pluginsInCategory.get(i);
+ rdbtn.setId(View.generateViewId());
+ rdbtn.setText(p.getName());
+ if (p.isEnabled(pType))
+ rdbtn.setChecked(true);
+ rdbtn.setTag(p);
+ radioGroup.addView(rdbtn);
+ params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ params.setMargins(80, 0, 0, 0);
+ TextView desc = new TextView(context);
+ desc.setText(p.getDescription());
+ desc.setLayoutParams(params);
+ radioGroup.addView(desc);
+ }
+
+ radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
+ RadioButton rb = group.findViewById(checkedId);
+ PluginBase plugin = (PluginBase) rb.getTag();
+ plugin.setPluginEnabled(pType, rb.isChecked());
+ plugin.setFragmentVisible(pType, rb.isChecked() && makeVisible);
+ ConfigBuilderFragment.processOnEnabledCategoryChanged(plugin, pType);
+ ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard");
+ MainApp.bus().post(new EventConfigBuilderChange());
+ MainApp.bus().post(new EventSWUpdate());
+ });
+ layout.addView(radioGroup);
+ super.generateDialog(layout);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java
new file mode 100644
index 0000000000..80346c433c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWRadioButton.java
@@ -0,0 +1,73 @@
+package info.nightscout.androidaps.setupwizard.elements;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.utils.SP;
+
+public class SWRadioButton extends SWItem {
+ private static Logger log = LoggerFactory.getLogger(SWRadioButton.class);
+
+ int labelsArray;
+ int valuesArray;
+ private RadioGroup radioGroup;
+
+ public SWRadioButton() {
+ super(Type.RADIOBUTTON);
+ }
+
+ public SWRadioButton option(int labels, int values) {
+ this.labelsArray = labels;
+ this.valuesArray = values;
+ return this;
+ }
+
+ public String[] labels() {
+ return MainApp.sResources.getStringArray(labelsArray);
+ }
+
+ public String[] values() {
+ return MainApp.sResources.getStringArray(valuesArray);
+ }
+
+ @Override
+ public void generateDialog(LinearLayout layout) {
+ Context context = layout.getContext();
+ // Get if there is already value in SP
+ String previousValue = SP.getString(preferenceId, "none");
+ radioGroup = new RadioGroup(context);
+ radioGroup.clearCheck();
+ radioGroup.setOrientation(LinearLayout.VERTICAL);
+ radioGroup.setVisibility(View.VISIBLE);
+
+ for (int i = 0; i < labels().length; i++) {
+ RadioButton rdbtn = new RadioButton(context);
+ rdbtn.setId(View.generateViewId());
+ rdbtn.setText(labels()[i]);
+ if (previousValue.equals(values()[i]))
+ rdbtn.setChecked(true);
+ rdbtn.setTag(i);
+ radioGroup.addView(rdbtn);
+ }
+
+ radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
+ int i = (int) group.findViewById(checkedId).getTag();
+ save(values()[i]);
+ });
+ layout.addView(radioGroup);
+ super.generateDialog(layout);
+ }
+
+ public SWRadioButton preferenceId(int preferenceId) {
+ this.preferenceId = preferenceId;
+ return this;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWLabel.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWLabel.java
new file mode 100644
index 0000000000..f0f4ff7628
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWLabel.java
@@ -0,0 +1,11 @@
+package info.nightscout.androidaps.setupwizard.events;
+
+import info.nightscout.androidaps.events.Event;
+
+public class EventSWLabel extends Event {
+ public String label;
+
+ public EventSWLabel(String label) {
+ this.label = label;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.java
new file mode 100644
index 0000000000..181960ac40
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/events/EventSWUpdate.java
@@ -0,0 +1,14 @@
+package info.nightscout.androidaps.setupwizard.events;
+
+import info.nightscout.androidaps.events.Event;
+
+public class EventSWUpdate extends Event {
+ public boolean redraw = false;
+
+ public EventSWUpdate() {
+ }
+
+ public EventSWUpdate(boolean redraw) {
+ this.redraw = redraw;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java b/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java
deleted file mode 100644
index 80424a04f7..0000000000
--- a/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java
+++ /dev/null
@@ -1,322 +0,0 @@
-package info.nightscout.androidaps.tabs;/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import android.content.Context;
-import android.graphics.Typeface;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.HorizontalScrollView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import info.nightscout.androidaps.R;
-
-/**
- * To be used with ViewPager to provide a tab indicator component which give constant feedback as to
- * the user's scroll progress.
- *
- * To use the component, simply add it to your view hierarchy. Then in your
- * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call
- * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for.
- *
- * The colors can be customized in two ways. The first and simplest is to provide an array of colors
- * via {@link #setSelectedIndicatorColors(int...)}. The
- * alternative is via the {@link TabColorizer} interface which provides you complete control over
- * which color is used for any individual position.
- *