diff --git a/app/build.gradle b/app/build.gradle index 31de31b970..d656fa97d9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,8 +43,8 @@ android { applicationId "info.nightscout.androidaps" minSdkVersion 21 targetSdkVersion 23 - versionCode 1100 - version "1.33" + versionCode 1500 + version "1.5" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", generateGitBuild() } @@ -168,8 +168,8 @@ dependencies { compile 'com.google.android.gms:play-services-wearable:7.5.0' compile 'junit:junit:4.12' testCompile 'org.json:json:20140107' - testCompile 'org.mockito:mockito-core:2.+' - androidTestCompile 'org.mockito:mockito-core:2.+' + testCompile 'org.mockito:mockito-core:2.7.22' + androidTestCompile 'org.mockito:mockito-core:2.7.22' androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' compile(name: 'android-edittext-validator-v1.3.4-mod', ext: 'aar') @@ -177,11 +177,7 @@ dependencies { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' } - compile 'com.google.code.gson:gson:2.4' - compile 'com.google.guava:guava:18.0' + compile 'com.google.code.gson:gson:2.7' + compile 'com.google.guava:guava:20.0' - compile ('com.jakewharton:butterknife:8.5.1') { - exclude module: 'support-compat' - } - annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e01ed53f34..c4f9bcfe04 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,10 +41,10 @@ android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity" android:theme="@style/Theme.AppCompat.Translucent" /> - - - - + + + + @@ -116,11 +116,16 @@ android:name=".Services.DataService" android:exported="false" /> + Build.VERSION_CODES.LOLLIPOP_MR1) { askForPermission(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, @@ -69,23 +77,7 @@ public class MainActivity extends AppCompatActivity { if (Config.logFunctionCalls) log.debug("onCreate"); - // show version in toolbar - setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); registerBus(); - - try { - getSupportActionBar().setDisplayShowHomeEnabled(true); - if (BuildConfig.NSCLIENTOLNY) - getSupportActionBar().setIcon(R.mipmap.yellowowl); - else - getSupportActionBar().setIcon(R.mipmap.blueowl); - } catch (NullPointerException e) { - // no action - } - - setUpTabs(false); } @@ -119,79 +111,6 @@ public class MainActivity extends AppCompatActivity { mPager.setCurrentItem(pageAdapter.getCount() - 1, false); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_main, menu); - 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", new Runnable() { - @Override - public void run() { - Intent i = new Intent(getApplicationContext(), PreferencesActivity.class); - startActivity(i); - } - }, null); - break; - 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, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - MainApp.getDbHelper().resetDatabases(); - } - }) - .create() - .show(); - break; - case R.id.nav_export: - ImportExportPrefs.verifyStoragePermissions(this); - ImportExportPrefs.exportSharedPreferences(this); - break; - case R.id.nav_import: - ImportExportPrefs.verifyStoragePermissions(this); - ImportExportPrefs.importSharedPreferences(this); - break; - case R.id.nav_show_logcat: - LogDialog.showLogcat(this); - break; -// case R.id.nav_test_alarm: -// final int REQUEST_CODE_ASK_PERMISSIONS = 2355; -// int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.SYSTEM_ALERT_WINDOW); -// if (permission != PackageManager.PERMISSION_GRANTED) { -// // We don't have permission so prompt the user -// // On Android 6 give permission for alarming in Settings -> Apps -> Draw over other apps -// ActivityCompat.requestPermissions( -// this, -// new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW}, -// REQUEST_CODE_ASK_PERMISSIONS -// ); -// } -// Intent alertServiceIntent = new Intent(getApplicationContext(), AlertService.class); -// alertServiceIntent.putExtra("alertText", getString(R.string.nav_test_alert)); -// getApplicationContext().startService(alertServiceIntent); -// 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 super.onOptionsItemSelected(item); - } - private void registerBus() { try { MainApp.bus().unregister(this); @@ -243,7 +162,7 @@ public class MainActivity extends AppCompatActivity { if (!pm.isIgnoringBatteryOptimizations(packageName)) { log.debug("Requesting ignore battery optimization"); - OKDialog.show(this, getString(R.string.pleaseallowpermission), String.format(getString(R.string.needwhitelisting), getString(R.string.app_name)), new Runnable() { + OKDialog.show(getParent(), getString(R.string.pleaseallowpermission), String.format(getString(R.string.needwhitelisting), getString(R.string.app_name)), new Runnable() { @Override public void run() { @@ -325,4 +244,81 @@ public class MainActivity extends AppCompatActivity { } return super.dispatchTouchEvent(event); } + + @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); + startActivity(i); + } + }, null); + 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(); + } + }) + .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(getString(R.string.app_name) + " " + BuildConfig.VERSION); + if (Config.NSCLIENT) + builder.setIcon(R.mipmap.yellowowl); + else + builder.setIcon(R.mipmap.blueowl); + builder.setMessage("Build: " + BuildConfig.BUILDVERSION); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); + AlertDialog alertDialog = builder.create(); + alertDialog.show(); + 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; + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 6568e03a53..1e49b03d73 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -18,38 +18,47 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Actions.ActionsFragment; import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; -import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfileFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRFragment; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanFragment; -import info.nightscout.androidaps.plugins.LocalProfile.LocalProfileFragment; +import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment; +import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyFragment; +import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingFragment; +import info.nightscout.androidaps.plugins.InsulinFastactingProlonged.InsulinFastactingProlongedFragment; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorFragment; import info.nightscout.androidaps.plugins.Loop.LoopFragment; -import info.nightscout.androidaps.plugins.MDI.MDIFragment; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalFragment; -import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment; -import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAFragment; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAFragment; import info.nightscout.androidaps.plugins.Overview.OverviewFragment; -import info.nightscout.androidaps.plugins.SafetyFragment.SafetyFragment; -import info.nightscout.androidaps.plugins.SimpleProfile.SimpleProfileFragment; +import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment; +import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment; +import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanFragment; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Fragment; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; +import info.nightscout.androidaps.plugins.PumpMDI.MDIFragment; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpFragment; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment; import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpFragment; import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment; -import info.nightscout.androidaps.plugins.TempBasals.TempBasalsFragment; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangeFragment; import info.nightscout.androidaps.plugins.Treatments.TreatmentsFragment; -import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpFragment; import info.nightscout.androidaps.plugins.Wear.WearFragment; -import info.nightscout.androidaps.plugins.persistentnotification.PersistentNotificationPlugin; +import info.nightscout.androidaps.plugins.XDripStatusline.StatuslineFragment; import info.nightscout.androidaps.receivers.KeepAliveReceiver; +import info.nightscout.utils.NSUpload; import io.fabric.sdk.android.Fabric; @@ -85,31 +94,38 @@ public class MainApp extends Application { pluginsList = new ArrayList<>(); // Register all tabs in app here pluginsList.add(OverviewFragment.getPlugin()); + pluginsList.add(IobCobCalculatorFragment.getPlugin()); if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); + pluginsList.add(InsulinFastactingFragment.getPlugin()); + pluginsList.add(InsulinFastactingProlongedFragment.getPlugin()); if (Config.DANAR) pluginsList.add(DanaRFragment.getPlugin()); - if (Config.DANARKOREAN) pluginsList.add(DanaRKoreanFragment.getPlugin()); + if (Config.DANAR) pluginsList.add(DanaRKoreanFragment.getPlugin()); + if (Config.DANARv2) pluginsList.add(DanaRv2Fragment.getPlugin()); pluginsList.add(CareportalFragment.getPlugin()); if (Config.MDI) pluginsList.add(MDIFragment.getPlugin()); - if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpFragment.getPlugin()); + if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getInstance()); if (Config.LOOPENABLED) pluginsList.add(LoopFragment.getPlugin()); if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin()); if (Config.OPENAPSENABLED) pluginsList.add(OpenAPSAMAFragment.getPlugin()); pluginsList.add(NSProfileFragment.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(SimpleProfileFragment.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(LocalProfileFragment.getPlugin()); - if (Config.OTHERPROFILES) pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); - if (Config.APS) pluginsList.add(TempTargetRangeFragment.getPlugin()); + if (Config.OTHERPROFILES) + pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); pluginsList.add(TreatmentsFragment.getPlugin()); - if (Config.TEMPBASALS) pluginsList.add(TempBasalsFragment.getPlugin()); if (Config.SAFETY) pluginsList.add(SafetyFragment.getPlugin()); if (Config.APS) pluginsList.add(ObjectivesFragment.getPlugin()); - pluginsList.add(SourceXdripFragment.getPlugin()); + if (!Config.NSCLIENT) + pluginsList.add(SourceXdripFragment.getPlugin()); pluginsList.add(SourceNSClientFragment.getPlugin()); - pluginsList.add(SourceMM640gFragment.getPlugin()); - pluginsList.add(SourceGlimpFragment.getPlugin()); + if (!Config.NSCLIENT) + pluginsList.add(SourceMM640gFragment.getPlugin()); + if (!Config.NSCLIENT) + pluginsList.add(SourceGlimpFragment.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorFragment.getPlugin()); if (Config.WEAR) pluginsList.add(WearFragment.getPlugin(this)); + pluginsList.add(StatuslineFragment.getPlugin(this)); pluginsList.add(new PersistentNotificationPlugin(this)); pluginsList.add(NSClientInternalFragment.getPlugin()); @@ -117,7 +133,7 @@ public class MainApp extends Application { MainApp.getConfigBuilder().initialize(); } - MainApp.getConfigBuilder().uploadAppStart(); + NSUpload.uploadAppStart(); startKeepAliveService(); @@ -140,18 +156,18 @@ public class MainApp extends Application { if (keepAliveReceiver == null) { keepAliveReceiver = new KeepAliveReceiver(); if (Config.DANAR) { - startService(new Intent(this, info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService.class)); - startService(new Intent(this, info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService.class)); + startService(new Intent(this, DanaRExecutionService.class)); + startService(new Intent(this, DanaRKoreanExecutionService.class)); + startService(new Intent(this, DanaRv2ExecutionService.class)); } keepAliveReceiver.setAlarm(this); } } - - public void stopKeepAliveService(){ - if(keepAliveReceiver!=null) - keepAliveReceiver.cancelAlarm(this); + public void stopKeepAliveService() { + if (keepAliveReceiver != null) + keepAliveReceiver.cancelAlarm(this); } public static Bus bus() { @@ -198,6 +214,36 @@ public class MainApp extends Application { return newList; } + @Nullable + public static InsulinInterface getInsulinIterfaceById(int id) { + ArrayList newList = new ArrayList<>(); + + if (pluginsList != null) { + for (PluginBase p : pluginsList) { + if (p.getType() == PluginBase.INSULIN && ((InsulinInterface) p).getId() == id) + return (InsulinInterface) p; + } + } else { + log.error("InsulinInterface not found"); + } + return null; + } + + public static ArrayList getSpecificPluginsVisibleInList(int type) { + ArrayList newList = new ArrayList<>(); + + if (pluginsList != null) { + for (PluginBase p : pluginsList) { + if (p.getType() == type) + if (p.showInList(type)) + newList.add(p); + } + } else { + log.error("pluginsList=null"); + } + return newList; + } + public static ArrayList getSpecificPluginsListByInterface(Class interfaceClass) { ArrayList newList = new ArrayList<>(); @@ -212,6 +258,21 @@ public class MainApp extends Application { return newList; } + public static ArrayList getSpecificPluginsVisibleInListByInterface(Class interfaceClass, int type) { + ArrayList newList = new ArrayList<>(); + + if (pluginsList != null) { + for (PluginBase p : pluginsList) { + if (p.getClass() != ConfigBuilderPlugin.class && interfaceClass.isAssignableFrom(p.getClass())) + if (p.showInList(type)) + newList.add(p); + } + } else { + log.error("pluginsList=null"); + } + return newList; + } + @Nullable public static PluginBase getSpecificPlugin(Class pluginClass) { if (pluginsList != null) { diff --git a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java index 29a4913bc3..d3d52298aa 100644 --- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java @@ -14,13 +14,15 @@ import android.preference.PreferenceManager; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.DanaR.BluetoothDevicePreference; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.BluetoothDevicePreference; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; -import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.Wear.WearPlugin; +import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; import info.nightscout.utils.LocaleHelper; public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -109,10 +111,14 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre if (Config.DANAR) { DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); + DanaRv2Plugin danaRv2Plugin = (DanaRv2Plugin) MainApp.getSpecificPlugin(DanaRv2Plugin.class); if (danaRPlugin.isEnabled(PluginBase.PUMP) || danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) { addPreferencesFromResource(R.xml.pref_danar); } - if (danaRPlugin.isEnabled(PluginBase.PROFILE) || danaRKoreanPlugin.isEnabled(PluginBase.PROFILE)) { + if (danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PUMP)) { + addPreferencesFromResource(R.xml.pref_danarv2); + } + if (danaRPlugin.isEnabled(PluginBase.PROFILE) || danaRKoreanPlugin.isEnabled(PluginBase.PROFILE) || danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PROFILE)) { addPreferencesFromResource(R.xml.pref_danarprofile); } } @@ -138,6 +144,11 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre } } + StatuslinePlugin statuslinePlugin = (StatuslinePlugin) MainApp.getSpecificPlugin(StatuslinePlugin.class); + if (statuslinePlugin != null && statuslinePlugin.isEnabled(PluginBase.GENERAL)) { + addPreferencesFromResource(R.xml.pref_xdripstatus); + } + initSummary(getPreferenceScreen()); } 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 f45e59f4c1..def268bd35 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -2,56 +2,42 @@ package info.nightscout.androidaps.Services; import android.app.IntentService; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Bundle; -import android.preference.PreferenceManager; import android.provider.Telephony; -import com.j256.ormlite.dao.Dao; -import com.j256.ormlite.stmt.PreparedQuery; -import com.j256.ormlite.stmt.QueryBuilder; -import com.j256.ormlite.stmt.Where; - import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.util.Date; -import java.util.List; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.DanaRHistoryRecord; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventNewBasalProfile; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync; -import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin; -import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSMbg; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SourceGlimp.SourceGlimpPlugin; import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gPlugin; import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientPlugin; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; import info.nightscout.androidaps.receivers.DataReceiver; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; +import info.nightscout.utils.SP; public class DataService extends IntentService { @@ -94,10 +80,9 @@ public class DataService extends IntentService { glimpEnabled = true; } - boolean isNSProfile = ConfigBuilderPlugin.getActiveProfile().getClass().equals(NSProfilePlugin.class); + boolean isNSProfile = ConfigBuilderPlugin.getActiveProfileInterface().getClass().equals(NSProfilePlugin.class); - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - boolean nsUploadOnly = SP.getBoolean("ns_upload_only", false); + boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); if (intent != null) { final String action = intent.getAction(); @@ -121,7 +106,7 @@ public class DataService extends IntentService { // Objectives 0 ObjectivesPlugin.bgIsAvailableInNS = true; ObjectivesPlugin.saveProgress(); - } else if (isNSProfile && Intents.ACTION_NEW_PROFILE.equals(action)) { + } else if (isNSProfile && Intents.ACTION_NEW_PROFILE.equals(action) || Intents.ACTION_NEW_DEVICESTATUS.equals(action)) { // always handle Profile if NSProfile is enabled without looking at nsUploadOnly handleNewDataFromNSClient(intent); } else if (!nsUploadOnly && @@ -178,25 +163,10 @@ public class DataService extends IntentService { bgReading.value = bundle.getDouble(Intents.EXTRA_BG_ESTIMATE); bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME); - bgReading.battery_level = bundle.getInt(Intents.EXTRA_SENSOR_BATTERY); - bgReading.timeIndex = bundle.getLong(Intents.EXTRA_TIMESTAMP); + bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP); bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW); - if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) { - if (Config.logIncommingBG) - log.debug("Ignoring old XDRIPREC BG " + bgReading.toString()); - return; - } - - if (Config.logIncommingBG) - log.debug("XDRIPREC BG " + bgReading.toString()); - - try { - MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading); - } catch (SQLException e) { - e.printStackTrace(); - } - MainApp.bus().post(new EventNewBG()); + MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP"); } private void handleNewDataFromGlimp(Intent intent) { @@ -207,20 +177,10 @@ public class DataService extends IntentService { bgReading.value = bundle.getDouble("mySGV"); bgReading.direction = bundle.getString("myTrend"); - bgReading.battery_level = bundle.getInt("myBatLvl"); - bgReading.timeIndex = bundle.getLong("myTimestamp"); + bgReading.date = bundle.getLong("myTimestamp"); bgReading.raw = 0; - if (Config.logIncommingBG) - log.debug(bundle.toString()); - log.debug("GLIMP BG " + bgReading.toString()); - - try { - MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading); - } catch (SQLException e) { - e.printStackTrace(); - } - MainApp.bus().post(new EventNewBG()); + MainApp.getDbHelper().createIfNotExists(bgReading, "GLIMP"); } private void handleNewDataFromMM640g(Intent intent) { @@ -245,23 +205,10 @@ public class DataService extends IntentService { bgReading.value = json_object.getDouble("sgv"); bgReading.direction = json_object.getString("direction"); - bgReading.timeIndex = json_object.getLong("date"); + bgReading.date = json_object.getLong("date"); bgReading.raw = json_object.getDouble("sgv"); - if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) { - if (Config.logIncommingBG) - log.debug("Ignoring old MM640g BG " + bgReading.toString()); - return; - } - - if (Config.logIncommingBG) - log.debug("MM640g BG " + bgReading.toString()); - - try { - MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading); - } catch (SQLException e) { - e.printStackTrace(); - } + MainApp.getDbHelper().createIfNotExists(bgReading, "MM640g"); break; default: log.debug("Unknown entries type: " + type); @@ -272,7 +219,6 @@ public class DataService extends IntentService { } } } - MainApp.bus().post(new EventNewBG()); } private void handleNewDataFromNSClient(Intent intent) { @@ -353,25 +299,12 @@ public class DataService extends IntentService { try { String activeProfile = bundles.getString("activeprofile"); String profile = bundles.getString("profile"); - NSProfile nsProfile = new NSProfile(new JSONObject(profile), activeProfile); - MainApp.bus().post(new EventNewBasalProfile(nsProfile)); + ProfileStore profileStore = new ProfileStore(new JSONObject(profile)); + NSProfilePlugin.storeNewProfile(profileStore); + MainApp.bus().post(new EventNewBasalProfile()); - PumpInterface pump = MainApp.getConfigBuilder(); - if (pump != null) { - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - if (SP.getBoolean("syncprofiletopump", false)) { - if (pump.setNewBasalProfile(nsProfile) == PumpInterface.SUCCESS) { - SmsCommunicatorPlugin smsCommunicatorPlugin = (SmsCommunicatorPlugin) MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); - if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { - smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); - } - } - } - } else { - log.error("No active pump selected"); - } if (Config.logIncommingData) - log.debug("Received profile: " + activeProfile + " " + profile); + log.debug("Received profileStore: " + activeProfile + " " + profile); } catch (JSONException e) { e.printStackTrace(); } @@ -380,7 +313,7 @@ public class DataService extends IntentService { try { if (bundles.containsKey("treatment")) { String trstring = bundles.getString("treatment"); - handleAddedTreatment(trstring); + handleAddChangeDataFromNS(trstring); } if (bundles.containsKey("treatments")) { String trstring = bundles.getString("treatments"); @@ -388,7 +321,7 @@ public class DataService extends IntentService { for (int i = 0; i < jsonArray.length(); i++) { JSONObject trJson = jsonArray.getJSONObject(i); String trstr = trJson.toString(); - handleAddedTreatment(trstr); + handleAddChangeDataFromNS(trstr); } } } catch (Exception e) { @@ -401,7 +334,7 @@ public class DataService extends IntentService { try { if (bundles.containsKey("treatment")) { String trstring = bundles.getString("treatment"); - handleChangedTreatment(trstring); + handleAddChangeDataFromNS(trstring); } if (bundles.containsKey("treatments")) { String trstring = bundles.getString("treatments"); @@ -409,7 +342,7 @@ public class DataService extends IntentService { for (int i = 0; i < jsonArray.length(); i++) { JSONObject trJson = jsonArray.getJSONObject(i); String trstr = trJson.toString(); - handleChangedTreatment(trstr); + handleAddChangeDataFromNS(trstr); } } } catch (Exception e) { @@ -423,8 +356,7 @@ public class DataService extends IntentService { String trstring = bundles.getString("treatment"); JSONObject trJson = new JSONObject(trstring); String _id = trJson.getString("_id"); - MainApp.getDbHelper().delete(_id); - handleRemoveTempTargetRecord(trJson); + handleRemovedRecordFromNS(_id); } if (bundles.containsKey("treatments")) { @@ -433,8 +365,7 @@ public class DataService extends IntentService { for (int i = 0; i < jsonArray.length(); i++) { JSONObject trJson = jsonArray.getJSONObject(i); String _id = trJson.getString("_id"); - MainApp.getDbHelper().delete(_id); - handleRemoveTempTargetRecord(trJson); + handleRemovedRecordFromNS(_id); } } } catch (Exception e) { @@ -449,14 +380,7 @@ public class DataService extends IntentService { JSONObject sgvJson = new JSONObject(sgvstring); NSSgv nsSgv = new NSSgv(sgvJson); BgReading bgReading = new BgReading(nsSgv); - if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000l) { - if (Config.logIncommingData) - log.debug("Ignoring old BG: " + bgReading.toString()); - return; - } - MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading); - if (Config.logIncommingData) - log.debug("ADD: Stored new BG: " + bgReading.toString()); + MainApp.getDbHelper().createIfNotExists(bgReading, "NS"); } if (bundles.containsKey("sgvs")) { @@ -466,244 +390,129 @@ public class DataService extends IntentService { JSONObject sgvJson = jsonArray.getJSONObject(i); NSSgv nsSgv = new NSSgv(sgvJson); BgReading bgReading = new BgReading(nsSgv); - if (bgReading.timeIndex < new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000l) { - if (Config.logIncommingData) - log.debug("Ignoring old BG: " + bgReading.toString()); - } else { - MainApp.getDbHelper().getDaoBgReadings().createIfNotExists(bgReading); - if (Config.logIncommingData) - log.debug("ADD: Stored new BG: " + bgReading.toString()); - } + MainApp.getDbHelper().createIfNotExists(bgReading, "NS"); } } } catch (Exception e) { e.printStackTrace(); } - MainApp.bus().post(new EventNewBG()); } if (intent.getAction().equals(Intents.ACTION_NEW_MBG)) { - log.error("Not implemented yet"); // TODO implemeng MBGS - } - } + try { + 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()); + } - private void handleAddedTreatment(String trstring) throws JSONException, SQLException { - JSONObject trJson = new JSONObject(trstring); - handleDanaRHistoryRecords(trJson); // update record _id in history - handleAddChangeTempTargetRecord(trJson); - if (!trJson.has("insulin") && !trJson.has("carbs")) { - if (Config.logIncommingData) - log.debug("ADD: Uninterested treatment: " + trstring); - return; - } - - Treatment stored = null; - String _id = trJson.getString("_id"); - - if (trJson.has("timeIndex")) { - if (Config.logIncommingData) - log.debug("ADD: timeIndex found: " + trstring); - stored = MainApp.getDbHelper().findTreatmentByTimeIndex(trJson.getLong("timeIndex")); - } else { - stored = MainApp.getDbHelper().findTreatmentById(_id); - } - - if (stored != null) { - if (Config.logIncommingData) - log.debug("ADD: Existing treatment: " + trstring); - if (trJson.has("timeIndex")) { - stored._id = _id; - int updated = MainApp.getDbHelper().update(stored); - if (Config.logIncommingData) - log.debug("Records updated: " + updated); - } - } else { - if (Config.logIncommingData) - log.debug("ADD: New treatment: " + trstring); - Treatment treatment = new Treatment(); - treatment._id = _id; - treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0; - treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d; - treatment.created_at = new Date(trJson.getLong("mills")); - if (trJson.has("eventType")) { - treatment.mealBolus = true; - if (trJson.get("eventType").equals("Correction Bolus")) - treatment.mealBolus = false; - double carbs = treatment.carbs; - if (trJson.has("boluscalc")) { - JSONObject boluscalc = trJson.getJSONObject("boluscalc"); - if (boluscalc.has("carbs")) { - carbs = Math.max(boluscalc.getDouble("carbs"), carbs); + if (bundles.containsKey("mbgs")) { + String sgvstring = bundles.getString("mbgs"); + 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()); } } - if (carbs <= 0) - treatment.mealBolus = false; + } catch (Exception e) { + e.printStackTrace(); } - treatment.setTimeIndex(treatment.getTimeIndex()); - MainApp.getDbHelper().createOrUpdate(treatment); - if (Config.logIncommingData) - log.debug("ADD: Stored treatment: " + treatment.log()); } } - private void handleChangedTreatment(String trstring) throws JSONException, SQLException { + private void handleRemovedRecordFromNS(String _id) { + MainApp.getDbHelper().deleteTreatmentById(_id); + MainApp.getDbHelper().deleteTempTargetById(_id); + MainApp.getDbHelper().deleteTempBasalById(_id); + MainApp.getDbHelper().deleteExtendedBolusById(_id); + MainApp.getDbHelper().deleteCareportalEventById(_id); + MainApp.getDbHelper().deleteProfileSwitchById(_id); + } + + private void handleAddChangeDataFromNS(String trstring) throws JSONException { JSONObject trJson = new JSONObject(trstring); handleDanaRHistoryRecords(trJson); // update record _id in history handleAddChangeTempTargetRecord(trJson); - if (!trJson.has("insulin") && !trJson.has("carbs")) { - if (Config.logIncommingData) - log.debug("CHANGE: Uninterested treatment: " + trstring); + handleAddChangeTempBasalRecord(trJson); + handleAddChangeExtendedBolusRecord(trJson); + handleAddChangeCareportalEventRecord(trJson); + handleAddChangeTreatmentRecord(trJson); + handleAddChangeProfileSwitchRecord(trJson); + } + + public void handleDanaRHistoryRecords(JSONObject trJson) { + if (trJson.has(DanaRNSHistorySync.DANARSIGNATURE)) { + MainApp.getDbHelper().updateDanaRHistoryRecordId(trJson); + } + } + + public void handleAddChangeTreatmentRecord(JSONObject trJson) throws JSONException { + if (trJson.has("insulin") || trJson.has("carbs")) { + MainApp.getDbHelper().createTreatmentFromJsonIfNotExists(trJson); return; } - String _id = trJson.getString("_id"); - - Treatment stored; - - if (trJson.has("timeIndex")) { - if (Config.logIncommingData) - log.debug("ADD: timeIndex found: " + trstring); - stored = MainApp.getDbHelper().findTreatmentByTimeIndex(trJson.getLong("timeIndex")); - } else { - stored = MainApp.getDbHelper().findTreatmentById(_id); - } - - if (stored != null) { - if (Config.logIncommingData) - log.debug("CHANGE: Removing old: " + trstring); - MainApp.getDbHelper().delete(_id); - } - - if (Config.logIncommingData) - log.debug("CHANGE: Adding new treatment: " + trstring); - Treatment treatment = new Treatment(); - treatment._id = _id; - treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0; - treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d; - //treatment.created_at = DateUtil.fromISODateString(trJson.getString("created_at")); - treatment.created_at = new Date(trJson.getLong("mills")); - if (trJson.has("eventType")) { - treatment.mealBolus = true; - if (trJson.get("eventType").equals("Correction Bolus")) - treatment.mealBolus = false; - double carbs = treatment.carbs; - if (trJson.has("boluscalc")) { - JSONObject boluscalc = trJson.getJSONObject("boluscalc"); - if (boluscalc.has("carbs")) { - carbs = Math.max(boluscalc.getDouble("carbs"), carbs); - } - } - if (carbs <= 0) - treatment.mealBolus = false; - } - treatment.setTimeIndex(treatment.getTimeIndex()); - Dao.CreateOrUpdateStatus status = MainApp.getDbHelper().createOrUpdate(treatment); - if (Config.logIncommingData) - log.debug("Records updated: " + status.getNumLinesChanged()); - if (Config.logIncommingData) - log.debug("CHANGE: Stored treatment: " + treatment.log()); } - public void handleDanaRHistoryRecords(JSONObject trJson) throws JSONException, SQLException { - if (trJson.has(DanaRNSHistorySync.DANARSIGNATURE)) { - Dao daoHistoryRecords = MainApp.getDbHelper().getDaoDanaRHistory(); - QueryBuilder queryBuilder = daoHistoryRecords.queryBuilder(); - Where where = queryBuilder.where(); - where.ge("bytes", trJson.get(DanaRNSHistorySync.DANARSIGNATURE)); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = daoHistoryRecords.query(preparedQuery); - if (list.size() == 0) { - // Record does not exists. Ignore - } else if (list.size() == 1) { - DanaRHistoryRecord record = list.get(0); - if (record.get_id() == null || record.get_id() != trJson.getString("_id")) { - if (Config.logIncommingData) - log.debug("Updating _id in DanaR history database: " + trJson.getString("_id")); - record.set_id(trJson.getString("_id")); - daoHistoryRecords.update(record); - } else { - // already set - } + public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException { + if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.TEMPORARYTARGET)) { + MainApp.getDbHelper().createTemptargetFromJsonIfNotExists(trJson); + } + } + + public void handleAddChangeTempBasalRecord(JSONObject trJson) throws JSONException { + if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.TEMPBASAL)) { + MainApp.getDbHelper().createTempBasalFromJsonIfNotExists(trJson); + } + } + + public void handleAddChangeExtendedBolusRecord(JSONObject trJson) throws JSONException { + if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.COMBOBOLUS)) { + MainApp.getDbHelper().createExtendedBolusFromJsonIfNotExists(trJson); + } + } + + public void handleAddChangeCareportalEventRecord(JSONObject trJson) throws JSONException { + if (trJson.has("insulin") && trJson.getDouble("insulin") > 0) + return; + if (trJson.has("carbs") && trJson.getDouble("carbs") > 0) + return; + if (trJson.has("eventType") && ( + trJson.getString("eventType").equals(CareportalEvent.SITECHANGE) || + trJson.getString("eventType").equals(CareportalEvent.INSULINCHANGE) || + trJson.getString("eventType").equals(CareportalEvent.SENSORCHANGE) || + trJson.getString("eventType").equals(CareportalEvent.BGCHECK) || + trJson.getString("eventType").equals(CareportalEvent.NOTE) || + trJson.getString("eventType").equals(CareportalEvent.NONE) || + trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT) || + trJson.getString("eventType").equals(CareportalEvent.QUESTION) || + trJson.getString("eventType").equals(CareportalEvent.EXERCISE) || + trJson.getString("eventType").equals(CareportalEvent.OPENAPSOFFLINE) || + trJson.getString("eventType").equals(CareportalEvent.PUMPBATTERYCHANGE) + )) { + MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(trJson); + } + + if (trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) { + long date = trJson.getLong("mills"); + long now = new Date().getTime(); + if (date > now - 15 * 60 * 1000L && trJson.has("notes")) { + Notification announcement = new Notification(Notification.ANNOUNCEMENT, trJson.getString("notes"), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(announcement)); } } } - /* - { - "_id": "58795998aa86647ba4d68ce7", - "enteredBy": "", - "eventType": "Temporary Target", - "reason": "Eating Soon", - "targetTop": 80, - "targetBottom": 80, - "duration": 120, - "created_at": "2017-01-13T22:50:00.782Z", - "carbs": null, - "insulin": null -} - */ - - public void handleAddChangeTempTargetRecord(JSONObject trJson) throws JSONException, SQLException { - if (trJson.has("eventType") && trJson.getString("eventType").equals("Temporary Target")) { - if (Config.logIncommingData) - log.debug("Processing TempTarget record: " + trJson.toString()); - Dao daoTempTargets = MainApp.getDbHelper().getDaoTempTargets(); - QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", trJson.getString("_id")).or().eq("timeIndex", trJson.getLong("mills")); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = daoTempTargets.query(preparedQuery); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile == null) return; // no profile data, better ignore than do something wrong - String units = profile.getUnits(); - if (list.size() == 0) { - // Record does not exists. add - TempTarget newRecord = new TempTarget(); - newRecord.timeStart = new Date(trJson.getLong("mills")); - newRecord.duration = trJson.getInt("duration"); - newRecord.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units); - newRecord.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units); - newRecord.reason = trJson.getString("reason"); - newRecord._id = trJson.getString("_id"); - newRecord.setTimeIndex(newRecord.getTimeIndex()); - daoTempTargets.createIfNotExists(newRecord); - if (Config.logIncommingData) - log.debug("Adding TempTarget record to database: " + newRecord.log()); - MainApp.bus().post(new EventTempTargetRangeChange()); - } else if (list.size() == 1) { - if (Config.logIncommingData) - log.debug("Updating TempTarget record in database: " + trJson.getString("_id")); - TempTarget record = list.get(0); - record.timeStart = new Date(trJson.getLong("mills")); - record.duration = trJson.getInt("duration"); - record.low = NSProfile.toMgdl(trJson.getDouble("targetBottom"), units); - record.high = NSProfile.toMgdl(trJson.getDouble("targetTop"), units); - record.reason = trJson.getString("reason"); - record._id = trJson.getString("_id"); - daoTempTargets.update(record); - MainApp.bus().post(new EventTempTargetRangeChange()); - } - } - } - - public void handleRemoveTempTargetRecord(JSONObject trJson) throws JSONException, SQLException { - if (trJson.has("_id")) { - Dao daoTempTargets = MainApp.getDbHelper().getDaoTempTargets(); - QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", trJson.getString("_id")); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = daoTempTargets.query(preparedQuery); - - if (list.size() == 1) { - TempTarget record = list.get(0); - if (Config.logIncommingData) - log.debug("Removing TempTarget record from database: " + record.log()); - daoTempTargets.delete(record); - MainApp.bus().post(new EventTempTargetRangeChange()); - } else { - if (Config.logIncommingData) - log.debug("TempTarget not found database: " + trJson.toString()); - } + public void handleAddChangeProfileSwitchRecord(JSONObject trJson) throws JSONException { + if (trJson.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.PROFILESWITCH)) { + MainApp.getDbHelper().createProfileSwitchFromJsonIfNotExists(trJson); } } diff --git a/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java new file mode 100644 index 0000000000..f560ad0282 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/DetailedBolusInfo.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.data; + +import android.content.Context; + +import org.json.JSONObject; + +import java.util.Date; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.interfaces.InsulinInterface; + +/** + * Created by mike on 29.05.2017. + */ + +public class DetailedBolusInfo { + public long date = new Date().getTime(); + public InsulinInterface insulinInterface = MainApp.getConfigBuilder().getActiveInsulin(); + public String eventType = CareportalEvent.MEALBOLUS; + public double insulin = 0; + public double carbs = 0; + public int source = Source.NONE; + public double glucose = 0; // Bg value in current units + public String glucoseType = ""; // NS values: Manual, Finger, Sensor + public int carbTime = 0; // time shift of carbs in minutes + public JSONObject boluscalc = null; // additional bolus wizard info + public Context context = null; // context for progress dialog + public boolean addToTreatments = true; + public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) +} diff --git a/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java b/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java index ad9b0acecf..68d4936460 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/data/GlucoseStatus.java @@ -66,19 +66,17 @@ public class GlucoseStatus { @Nullable public static GlucoseStatus getGlucoseStatusData() { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainApp.instance()); - // load 45min long fromtime = (long) (new Date().getTime() - 60 * 1000L * 45); List data = MainApp.getDbHelper().getBgreadingsDataFromTime(fromtime, false); int sizeRecords = data.size(); - if (sizeRecords < 1 || data.get(0).timeIndex < new Date().getTime() - 7 * 60 * 1000L) { + if (sizeRecords < 1 || data.get(0).date < new Date().getTime() - 7 * 60 * 1000L) { return null; } BgReading now = data.get(0); - long now_date = now.timeIndex; + long now_date = now.date; double change; if (sizeRecords < 2) { @@ -98,7 +96,7 @@ public class GlucoseStatus { for (int i = 1; i < data.size(); i++) { if (data.get(i).value > 38) { BgReading then = data.get(i); - long then_date = then.timeIndex; + long then_date = then.date; double avgdelta = 0; long minutesago; @@ -131,7 +129,7 @@ public class GlucoseStatus { status.short_avgdelta = average(short_deltas); - if (prefs.getBoolean("always_use_shortavg", false) || last_deltas.isEmpty()) { + if (last_deltas.isEmpty()) { status.delta = status.short_avgdelta; } else { status.delta = average(last_deltas); @@ -143,48 +141,6 @@ public class GlucoseStatus { return status.round(); } - /* - * Return last BgReading from database or null if db is empty - */ - @Nullable - public static BgReading lastBg() { - List bgList = null; - - try { - Dao daoBgReadings = MainApp.getDbHelper().getDaoBgReadings(); - QueryBuilder queryBuilder = daoBgReadings.queryBuilder(); - queryBuilder.orderBy("timeIndex", false); - queryBuilder.limit(1L); - queryBuilder.where().gt("value", 38); - PreparedQuery preparedQuery = queryBuilder.prepare(); - bgList = daoBgReadings.query(preparedQuery); - - } catch (SQLException e) { - log.debug(e.getMessage(), e); - } - if (bgList != null && bgList.size() > 0) - return bgList.get(0); - else - return null; - } - - /* - * Return bg reading if not old ( <9 min ) - * or null if older - */ - @Nullable - public static BgReading actualBg() { - BgReading lastBg = lastBg(); - - if (lastBg == null) - return null; - - if (lastBg.timeIndex > new Date().getTime() - 9 * 60 * 1000) - return lastBg; - - return null; - } - public static double average(ArrayList array) { double sum = 0d; diff --git a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java index ce0a94ef5a..5c89a7bec7 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java +++ b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java @@ -1,13 +1,10 @@ package info.nightscout.androidaps.data; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.Date; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DateUtil; import info.nightscout.utils.Round; @@ -20,7 +17,9 @@ public class IobTotal { public Double hightempinsulin; public Double netInsulin = 0d; // for calculations from temp basals only - public Double netRatio = 0d; // for calculations from temp basals only + public Double netRatio = 0d; // net ratio at start of temp basal + + public Double extendedBolusInsulin = 0d; // total insulin for extended bolus long time; @@ -42,7 +41,7 @@ public class IobTotal { netbasalinsulin += other.netbasalinsulin; hightempinsulin += other.hightempinsulin; netInsulin += other.netInsulin; - netRatio += other.netRatio; + extendedBolusInsulin += other.extendedBolusInsulin; return this; } @@ -94,43 +93,4 @@ public class IobTotal { return json; } - public static IobTotal calulateFromTreatmentsAndTemps() { - ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB(); - IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round(); - ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB(); - IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round(); - IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); - return iobTotal; - } - - public static IobTotal calulateFromTreatmentsAndTemps(long time) { - IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round(); - IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round(); - IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); - return iobTotal; - } - - public static IobTotal[] calculateIobArrayInDia() { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - // predict IOB out to DIA plus 30m - long time = new Date().getTime(); - int len = (int) ((profile.getDia() *60 + 30) / 5); - IobTotal[] array = new IobTotal[len]; - int pos = 0; - for (int i = 0; i < len; i++){ - long t = time + i * 5 * 60000; - IobTotal iob = calulateFromTreatmentsAndTemps(t); - array[pos] = iob; - pos++; - } - return array; - } - - public static JSONArray convertToJSONArray(IobTotal[] iobArray) { - JSONArray array = new JSONArray(); - for (int i = 0; i < iobArray.length; i ++) { - array.put(iobArray[i].determineBasalJson()); - } - return array; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/data/MealData.java b/app/src/main/java/info/nightscout/androidaps/data/MealData.java index 18919c3c8a..292d2272d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/MealData.java +++ b/app/src/main/java/info/nightscout/androidaps/data/MealData.java @@ -1,17 +1,5 @@ package info.nightscout.androidaps.data; -import java.util.Date; -import java.util.List; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.OpenAPSAMA.Autosens; -import info.nightscout.androidaps.plugins.OpenAPSAMA.AutosensResult; -import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; - /** * Created by mike on 04.01.2017. */ @@ -19,30 +7,4 @@ public class MealData { public double boluses = 0d; public double carbs = 0d; public double mealCOB = 0.0d; - - - public void addTreatment(Treatment treatment) { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile == null) return; - - List bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * profile.getDia() * 2), false); - - long now = new Date().getTime(); - long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue(); - long t = treatment.created_at.getTime(); - if (t > dia_ago && t <= now) { - if (treatment.carbs >= 1) { - carbs += treatment.carbs; - if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) { - AutosensResult result = Autosens.detectSensitivityandCarbAbsorption(bgReadings, t); - double myCarbsAbsorbed = result.carbsAbsorbed; - double myMealCOB = Math.max(0, carbs - myCarbsAbsorbed); - mealCOB = Math.max(mealCOB, myMealCOB); - } - } - if (treatment.insulin > 0 && treatment.mealBolus) { - boluses += treatment.insulin; - } - } - } } diff --git a/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java new file mode 100644 index 0000000000..cc03936766 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java @@ -0,0 +1,99 @@ +package info.nightscout.androidaps.data; + +import android.support.annotation.Nullable; +import android.support.v4.util.LongSparseArray; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.interfaces.Interval; + +/** + * Created by mike on 09.05.2017. + */ + +// Zero duration means end of interval + +public class OverlappingIntervals { + + private LongSparseArray rawData = new LongSparseArray<>(); // oldest at index 0 + + public OverlappingIntervals reset() { + rawData = new LongSparseArray<>(); + return this; + } + + public void add(T newInterval) { + rawData.put(newInterval.start(), newInterval); + merge(); + } + + public void add(List list) { + for (T interval : list) { + rawData.put(interval.start(), interval); + } + merge(); + } + + private void merge() { + for (int index = 0; index < rawData.size() - 1; index++) { + Interval i = rawData.valueAt(index); + long startOfNewer = rawData.valueAt(index + 1).start(); + if (i.originalEnd() > startOfNewer) { + i.cutEndTo(startOfNewer); + } + } + } + + @Nullable + public Interval getValueByInterval(long time) { + int index = binarySearch(time); + if (index >= 0) return rawData.valueAt(index); + return null; + } + + public List getList() { + List list = new ArrayList<>(); + for (int i = 0; i < rawData.size(); i++) + list.add(rawData.valueAt(i)); + return list; + } + + public List getReversedList() { + List list = new ArrayList<>(); + for (int i = rawData.size() -1; i>=0; i--) + list.add(rawData.valueAt(i)); + return list; + } + + private int binarySearch(long value) { + int lo = 0; + int hi = rawData.size() - 1; + + while (lo <= hi) { + final int mid = (lo + hi) >>> 1; + final Interval midVal = rawData.valueAt(mid); + + if (midVal.before(value)) { + lo = mid + 1; + } else if (midVal.after(value)) { + hi = mid - 1; + } else if (midVal.match(value)) { + return mid; // value found + } + } + return ~lo; // value not present + } + + public int size() { + return rawData.size(); + } + + public T get(int index) { + return rawData.valueAt(index); + } + + public T getReversed(int index) { + return rawData.valueAt(size() - 1 - index); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java new file mode 100644 index 0000000000..dd68eff35f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -0,0 +1,347 @@ +package info.nightscout.androidaps.data; + +import com.crashlytics.android.Crashlytics; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DecimalFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.ToastUtils; + +public class Profile { + private static Logger log = LoggerFactory.getLogger(Profile.class); + + private JSONObject json; + private String units = null; + double dia = Constants.defaultDIA; + TimeZone timeZone = TimeZone.getDefault(); + JSONArray isf; + JSONArray ic; + JSONArray basal; + JSONArray targetLow; + JSONArray targetHigh; + + public Profile(JSONObject json, String units) { + this(json); + if (this.units == null) { + if (units != null) + this.units = units; + else { + Crashlytics.log("Profile failover failed too"); + this.units = Constants.MGDL; + } + } + } + + public Profile(JSONObject json) { + this.json = json; + try { + if (json.has("units")) + units = json.getString("units").toLowerCase(); + if (json.has("dia")) + dia = json.getDouble("dia"); + if (json.has("dia")) + dia = json.getDouble("dia"); + if (json.has("timezone")) + timeZone = TimeZone.getTimeZone(json.getString("timezone")); + isf = json.getJSONArray("sens"); + if (getIsf(0) == null) { + int defaultISF = units.equals(Constants.MGDL) ? 400 : 20; + isf = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultISF + "\",\"timeAsSeconds\":\"0\"}]"); + Notification noisf = new Notification(Notification.ISF_MISSING, MainApp.sResources.getString(R.string.isfmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(noisf)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.ISF_MISSING)); + } + ic = json.getJSONArray("carbratio"); + if (getIc(0) == null) { + int defaultIC = 25; + isf = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultIC + "\",\"timeAsSeconds\":\"0\"}]"); + Notification noic = new Notification(Notification.IC_MISSING, MainApp.sResources.getString(R.string.icmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(noic)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.IC_MISSING)); + } + basal = json.getJSONArray("basal"); + if (getBasal(0) == null) { + double defaultBasal = 0.1d; + isf = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultBasal + "\",\"timeAsSeconds\":\"0\"}]"); + Notification nobasal = new Notification(Notification.BASAL_MISSING, MainApp.sResources.getString(R.string.basalmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(nobasal)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.BASAL_MISSING)); + } + targetLow = json.getJSONArray("target_low"); + if (getTargetLow(0) == null) { + double defaultLow = units.equals(Constants.MGDL) ? 120 : 6; + isf = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultLow + "\",\"timeAsSeconds\":\"0\"}]"); + Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notarget)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.TARGET_MISSING)); + } + targetHigh = json.getJSONArray("target_high"); + if (getTargetHigh(0) == null) { + double defaultHigh = units.equals(Constants.MGDL) ? 160 : 8; + isf = new JSONArray("[{\"time\":\"00:00\",\"value\":\"" + defaultHigh + "\",\"timeAsSeconds\":\"0\"}]"); + Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notarget)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.TARGET_MISSING)); + } + } catch (JSONException e) { + e.printStackTrace(); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.invalidprofile)); + } + } + + public String log() { + String ret = "\n"; + for (Integer hour = 0; hour < 24; hour++) { + double value = getBasal(hour * 60 * 60); + ret += "NS basal value for " + hour + ":00 is " + value + "\n"; + } + ret += "NS units: " + getUnits(); + return ret; + } + + public JSONObject getData() { + return json; + } + + public Double getDia() { + return dia; + } + + // mmol or mg/dl + public String getUnits() { + return units; + } + + public TimeZone getTimeZone() { + return timeZone; + } + + private Double getValueToTime(JSONArray array, Integer timeAsSeconds) { + Double lastValue = null; + + for (Integer index = 0; index < array.length(); index++) { + try { + JSONObject o = array.getJSONObject(index); + Integer tas = o.getInt("timeAsSeconds"); + Double value = o.getDouble("value"); + if (lastValue == null) lastValue = value; + if (timeAsSeconds < tas) { + break; + } + lastValue = value; + } catch (JSONException e) { + e.printStackTrace(); + } + } + return lastValue; + } + + private String getValuesList(JSONArray array, JSONArray array2, DecimalFormat format, String units) { + String retValue = ""; + + for (Integer index = 0; index < array.length(); index++) { + try { + JSONObject o = array.getJSONObject(index); + retValue += o.getString("time"); + retValue += " "; + retValue += format.format(o.getDouble("value")); + if (array2 != null) { + JSONObject o2 = array2.getJSONObject(index); + retValue += " - "; + retValue += format.format(o2.getDouble("value")); + } + retValue += " " + units; + retValue += "\n"; + } catch (JSONException e) { + e.printStackTrace(); + } + } + return retValue; + } + + public Double getIsf() { + return getIsf(secondsFromMidnight(new Date().getTime())); + } + + public Double getIsf(long time) { + return getIsf(secondsFromMidnight(time)); + } + + public Double getIsf(Integer timeAsSeconds) { + return getValueToTime(isf, timeAsSeconds); + } + + public String getIsfList() { + return getValuesList(isf, null, new DecimalFormat("0.0"), getUnits() + "/U"); + } + + public Double getIc() { + return getIc(secondsFromMidnight(new Date().getTime())); + } + + public Double getIc(long time) { + return getIc(secondsFromMidnight(time)); + } + + public Double getIc(Integer timeAsSeconds) { + return getValueToTime(ic, timeAsSeconds); + } + + public String getIcList() { + return getValuesList(ic, null, new DecimalFormat("0.0"), getUnits() + "/U"); + } + + public Double getBasal() { + return getBasal(secondsFromMidnight(new Date().getTime())); + } + + public Double getBasal(long time) { + return getBasal(secondsFromMidnight(time)); + } + + public Double getBasal(Integer timeAsSeconds) { + return getValueToTime(basal, timeAsSeconds); + } + + public String getBasalList() { + return getValuesList(basal, null, new DecimalFormat("0.00"), "U"); + } + + public class BasalValue { + public BasalValue(Integer timeAsSeconds, Double value) { + this.timeAsSeconds = timeAsSeconds; + this.value = value; + } + + public Integer timeAsSeconds; + public Double value; + } + + public BasalValue[] getBasalValues() { + try { + BasalValue[] ret = new BasalValue[basal.length()]; + + for (Integer index = 0; index < basal.length(); index++) { + JSONObject o = basal.getJSONObject(index); + Integer tas = o.getInt("timeAsSeconds"); + Double value = o.getDouble("value"); + ret[index] = new BasalValue(tas, value); + } + return ret; + } catch (JSONException e) { + e.printStackTrace(); + } + return new BasalValue[0]; + } + + public Double getTargetLow() { + return getTargetLow(secondsFromMidnight(new Date().getTime())); + } + + public Double getTargetLow(long time) { + return getTargetLow(secondsFromMidnight(time)); + } + + public Double getTargetLow(Integer timeAsSeconds) { + return getValueToTime(targetLow, timeAsSeconds); + } + + public Double getTargetHigh() { + return getTargetHigh(secondsFromMidnight(new Date().getTime())); + } + + public Double getTargetHigh(long time) { + return getTargetHigh(secondsFromMidnight(time)); + } + + public Double getTargetHigh(Integer timeAsSeconds) { + return getValueToTime(targetHigh, timeAsSeconds); + } + + public String getTargetList() { + return getValuesList(targetLow, targetHigh, new DecimalFormat("0.0"), getUnits()); + } + + public double getMaxDailyBasal() { + Double max = 0d; + for (Integer hour = 0; hour < 24; hour++) { + double value = getBasal(hour * 60 * 60); + if (value > max) max = value; + } + return max; + } + + public static Integer secondsFromMidnight() { + Calendar c = Calendar.getInstance(); + long now = c.getTimeInMillis(); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + long passed = now - c.getTimeInMillis(); + return (int) (passed / 1000); + } + + public static Integer secondsFromMidnight(Date date) { + Calendar c = Calendar.getInstance(); + long now = date.getTime(); + c.setTime(date); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + long passed = now - c.getTimeInMillis(); + return (int) (passed / 1000); + } + + public static Integer secondsFromMidnight(long date) { + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(date); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + long passed = date - c.getTimeInMillis(); + return (int) (passed / 1000); + } + + public static Double toMgdl(Double value, String units) { + if (units.equals(Constants.MGDL)) return value; + else return value * Constants.MMOLL_TO_MGDL; + } + + public static Double fromMgdlToUnits(Double value, String units) { + if (units.equals(Constants.MGDL)) return value; + else return value * Constants.MGDL_TO_MMOLL; + } + + public static Double toUnits(Double valueInMgdl, Double valueInMmol, String units) { + if (units.equals(Constants.MGDL)) return valueInMgdl; + else return valueInMmol; + } + + public static String toUnitsString(Double valueInMgdl, Double valueInMmol, String units) { + if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(valueInMgdl); + else return DecimalFormatter.to1Decimal(valueInMmol); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java new file mode 100644 index 0000000000..ef255ed901 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileIntervals.java @@ -0,0 +1,109 @@ +package info.nightscout.androidaps.data; + +import android.support.annotation.Nullable; +import android.support.v4.util.LongSparseArray; + +import java.util.ArrayList; +import java.util.List; + +import info.nightscout.androidaps.interfaces.Interval; + +/** + * Created by mike on 09.05.2017. + */ + +// Zero duration means profile is valid until is chaged +// When no interval match the lastest record without duration is used + +public class ProfileIntervals { + + private LongSparseArray rawData = new LongSparseArray<>(); // oldest at index 0 + + public ProfileIntervals reset() { + rawData = new LongSparseArray<>(); + return this; + } + + public void add(T newInterval) { + rawData.put(newInterval.start(), newInterval); + merge(); + } + + public void add(List list) { + for (T interval : list) { + rawData.put(interval.start(), interval); + } + merge(); + } + + private void merge() { + for (int index = 0; index < rawData.size() - 1; index++) { + Interval i = rawData.valueAt(index); + long startOfNewer = rawData.valueAt(index + 1).start(); + if (i.originalEnd() > startOfNewer) { + i.cutEndTo(startOfNewer); + } + } + } + + @Nullable + public Interval getValueToTime(long time) { + int index = binarySearch(time); + if (index >= 0) return rawData.valueAt(index); + return null; + } + + public List getList() { + List list = new ArrayList<>(); + for (int i = 0; i < rawData.size(); i++) + list.add(rawData.valueAt(i)); + return list; + } + + public List getReversedList() { + List list = new ArrayList<>(); + for (int i = rawData.size() -1; i>=0; i--) + list.add(rawData.valueAt(i)); + return list; + } + + private int binarySearch(long value) { + if (rawData.size() == 0) + return -1; + int lo = 0; + int hi = rawData.size() - 1; + + while (lo <= hi) { + final int mid = (lo + hi) >>> 1; + final Interval midVal = rawData.valueAt(mid); + + if (midVal.match(value)) { + return mid; // value found + } else if (midVal.before(value)) { + lo = mid + 1; + } else if (midVal.after(value)) { + hi = mid - 1; + } + } + // not found, try nearest older with duration 0 + lo = lo - 1; + while (lo >= 0 && lo < rawData.size()) { + if (rawData.valueAt(lo).isEndingEvent()) + return lo; + lo--; + } + return -1; // value not present + } + + public int size() { + return rawData.size(); + } + + public T get(int index) { + return rawData.valueAt(index); + } + + public T getReversed(int index) { + return rawData.valueAt(size() - 1 - index); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java new file mode 100644 index 0000000000..466351076b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java @@ -0,0 +1,99 @@ +package info.nightscout.androidaps.data; + +import android.support.annotation.Nullable; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Iterator; + +/** + * Created by mike on 01.06.2017. + */ + +public class ProfileStore { + private static Logger log = LoggerFactory.getLogger(ProfileStore.class); + private JSONObject json = null; + + public ProfileStore(JSONObject json) { + this.json = json; + } + + public JSONObject getData() { + return json; + } + + @Nullable + public Profile getDefaultProfile() { + Profile profile = null; + try { + String defaultProfileName = json.getString("defaultProfile"); + JSONObject store = json.getJSONObject("store"); + if (store.has(defaultProfileName)) { + String units = null; + if (store.has("units")) + units = store.getString("units"); + profile = new Profile(store.getJSONObject(defaultProfileName), units); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return profile; + } + + @Nullable + public String getDefaultProfileName() { + String defaultProfileName = null; + try { + defaultProfileName = json.getString("defaultProfile"); + JSONObject store = json.getJSONObject("store"); + if (store.has(defaultProfileName)) { + return defaultProfileName; + } + } catch (JSONException e) { + e.printStackTrace(); + } + return defaultProfileName; + } + + @Nullable + public Profile getSpecificProfile(String profileName) { + Profile profile = null; + try { + JSONObject store = json.getJSONObject("store"); + if (store.has(profileName)) { + String units = null; + if (json.has("units")) + units = json.getString("units"); + profile = new Profile(store.getJSONObject(profileName), units); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return profile; + } + + public ArrayList getProfileList() { + ArrayList ret = new ArrayList(); + + JSONObject store; + try { + store = json.getJSONObject("store"); + Iterator keys = store.keys(); + + while (keys.hasNext()) { + String profileName = (String) keys.next(); + ret.add(profileName); + } + } catch (JSONException e) { + e.printStackTrace(); + } + + return ret; + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java index a2a5b91870..bfddeff320 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java +++ b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java @@ -8,7 +8,6 @@ import org.json.JSONObject; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; @@ -25,7 +24,7 @@ public class PumpEnactResult extends Object { public boolean isTempCancel = false; // if true we are caceling temp basal // Result of treatment delivery public Double bolusDelivered = 0d; // real value of delivered insulin - public Integer carbsDelivered = 0; // real value of delivered carbs + public Double carbsDelivered = 0d; // real value of delivered carbs public boolean queued = false; @@ -94,7 +93,7 @@ public class PumpEnactResult extends Object { result.put("duration", 0); } else if (isPercent) { // Nightscout is expecting absolute value - Double abs = Round.roundTo(MainApp.getConfigBuilder().getActiveProfile().getProfile().getBasal(NSProfile.secondsFromMidnight()) * percent / 100, 0.01); + Double abs = Round.roundTo(MainApp.getConfigBuilder().getProfile().getBasal() * percent / 100, 0.01); result.put("rate", abs); result.put("duration", duration); } else { diff --git a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java index 8a0aaf96e1..fa5cd00c54 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java +++ b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java @@ -2,50 +2,54 @@ package info.nightscout.androidaps.db; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; -import com.jjoe64.graphview.series.DataPointInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; +import java.util.Objects; import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; +import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; +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.DecimalFormatter; +import info.nightscout.utils.SP; @DatabaseTable(tableName = DatabaseHelper.DATABASE_BGREADINGS) -public class BgReading implements DataPointInterface { +public class BgReading implements DataPointWithLabelInterface { private static Logger log = LoggerFactory.getLogger(BgReading.class); - public long getTimeIndex() { - return timeIndex; - } + @DatabaseField(id = true) + public long date; - public void setTimeIndex(long timeIndex) { - this.timeIndex = timeIndex; - } - - @DatabaseField(id = true, useGetSet = true) - public long timeIndex; + @DatabaseField + public boolean isValid = true; @DatabaseField public double value; - @DatabaseField public String direction; - @DatabaseField public double raw; @DatabaseField - public int battery_level; + public int source = Source.NONE; + @DatabaseField + public String _id = null; // NS _id - public static String units = Constants.MGDL; + public boolean isPrediction = false; // true when drawing predictions as bg points - public BgReading() {} + public BgReading() { + } public BgReading(NSSgv sgv) { - timeIndex = sgv.getMills(); + date = sgv.getMills(); value = sgv.getMgdl(); raw = sgv.getFiltered() != null ? sgv.getFiltered() : value; direction = sgv.getDirection(); @@ -63,7 +67,7 @@ public class BgReading implements DataPointInterface { else return DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL); } - public String directionToSymbol() { + public String directionToSymbol() { String symbol = ""; if (direction.compareTo("DoubleDown") == 0) { symbol = "\u21ca"; @@ -101,23 +105,108 @@ public class BgReading implements DataPointInterface { @Override public String toString() { return "BgReading{" + - "timeIndex=" + timeIndex + - ", date=" + new Date(timeIndex) + + "date=" + date + + ", date=" + new Date(date).toLocaleString() + ", value=" + value + ", direction=" + direction + ", raw=" + raw + - ", battery_level=" + battery_level + '}'; } + public boolean isDataChanging(BgReading other) { + if (date != other.date) { + log.error("Comparing different"); + return false; + } + if (value != other.value) + return true; + return false; + } + + public boolean isEqual(BgReading other) { + if (date != other.date) { + log.error("Comparing different"); + return false; + } + if (value != other.value) + return false; + if (raw != other.raw) + return false; + if (!direction.equals(other.direction)) + return false; + if (!Objects.equals(_id, other._id)) + return false; + return true; + } + + public void copyFrom(BgReading other) { + if (date != other.date) { + log.error("Copying different"); + return; + } + value = other.value; + raw = other.raw; + direction = other.direction; + _id = other._id; + } + + // ------------------ DataPointWithLabelInterface ------------------ @Override public double getX() { - return timeIndex; + return date; } @Override public double getY() { + String units = MainApp.getConfigBuilder().getProfile().getUnits(); return valueToUnits(units); } + @Override + public void setY(double y) { + + } + + @Override + public String getLabel() { + return null; + } + + @Override + public long getDuration() { + return 0; + } + + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + return PointsWithLabelGraphSeries.Shape.POINT; + } + + @Override + public float getSize() { + boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet); + return isTablet ? 8 : 5; + } + + @Override + public int getColor() { + String units = MainApp.getConfigBuilder().getProfile().getUnits(); + Double lowLine = SP.getDouble("low_mark", 0d); + Double highLine = SP.getDouble("high_mark", 0d); + if (lowLine < 1) { + lowLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units); + } + if (highLine < 1) { + highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); + } + int color = MainApp.sResources.getColor(R.color.inrange); + if (isPrediction) + color = MainApp.sResources.getColor(R.color.prediction); + else if (valueToUnits(units) < lowLine) + color = MainApp.sResources.getColor(R.color.low); + else if (valueToUnits(units) > highLine) + color = MainApp.sResources.getColor(R.color.high); + return color; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java new file mode 100644 index 0000000000..3d67abc597 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -0,0 +1,244 @@ +package info.nightscout.androidaps.db; + +import android.graphics.Color; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +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.plugins.NSClientInternal.data.NSMbg; +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.Translator; + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_CAREPORTALEVENTS) +public class CareportalEvent implements DataPointWithLabelInterface { + private static Logger log = LoggerFactory.getLogger(CareportalEvent.class); + + @DatabaseField(id = true) + public long date; + + @DatabaseField + public boolean isValid = true; + + @DatabaseField + public int source = Source.NONE; + @DatabaseField + public String _id; + + @DatabaseField + public String eventType; + @DatabaseField + public String json; + + public static final String CARBCORRECTION = "Carb Correction"; + public static final String BOLUSWIZARD = "Bolus Wizard"; + public static final String CORRECTIONBOLUS = "Correction Bolus"; + public static final String MEALBOLUS = "Meal Bolus"; + public static final String COMBOBOLUS = "Combo Bolus"; + public static final String TEMPBASAL = "Temp Basal"; + public static final String TEMPORARYTARGET = "Temporary Target"; + public static final String PROFILESWITCH = "Profile Switch"; + public static final String SITECHANGE = "Site Change"; + public static final String INSULINCHANGE = "Insulin Change"; + public static final String SENSORCHANGE = "Sensor Change"; + public static final String PUMPBATTERYCHANGE = "Pump Battery Change"; + public static final String BGCHECK = "BG Check"; + public static final String ANNOUNCEMENT = "Announcement"; + public static final String NOTE = "Note"; + public static final String QUESTION = "Question"; + public static final String EXERCISE = "Exercise"; + public static final String OPENAPSOFFLINE = "OpenAPS Offline"; + public static final String NONE = ""; + + public static final String MBG = "Mbg"; // comming from entries + + public CareportalEvent() { + } + + public CareportalEvent(NSMbg mbg) { + date = mbg.date; + eventType = MBG; + json = mbg.json; + } + + public long getMillisecondsFromStart() { + return new Date().getTime() - date; + } + + public long getHoursFromStart() { + return (new Date().getTime() - date) / (60 * 1000); + } + + public String age() { + Map diff = computeDiff(date, new Date().getTime()); + return diff.get(TimeUnit.DAYS) + " " + MainApp.sResources.getString(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.sResources.getString(R.string.hours); + } + + public String log() { + return "CareportalEvent{" + + "date= " + date + + ", date= " + DateUtil.dateAndTimeString(date) + + ", isValid= " + isValid + + ", _id= " + _id + + ", eventType= " + eventType + + ", json= " + json + + "}"; + } + + //Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0} + public static Map computeDiff(long date1, long date2) { + long diffInMillies = date2 - date1; + List units = new ArrayList(EnumSet.allOf(TimeUnit.class)); + Collections.reverse(units); + Map result = new LinkedHashMap(); + long milliesRest = diffInMillies; + for ( TimeUnit unit : units ) { + long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS); + long diffInMilliesForUnit = unit.toMillis(diff); + milliesRest = milliesRest - diffInMilliesForUnit; + result.put(unit,diff); + } + return result; + } + + // -------- DataPointWithLabelInterface ------- + + @Override + public double getX() { + return date; + } + + double yValue = 0; + + @Override + public double getY() { + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (eventType.equals(MBG)) { + double mbg = 0d; + try { + JSONObject object = new JSONObject(json); + mbg = object.getDouble("mgdl"); + } catch (JSONException e) { + e.printStackTrace(); + } + if (profile != null) + return profile.fromMgdlToUnits(mbg, profile.getUnits()); + return 0d; + } + + double glucose = 0d; + String units = Constants.MGDL; + try { + JSONObject object = new JSONObject(json); + if (object.has("glucose")) { + glucose = object.getDouble("glucose"); + units = object.getString("units"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + if (profile != null && glucose != 0d) { + double mmol = 0d; + double mgdl = 0; + if (units.equals(Constants.MGDL)) { + mgdl = glucose; + mmol = glucose * Constants.MGDL_TO_MMOLL; + } + if (units.equals(Constants.MMOL)) { + mmol = glucose; + mgdl = glucose * Constants.MMOLL_TO_MGDL; + } + return profile.toUnits(mgdl, mmol, profile.getUnits()); + } + + return yValue; + } + + @Override + public void setY(double y) { + yValue = y; + } + + @Override + public String getLabel() { + try { + JSONObject object = new JSONObject(json); + if (object.has("notes")) + return object.getString("notes"); + } catch (JSONException e) { + e.printStackTrace(); + } + return Translator.translate(eventType); + } + + @Override + public long getDuration() { + try { + JSONObject object = new JSONObject(json); + if (object.has("duration")) + return object.getInt("duration") * 60 * 1000L; + } catch (JSONException e) { + e.printStackTrace(); + } + return 0; + } + + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + switch (eventType) { + case CareportalEvent.MBG: + return PointsWithLabelGraphSeries.Shape.MBG; + case CareportalEvent.BGCHECK: + return PointsWithLabelGraphSeries.Shape.BGCHECK; + case CareportalEvent.ANNOUNCEMENT: + return PointsWithLabelGraphSeries.Shape.ANNOUNCEMENT; + case CareportalEvent.OPENAPSOFFLINE: + return PointsWithLabelGraphSeries.Shape.OPENAPSOFFLINE; + case CareportalEvent.EXERCISE: + return PointsWithLabelGraphSeries.Shape.EXERCISE; + } + if (getDuration() > 0) + return PointsWithLabelGraphSeries.Shape.GENERALWITHDURATION; + return PointsWithLabelGraphSeries.Shape.GENERAL; + } + + @Override + public float getSize() { + boolean isTablet = MainApp.sResources.getBoolean(R.bool.isTablet); + return isTablet ? 12 : 10; + } + + @Override + public int getColor() { + if (eventType.equals(ANNOUNCEMENT)) + return 0xFFFF8C00; + if (eventType.equals(MBG)) + return Color.RED; + if (eventType.equals(BGCHECK)) + return Color.RED; + if (eventType.equals(EXERCISE)) + return Color.BLUE; + if (eventType.equals(OPENAPSOFFLINE)) + return Color.GRAY; + return Color.GRAY; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/db/DanaRHistoryRecord.java b/app/src/main/java/info/nightscout/androidaps/db/DanaRHistoryRecord.java index 48b976548b..5c2e4f4985 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DanaRHistoryRecord.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DanaRHistoryRecord.java @@ -8,38 +8,38 @@ import java.util.Date; @DatabaseTable(tableName = DatabaseHelper.DATABASE_DANARHISTORY) public class DanaRHistoryRecord { - @DatabaseField(useGetSet = true) - private String _id; + @DatabaseField + public String _id; - @DatabaseField(useGetSet = true) - private byte recordCode; + @DatabaseField + public byte recordCode; - @DatabaseField(id = true, useGetSet = true) - private String bytes; + @DatabaseField(id = true) + public String bytes; - @DatabaseField(useGetSet = true) - private long recordDate; + @DatabaseField + public long recordDate; - @DatabaseField(useGetSet = true) - private double recordValue; + @DatabaseField + public double recordValue; - @DatabaseField(useGetSet = true) - private String bolusType; + @DatabaseField + public String bolusType; - @DatabaseField(useGetSet = true) - private String stringRecordValue; + @DatabaseField + public String stringRecordValue; - @DatabaseField(useGetSet = true) - private int recordDuration; + @DatabaseField + public int recordDuration; - @DatabaseField(useGetSet = true) - private double recordDailyBasal; + @DatabaseField + public double recordDailyBasal; - @DatabaseField(useGetSet = true) - private double recordDailyBolus; + @DatabaseField + public double recordDailyBolus; - @DatabaseField(useGetSet = true) - private String recordAlarm; + @DatabaseField + public String recordAlarm; public DanaRHistoryRecord() { this.recordDate = 0; @@ -50,74 +50,6 @@ public class DanaRHistoryRecord { this._id = null; } - public void setRecordDate(Date dtRecordDate) { - this.recordDate = dtRecordDate.getTime(); - } - - public long getRecordDate() { - return this.recordDate; - } - - public void setRecordDate(long dtRecordDate) { - this.recordDate = dtRecordDate; - } - - public double getRecordValue() { - return this.recordValue; - } - - public void setRecordValue(double dRecordValue) { - this.recordValue = dRecordValue; - } - - public String getBolusType() { - return this.bolusType; - } - - public void setBolusType(String strRecordType) { - this.bolusType = strRecordType; - } - - public String getStringRecordValue() { - return this.stringRecordValue; - } - - public void setStringRecordValue(String strRecordValue) { - this.stringRecordValue = strRecordValue; - } - - public byte getRecordCode() { - return this.recordCode; - } - - public void setRecordCode(byte cRecordCode) { - this.recordCode = cRecordCode; - } - - public int getRecordDuration() { - return this.recordDuration; - } - - public void setRecordDuration(int dRecordDuraion) { - this.recordDuration = dRecordDuraion; - } - - public double getRecordDailyBasal() { - return this.recordDailyBasal; - } - - public void setRecordDailyBasal(double dRecordDailyBasal) { - this.recordDailyBasal = dRecordDailyBasal; - } - - public double getRecordDailyBolus() { - return this.recordDailyBolus; - } - - public void setRecordDailyBolus(double dRecordDailyBolus) { - this.recordDailyBolus = dRecordDailyBolus; - } - public int getRecordLevel(double dExLow, double dLow, double dHigh, double dExHigh) { if (this.recordValue < dExLow) return 0; @@ -128,34 +60,10 @@ public class DanaRHistoryRecord { return this.recordValue < dExHigh ? 3 : 4; } - public String getRecordAlarm() { - return this.recordAlarm; - } - - public void setRecordAlarm(String strAlarm) { - this.recordAlarm = strAlarm; - } - - public String get_id() { - return this._id; - } - - public void set_id(String _id) { - this._id = _id; - } - public void setBytes(byte[] raw) { this.bytes = bytesToHex(raw); } - public void setBytes(String bytes) { - this.bytes = bytes; - } - - public String getBytes() { - return this.bytes; - } - final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes) { 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 17ee574678..cd216ef8e0 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -6,6 +6,7 @@ import android.database.sqlite.SQLiteDatabase; import android.support.annotation.Nullable; import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; +import com.j256.ormlite.dao.CloseableIterator; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.QueryBuilder; @@ -13,6 +14,8 @@ import com.j256.ormlite.stmt.Where; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; +import org.json.JSONException; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,42 +31,78 @@ 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.Profile; +import info.nightscout.androidaps.events.EventCareportalEventChange; +import info.nightscout.androidaps.events.EventExtendedBolusChange; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventReloadTempBasalData; +import info.nightscout.androidaps.events.EventReloadTreatmentData; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class); public static final String DATABASE_NAME = "AndroidAPSDb"; public static final String DATABASE_BGREADINGS = "BgReadings"; - public static final String DATABASE_TEMPBASALS = "TempBasals"; + public static final String DATABASE_TEMPORARYBASALS = "TemporaryBasals"; + public static final String DATABASE_EXTENDEDBOLUSES = "ExtendedBoluses"; public static final String DATABASE_TEMPTARGETS = "TempTargets"; public static final String DATABASE_TREATMENTS = "Treatments"; public static final String DATABASE_DANARHISTORY = "DanaRHistory"; public static final String DATABASE_DBREQUESTS = "DBRequests"; + public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents"; + public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches"; - private static final int DATABASE_VERSION = 5; + private static final int DATABASE_VERSION = 7; - private long latestTreatmentChange = 0; + private static Long earliestDataChange = null; - private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); - private static ScheduledFuture scheduledPost = null; + private static final ScheduledExecutorService bgWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledBgPost = null; + + private static final ScheduledExecutorService treatmentsWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledTratmentPost = null; + + private static final ScheduledExecutorService tempBasalsWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledTemBasalsPost = null; + + private static final ScheduledExecutorService tempTargetWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledTemTargetPost = null; + + private static final ScheduledExecutorService extendedBolusWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledExtendedBolusPost = null; + + private static final ScheduledExecutorService careportalEventWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledCareportalEventPost = null; + + private static final ScheduledExecutorService profileSwitchEventWorker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledProfileSwitchEventPost = null; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); onCreate(getWritableDatabase(), getConnectionSource()); + //onUpgrade(getWritableDatabase(), getConnectionSource(), 1,1); } - @Override public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { log.info("onCreate"); - TableUtils.createTableIfNotExists(connectionSource, TempBasal.class); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); + TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); + TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); + TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); + TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); } catch (SQLException e) { log.error("Can't create database", e); throw new RuntimeException(e); @@ -74,12 +113,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) { try { log.info(DatabaseHelper.class.getName(), "onUpgrade"); - TableUtils.dropTable(connectionSource, TempBasal.class, true); TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); TableUtils.dropTable(connectionSource, DbRequest.class, true); + TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); + TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); + TableUtils.dropTable(connectionSource, CareportalEvent.class, true); + TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); onCreate(database, connectionSource); } catch (SQLException e) { log.error("Can't drop databases", e); @@ -98,53 +140,95 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void cleanUpDatabases() { // TODO: call it somewhere log.debug("Before BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); - getWritableDatabase().delete(DATABASE_BGREADINGS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + getWritableDatabase().delete(DATABASE_BGREADINGS, "date" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); log.debug("After BgReadings size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_BGREADINGS)); - log.debug("Before TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS)); - getWritableDatabase().delete(DATABASE_TEMPBASALS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); - log.debug("After TempBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPBASALS)); - log.debug("Before TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS)); - getWritableDatabase().delete(DATABASE_TEMPTARGETS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + getWritableDatabase().delete(DATABASE_TEMPTARGETS, "date" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); log.debug("After TempTargets size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPTARGETS)); log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); - getWritableDatabase().delete(DATABASE_TREATMENTS, "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); + getWritableDatabase().delete(DATABASE_TREATMENTS, "date" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null); log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TREATMENTS)); log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY)); getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_DANARHISTORY)); + + log.debug("Before TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS)); + getWritableDatabase().delete(DATABASE_TEMPORARYBASALS, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); + log.debug("After TemporaryBasals size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_TEMPORARYBASALS)); + + log.debug("Before ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES)); + getWritableDatabase().delete(DATABASE_EXTENDEDBOLUSES, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); + log.debug("After ExtendedBoluses size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_EXTENDEDBOLUSES)); + + log.debug("Before CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS)); + getWritableDatabase().delete(DATABASE_CAREPORTALEVENTS, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); + log.debug("After CareportalEvent size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_CAREPORTALEVENTS)); + + log.debug("Before ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES)); + getWritableDatabase().delete(DATABASE_PROFILESWITCHES, "recordDate" + " < '" + (new Date().getTime() - Constants.daysToKeepHistoryInDatabase * 24 * 60 * 60 * 1000L) + "'", null); + log.debug("After ProfileSwitch size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), DATABASE_PROFILESWITCHES)); } + public long size(String database) { + return DatabaseUtils.queryNumEntries(getReadableDatabase(), database); + } + + // --------------------- DB resets --------------------- + public void resetDatabases() { try { - TableUtils.dropTable(connectionSource, TempBasal.class, true); TableUtils.dropTable(connectionSource, TempTarget.class, true); TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.dropTable(connectionSource, BgReading.class, true); TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); - //DbRequests can be cleared from NSClient fragment - TableUtils.createTableIfNotExists(connectionSource, TempBasal.class); + TableUtils.dropTable(connectionSource, DbRequest.class, true); + TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); + TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); + TableUtils.dropTable(connectionSource, CareportalEvent.class, true); + TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); TableUtils.createTableIfNotExists(connectionSource, TempTarget.class); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); TableUtils.createTableIfNotExists(connectionSource, BgReading.class); TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); - latestTreatmentChange = 0; + TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); + TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); + TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); + TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); + TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); + updateEarliestDataChange(0); } catch (SQLException e) { e.printStackTrace(); } + scheduleBgChange(); // trigger refresh + scheduleTemporaryBasalChange(); + scheduleTreatmentChange(); + scheduleExtendedBolusChange(); + scheduleTemporaryTargetChange(); + scheduleCareportalEventChange(); + scheduleProfileSwitchChange(); + new java.util.Timer().schedule( + new java.util.TimerTask() { + @Override + public void run() { + MainApp.bus().post(new EventRefreshGui(false)); + } + }, + 3000 + ); } public void resetTreatments() { try { TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); - latestTreatmentChange = 0; + updateEarliestDataChange(0); } catch (SQLException e) { e.printStackTrace(); } + scheduleTreatmentChange(); } public void resetTempTargets() { @@ -154,13 +238,54 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } catch (SQLException e) { e.printStackTrace(); } + scheduleTemporaryTargetChange(); } - public Dao getDaoTempBasals() throws SQLException { - return getDao(TempBasal.class); + public void resetTemporaryBasals() { + try { + TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); + TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); + updateEarliestDataChange(0); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleTemporaryBasalChange(); } - public Dao getDaoTempTargets() throws SQLException { + public void resetExtededBoluses() { + try { + TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); + TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); + updateEarliestDataChange(0); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleExtendedBolusChange(); + } + + public void resetCareportalEvents() { + try { + TableUtils.dropTable(connectionSource, CareportalEvent.class, true); + TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleCareportalEventChange(); + } + + public void resetProfileSwitch() { + try { + TableUtils.dropTable(connectionSource, ProfileSwitch.class, true); + TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleProfileSwitchChange(); + } + + // ------------------ getDao ------------------------------------------- + + private Dao getDaoTempTargets() throws SQLException { return getDao(TempTarget.class); } @@ -168,30 +293,130 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return getDao(Treatment.class); } - public Dao getDaoBgReadings() throws SQLException { + private Dao getDaoBgReadings() throws SQLException { return getDao(BgReading.class); } - public Dao getDaoDanaRHistory() throws SQLException { + private Dao getDaoDanaRHistory() throws SQLException { return getDao(DanaRHistoryRecord.class); } - public Dao getDaoDbRequest() throws SQLException { + private Dao getDaoDbRequest() throws SQLException { return getDao(DbRequest.class); } - public long size(String database) { - return DatabaseUtils.queryNumEntries(getReadableDatabase(), database); + private Dao getDaoTemporaryBasal() throws SQLException { + return getDao(TemporaryBasal.class); } + private Dao getDaoExtendedBolus() throws SQLException { + return getDao(ExtendedBolus.class); + } + + private Dao getDaoCareportalEvents() throws SQLException { + return getDao(CareportalEvent.class); + } + + private Dao getDaoProfileSwitch() throws SQLException { + return getDao(ProfileSwitch.class); + } + + public long roundDateToSec(long date) { + return date - date % 1000; + } + // ------------------- BgReading handling ----------------------- + + public void createIfNotExists(BgReading bgReading, String from) { + try { + bgReading.date = roundDateToSec(bgReading.date); + BgReading old = getDaoBgReadings().queryForId(bgReading.date); + if (old == null) { + getDaoBgReadings().create(bgReading); + log.debug("BG: New record from: " + from + " " + bgReading.toString()); + scheduleBgChange(); + return; + } + if (!old.isEqual(bgReading)) { + old.copyFrom(bgReading); + getDaoBgReadings().update(old); + log.debug("BG: Updating record from: " + from + " " + old.toString()); + scheduleBgChange(); + return; + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private static void scheduleBgChange() { + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing EventNewBg"); + MainApp.bus().post(new EventNewBG()); + scheduledBgPost = null; + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (scheduledBgPost != null) + scheduledBgPost.cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + scheduledBgPost = bgWorker.schedule(task, sec, TimeUnit.SECONDS); + + } + + /* + * Return last BgReading from database or null if db is empty + */ + @Nullable + public static BgReading lastBg() { + List bgList = null; + + try { + Dao daoBgReadings = MainApp.getDbHelper().getDaoBgReadings(); + QueryBuilder queryBuilder = daoBgReadings.queryBuilder(); + queryBuilder.orderBy("date", false); + queryBuilder.limit(1L); + queryBuilder.where().gt("value", 38); + PreparedQuery preparedQuery = queryBuilder.prepare(); + bgList = daoBgReadings.query(preparedQuery); + + } catch (SQLException e) { + log.debug(e.getMessage(), e); + } + if (bgList != null && bgList.size() > 0) + return bgList.get(0); + else + return null; + } + + /* + * Return bg reading if not old ( <9 min ) + * or null if older + */ + @Nullable + public static BgReading actualBg() { + BgReading lastBg = lastBg(); + + if (lastBg == null) + return null; + + if (lastBg.date > new Date().getTime() - 9 * 60 * 1000) + return lastBg; + + return null; + } + + public List getBgreadingsDataFromTime(long mills, boolean ascending) { try { Dao daoBgreadings = getDaoBgReadings(); List bgReadings; QueryBuilder queryBuilder = daoBgreadings.queryBuilder(); - queryBuilder.orderBy("timeIndex", ascending); + queryBuilder.orderBy("date", ascending); Where where = queryBuilder.where(); - where.ge("timeIndex", mills).and().gt("value", 38); + where.ge("date", mills).and().gt("value", 38); PreparedQuery preparedQuery = queryBuilder.prepare(); bgReadings = daoBgreadings.query(preparedQuery); return bgReadings; @@ -201,7 +426,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } - // DbRequests handling + // ------------- DbRequests handling ------------------- public void create(DbRequest dbr) { try { @@ -211,7 +436,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - public int delete(DbRequest dbr) { + public int delete(DbRequest dbr) { try { return getDaoDbRequest().delete(dbr); } catch (SQLException e) { @@ -257,75 +482,121 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - // TREATMENT HANDLING - - public boolean isDataUnchanged(long time) { - if (time >= latestTreatmentChange) return true; - else return false; + public CloseableIterator getDbRequestInterator() { + try { + return getDaoDbRequest().closeableIterator(); + } catch (SQLException e) { + e.printStackTrace(); + return null; + } } - public int update(Treatment treatment) { - int updated = 0; + // -------------------- TREATMENT HANDLING ------------------- + + // return true if new record is created + public boolean createOrUpdate(Treatment treatment) { try { - updated = getDaoTreatments().update(treatment); - latestTreatmentChange = treatment.getTimeIndex(); + Treatment old; + treatment.date = roundDateToSec(treatment.date); + + if (treatment.source == Source.PUMP) { + // check for changed from pump change in NS + QueryBuilder queryBuilder = getDaoTreatments().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("pumpId", treatment.pumpId); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoTreatments().query(preparedQuery); + if (trList.size() > 0) { + // do nothing, pump history record cannot be changed + return false; + } + getDaoTreatments().create(treatment); + log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(); + return true; + } + if (treatment.source == Source.NIGHTSCOUT) { + old = getDaoTreatments().queryForId(treatment.date); + if (old != null) { + if (!old.isEqual(treatment)) { + boolean historyChange = old.isDataChanging(treatment); + long oldDate = old.date; + getDaoTreatments().delete(old); // need to delete/create because date may change too + old.copyFrom(treatment); + getDaoTreatments().create(old); + log.debug("TREATMENT: Updating record by date from: " + Source.getString(treatment.source) + " " + old.toString()); + if (historyChange) { + updateEarliestDataChange(oldDate); + updateEarliestDataChange(old.date); + } + scheduleTreatmentChange(); + return true; + } + return false; + } + // find by NS _id + if (treatment._id != null) { + QueryBuilder queryBuilder = getDaoTreatments().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", treatment._id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoTreatments().query(preparedQuery); + if (trList.size() > 0) { + old = trList.get(0); + if (!old.isEqual(treatment)) { + boolean historyChange = old.isDataChanging(treatment); + long oldDate = old.date; + getDaoTreatments().delete(old); // need to delete/create because date may change too + old.copyFrom(treatment); + getDaoTreatments().create(old); + log.debug("TREATMENT: Updating record by _id from: " + Source.getString(treatment.source) + " " + old.toString()); + if (historyChange) { + updateEarliestDataChange(oldDate); + updateEarliestDataChange(old.date); + } + scheduleTreatmentChange(); + return true; + } + } + } + getDaoTreatments().create(treatment); + log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(); + return true; + } + if (treatment.source == Source.USER) { + getDaoTreatments().create(treatment); + log.debug("TREATMENT: New record from: " + Source.getString(treatment.source) + " " + treatment.toString()); + updateEarliestDataChange(treatment.date); + scheduleTreatmentChange(); + return true; + } } catch (SQLException e) { e.printStackTrace(); } - scheduleTreatmentChange(); - return updated; - } - - public Dao.CreateOrUpdateStatus createOrUpdate(Treatment treatment) { - Dao.CreateOrUpdateStatus status = null; - try { - status = getDaoTreatments().createOrUpdate(treatment); - latestTreatmentChange = treatment.getTimeIndex(); - } catch (SQLException e) { - e.printStackTrace(); - } - scheduleTreatmentChange(); - return status; - } - - public void create(Treatment treatment) { - try { - getDaoTreatments().create(treatment); - latestTreatmentChange = treatment.getTimeIndex(); - } catch (SQLException e) { - e.printStackTrace(); - } - scheduleTreatmentChange(); + return false; } public void delete(Treatment treatment) { try { getDaoTreatments().delete(treatment); - latestTreatmentChange = treatment.getTimeIndex(); + updateEarliestDataChange(treatment.date); } catch (SQLException e) { e.printStackTrace(); } scheduleTreatmentChange(); } - public int delete(String _id) { + public void deleteTreatmentById(String _id) { Treatment stored = findTreatmentById(_id); - int removed = 0; if (stored != null) { - log.debug("REMOVE: Existing treatment (removing): " + _id); - try { - removed = getDaoTreatments().delete(stored); - } catch (SQLException e) { - e.printStackTrace(); - } - if (Config.logIncommingData) - log.debug("Records removed: " + removed); - latestTreatmentChange = stored.getTimeIndex(); + log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString()); + delete(stored); + updateEarliestDataChange(stored.date); scheduleTreatmentChange(); - } else { - log.debug("REMOVE: Not stored treatment (ignoring): " + _id); } - return removed; } @Nullable @@ -351,44 +622,35 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return null; } - @Nullable - public Treatment findTreatmentByTimeIndex(Long timeIndex) { - try { - QueryBuilder qb = null; - Dao daoTreatments = getDaoTreatments(); - QueryBuilder queryBuilder = daoTreatments.queryBuilder(); - Where where = queryBuilder.where(); - where.eq("timeIndex", timeIndex); - queryBuilder.limit(10L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = daoTreatments.query(preparedQuery); - if (trList.size() != 1) { - log.debug("Treatment findTreatmentByTimeIndex query size: " + trList.size()); - return null; - } else { - log.debug("Treatment findTreatmentByTimeIndex found: " + trList.get(0).log()); - return trList.get(0); - } - } catch (SQLException e) { - e.printStackTrace(); + private void updateEarliestDataChange(long newDate) { + if (earliestDataChange == null) { + earliestDataChange = newDate; + return; + } + if (newDate < earliestDataChange) { + earliestDataChange = newDate; } - return null; } - static public void scheduleTreatmentChange() { + private static void scheduleTreatmentChange() { class PostRunnable implements Runnable { public void run() { + log.debug("Firing EventTreatmentChange"); + MainApp.bus().post(new EventReloadTreatmentData()); MainApp.bus().post(new EventTreatmentChange()); - scheduledPost = null; + if (earliestDataChange != null) + MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); + earliestDataChange = null; + scheduledTratmentPost = null; } } - // prepare task for execution in 5 sec + // prepare task for execution in 1 sec // cancel waiting task to prevent sending multiple posts - if (scheduledPost != null) - scheduledPost.cancel(false); + if (scheduledTratmentPost != null) + scheduledTratmentPost.cancel(false); Runnable task = new PostRunnable(); - final int sec = 5; - scheduledPost = worker.schedule(task, sec, TimeUnit.SECONDS); + final int sec = 1; + scheduledTratmentPost = treatmentsWorker.schedule(task, sec, TimeUnit.SECONDS); } @@ -397,9 +659,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { Dao daoTreatments = getDaoTreatments(); List treatments; QueryBuilder queryBuilder = daoTreatments.queryBuilder(); - queryBuilder.orderBy("timeIndex", ascending); + queryBuilder.orderBy("date", ascending); Where where = queryBuilder.where(); - where.ge("timeIndex", mills); + where.ge("date", mills); PreparedQuery preparedQuery = queryBuilder.prepare(); treatments = daoTreatments.query(preparedQuery); return treatments; @@ -409,14 +671,43 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } + public void createTreatmentFromJsonIfNotExists(JSONObject trJson) { + try { + Treatment treatment = new Treatment(); + treatment.source = Source.NIGHTSCOUT; + treatment.date = roundDateToSec(trJson.getLong("mills")); + treatment.carbs = trJson.has("carbs") ? trJson.getDouble("carbs") : 0; + treatment.insulin = trJson.has("insulin") ? trJson.getDouble("insulin") : 0d; + treatment.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; + treatment._id = trJson.getString("_id"); + if (trJson.has("eventType")) { + treatment.mealBolus = !trJson.get("eventType").equals("Correction Bolus"); + double carbs = treatment.carbs; + if (trJson.has("boluscalc")) { + JSONObject boluscalc = trJson.getJSONObject("boluscalc"); + if (boluscalc.has("carbs")) { + carbs = Math.max(boluscalc.getDouble("carbs"), carbs); + } + } + if (carbs <= 0) + treatment.mealBolus = false; + } + createOrUpdate(treatment); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + // ---------------- TempTargets handling --------------- + public List getTemptargetsDataFromTime(long mills, boolean ascending) { try { Dao daoTempTargets = getDaoTempTargets(); List tempTargets; QueryBuilder queryBuilder = daoTempTargets.queryBuilder(); - queryBuilder.orderBy("timeIndex", ascending); + queryBuilder.orderBy("date", ascending); Where where = queryBuilder.where(); - where.ge("timeIndex", mills); + where.ge("date", mills); PreparedQuery preparedQuery = queryBuilder.prepare(); tempTargets = daoTempTargets.query(preparedQuery); return tempTargets; @@ -426,22 +717,923 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } - - public List getTempbasalsDataFromTime(long mills, boolean ascending, boolean isExtended) { + public boolean createOrUpdate(TempTarget tempTarget) { try { - Dao daoTempbasals = getDaoTempBasals(); - List tempbasals; - QueryBuilder queryBuilder = daoTempbasals.queryBuilder(); - queryBuilder.orderBy("timeIndex", ascending); + TempTarget old; + tempTarget.date = roundDateToSec(tempTarget.date); + + if (tempTarget.source == Source.NIGHTSCOUT) { + old = getDaoTempTargets().queryForId(tempTarget.date); + if (old != null) { + if (!old.isEqual(tempTarget)) { + getDaoTempTargets().delete(old); // need to delete/create because date may change too + old.copyFrom(tempTarget); + getDaoTempTargets().create(old); + log.debug("TEMPTARGET: Updating record by date from: " + Source.getString(tempTarget.source) + " " + old.toString()); + scheduleTemporaryTargetChange(); + return true; + } + return false; + } + // find by NS _id + if (tempTarget._id != null) { + QueryBuilder queryBuilder = getDaoTempTargets().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", tempTarget._id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoTempTargets().query(preparedQuery); + if (trList.size() > 0) { + old = trList.get(0); + if (!old.isEqual(tempTarget)) { + getDaoTempTargets().delete(old); // need to delete/create because date may change too + old.copyFrom(tempTarget); + getDaoTempTargets().create(old); + log.debug("TEMPTARGET: Updating record by _id from: " + Source.getString(tempTarget.source) + " " + old.toString()); + scheduleTemporaryTargetChange(); + return true; + } + } + } + getDaoTempTargets().create(tempTarget); + log.debug("TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString()); + scheduleTemporaryTargetChange(); + return true; + } + if (tempTarget.source == Source.USER) { + getDaoTempTargets().create(tempTarget); + log.debug("TEMPTARGET: New record from: " + Source.getString(tempTarget.source) + " " + tempTarget.toString()); + scheduleTemporaryTargetChange(); + return true; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + public void delete(TempTarget tempTarget) { + try { + getDaoTempTargets().delete(tempTarget); + scheduleTemporaryTargetChange(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private static void scheduleTemporaryTargetChange() { + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing EventTempTargetChange"); + MainApp.bus().post(new EventTempTargetChange()); + scheduledTemTargetPost = null; + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (scheduledTemTargetPost != null) + scheduledTemTargetPost.cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + scheduledTemTargetPost = tempTargetWorker.schedule(task, sec, TimeUnit.SECONDS); + + } + + /* + { + "_id": "58795998aa86647ba4d68ce7", + "enteredBy": "", + "eventType": "Temporary Target", + "reason": "Eating Soon", + "targetTop": 80, + "targetBottom": 80, + "duration": 120, + "created_at": "2017-01-13T22:50:00.782Z", + "carbs": null, + "insulin": null +} + */ + + public void createTemptargetFromJsonIfNotExists(JSONObject trJson) { + try { + Profile profile = MainApp.getConfigBuilder().getProfile(); + String units = profile.getUnits(); + TempTarget tempTarget = new TempTarget(); + tempTarget.date = trJson.getLong("mills"); + tempTarget.durationInMinutes = trJson.getInt("duration"); + tempTarget.low = Profile.toMgdl(trJson.getDouble("targetBottom"), units); + tempTarget.high = Profile.toMgdl(trJson.getDouble("targetTop"), units); + tempTarget.reason = trJson.getString("reason"); + tempTarget._id = trJson.getString("_id"); + tempTarget.source = Source.NIGHTSCOUT; + createOrUpdate(tempTarget); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void deleteTempTargetById(String _id) { + TempTarget stored = findTempTargetById(_id); + if (stored != null) { + log.debug("TEMPTARGET: Removing TempTarget record from database: " + stored.toString()); + delete(stored); + scheduleTemporaryTargetChange(); + } + } + + public TempTarget findTempTargetById(String _id) { + try { + QueryBuilder queryBuilder = getDaoTempTargets().queryBuilder(); Where where = queryBuilder.where(); - where.ge("timeIndex", mills).and().eq("isExtended", isExtended); - PreparedQuery preparedQuery = queryBuilder.prepare(); - tempbasals = daoTempbasals.query(preparedQuery); + where.eq("_id", _id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoTempTargets().query(preparedQuery); + + if (list.size() == 1) { + return list.get(0); + } else { + return null; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + // ----------------- DanaRHistory handling -------------------- + + public void createOrUpdate(DanaRHistoryRecord record) { + try { + getDaoDanaRHistory().createOrUpdate(record); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public List getDanaRHistoryRecordsByType(byte type) { + List historyList; + try { + QueryBuilder queryBuilder = getDaoDanaRHistory().queryBuilder(); + queryBuilder.orderBy("recordDate", false); + Where where = queryBuilder.where(); + where.eq("recordCode", type); + queryBuilder.limit(200L); + PreparedQuery preparedQuery = queryBuilder.prepare(); + historyList = getDaoDanaRHistory().query(preparedQuery); + } catch (SQLException e) { + e.printStackTrace(); + historyList = new ArrayList<>(); + } + return historyList; + } + + public void updateDanaRHistoryRecordId(JSONObject trJson) { + try { + QueryBuilder queryBuilder = getDaoDanaRHistory().queryBuilder(); + Where where = queryBuilder.where(); + where.ge("bytes", trJson.get(DanaRNSHistorySync.DANARSIGNATURE)); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoDanaRHistory().query(preparedQuery); + if (list.size() == 0) { + // Record does not exists. Ignore + } else if (list.size() == 1) { + DanaRHistoryRecord record = list.get(0); + if (record._id == null || !record._id.equals(trJson.getString("_id"))) { + if (Config.logIncommingData) + log.debug("Updating _id in DanaR history database: " + trJson.getString("_id")); + record._id = trJson.getString("_id"); + getDaoDanaRHistory().update(record); + } else { + // already set + } + } + } catch (SQLException | JSONException e) { + e.printStackTrace(); + } + } + + // ------------ TemporaryBasal handling --------------- + + //return true if new record was created + public boolean createOrUpdate(TemporaryBasal tempBasal) { + try { + TemporaryBasal old; + tempBasal.date = roundDateToSec(tempBasal.date); + + if (tempBasal.source == Source.PUMP) { + // check for changed from pump change in NS + QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("pumpId", tempBasal.pumpId); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoTemporaryBasal().query(preparedQuery); + if (trList.size() > 0) { + // do nothing, pump history record cannot be changed + log.debug("TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); + return false; + } + getDaoTemporaryBasal().create(tempBasal); + log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); + updateEarliestDataChange(tempBasal.date); + scheduleTemporaryBasalChange(); + return true; + } + if (tempBasal.source == Source.NIGHTSCOUT) { + old = getDaoTemporaryBasal().queryForId(tempBasal.date); + if (old != null) { + if (!old.isEqual(tempBasal)) { + long oldDate = old.date; + getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too + old.copyFrom(tempBasal); + getDaoTemporaryBasal().create(old); + log.debug("TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString()); + updateEarliestDataChange(oldDate); + updateEarliestDataChange(old.date); + scheduleTemporaryBasalChange(); + return true; + } + return false; + } + // find by NS _id + if (tempBasal._id != null) { + QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", tempBasal._id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoTemporaryBasal().query(preparedQuery); + if (trList.size() > 0) { + old = trList.get(0); + if (!old.isEqual(tempBasal)) { + long oldDate = old.date; + getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too + old.copyFrom(tempBasal); + getDaoTemporaryBasal().create(old); + log.debug("TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString()); + updateEarliestDataChange(oldDate); + updateEarliestDataChange(old.date); + scheduleTemporaryBasalChange(); + return true; + } + } + } + getDaoTemporaryBasal().create(tempBasal); + log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); + updateEarliestDataChange(tempBasal.date); + scheduleTemporaryBasalChange(); + return true; + } + if (tempBasal.source == Source.USER) { + getDaoTemporaryBasal().create(tempBasal); + log.debug("TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); + updateEarliestDataChange(tempBasal.date); + scheduleTemporaryBasalChange(); + return true; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + public void delete(TemporaryBasal tempBasal) { + try { + getDaoTemporaryBasal().delete(tempBasal); + updateEarliestDataChange(tempBasal.date); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleTemporaryBasalChange(); + } + + public List getTemporaryBasalsDataFromTime(long mills, boolean ascending) { + try { + List tempbasals; + QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.ge("date", mills); + PreparedQuery preparedQuery = queryBuilder.prepare(); + tempbasals = getDaoTemporaryBasal().query(preparedQuery); return tempbasals; } catch (SQLException e) { e.printStackTrace(); } - return new ArrayList(); + return new ArrayList(); } + private static void scheduleTemporaryBasalChange() { + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing EventTempBasalChange"); + MainApp.bus().post(new EventReloadTempBasalData()); + MainApp.bus().post(new EventTempBasalChange()); + if (earliestDataChange != null) + MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); + earliestDataChange = null; + scheduledTemBasalsPost = null; + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (scheduledTemBasalsPost != null) + scheduledTemBasalsPost.cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + scheduledTemBasalsPost = tempBasalsWorker.schedule(task, sec, TimeUnit.SECONDS); + + } + + /* + { + "_id": "59232e1ddd032d04218dab00", + "eventType": "Temp Basal", + "duration": 60, + "percent": -50, + "created_at": "2017-05-22T18:29:57Z", + "enteredBy": "AndroidAPS", + "notes": "Basal Temp Start 50% 60.0 min", + "NSCLIENT_ID": 1495477797863, + "mills": 1495477797000, + "mgdl": 194.5, + "endmills": 1495481397000 + } + */ + + public void createTempBasalFromJsonIfNotExists(JSONObject trJson) { + try { + if (trJson.has("originalExtendedAmount")) { // extended bolus uploaded as temp basal + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.source = Source.NIGHTSCOUT; + extendedBolus.date = trJson.getLong("mills"); + extendedBolus.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; + extendedBolus.durationInMinutes = trJson.getInt("duration"); + extendedBolus.insulin = trJson.getDouble("originalExtendedAmount"); + extendedBolus._id = trJson.getString("_id"); + createOrUpdate(extendedBolus); + } else if (trJson.has("isFakedTempBasal")) { // extended bolus end uploaded as temp basal end + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.source = Source.NIGHTSCOUT; + extendedBolus.date = trJson.getLong("mills"); + extendedBolus.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; + extendedBolus.durationInMinutes = 0; + extendedBolus.insulin = 0; + extendedBolus._id = trJson.getString("_id"); + createOrUpdate(extendedBolus); + } else { + TemporaryBasal tempBasal = new TemporaryBasal(); + tempBasal.date = trJson.getLong("mills"); + tempBasal.source = Source.NIGHTSCOUT; + tempBasal.pumpId = trJson.has("pumpId") ? trJson.getLong("pumpId") : 0; + if (trJson.has("duration")) { + tempBasal.durationInMinutes = trJson.getInt("duration"); + } + if (trJson.has("percent")) { + tempBasal.percentRate = trJson.getInt("percent") + 100; + tempBasal.isAbsolute = false; + } + if (trJson.has("absolute")) { + tempBasal.absoluteRate = trJson.getDouble("absolute"); + tempBasal.isAbsolute = true; + } + tempBasal._id = trJson.getString("_id"); + createOrUpdate(tempBasal); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void deleteTempBasalById(String _id) { + TemporaryBasal stored = findTempBasalById(_id); + if (stored != null) { + log.debug("TEMPBASAL: Removing TempBasal record from database: " + stored.toString()); + delete(stored); + updateEarliestDataChange(stored.date); + scheduleTemporaryBasalChange(); + } + } + + public TemporaryBasal findTempBasalById(String _id) { + try { + QueryBuilder queryBuilder = null; + queryBuilder = getDaoTemporaryBasal().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", _id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoTemporaryBasal().query(preparedQuery); + + if (list.size() != 1) { + return null; + } else { + return list.get(0); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + // ------------ ExtendedBolus handling --------------- + + public boolean createOrUpdate(ExtendedBolus extendedBolus) { + try { + ExtendedBolus old; + extendedBolus.date = roundDateToSec(extendedBolus.date); + + if (extendedBolus.source == Source.PUMP) { + // check for changed from pump change in NS + QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("pumpId", extendedBolus.pumpId); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoExtendedBolus().query(preparedQuery); + if (trList.size() > 0) { + // do nothing, pump history record cannot be changed + return false; + } + getDaoExtendedBolus().create(extendedBolus); + log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.toString()); + updateEarliestDataChange(extendedBolus.date); + scheduleTreatmentChange(); + return true; + } + if (extendedBolus.source == Source.NIGHTSCOUT) { + old = getDaoExtendedBolus().queryForId(extendedBolus.date); + if (old != null) { + if (!old.isEqual(extendedBolus)) { + long oldDate = old.date; + getDaoExtendedBolus().delete(old); // need to delete/create because date may change too + old.copyFrom(extendedBolus); + getDaoExtendedBolus().create(old); + log.debug("EXTENDEDBOLUS: Updating record by date from: " + Source.getString(extendedBolus.source) + " " + old.toString()); + updateEarliestDataChange(oldDate); + updateEarliestDataChange(old.date); + scheduleTreatmentChange(); + return true; + } + return false; + } + // find by NS _id + if (extendedBolus._id != null) { + QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", extendedBolus._id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoExtendedBolus().query(preparedQuery); + if (trList.size() > 0) { + old = trList.get(0); + if (!old.isEqual(extendedBolus)) { + long oldDate = old.date; + getDaoExtendedBolus().delete(old); // need to delete/create because date may change too + old.copyFrom(extendedBolus); + getDaoExtendedBolus().create(old); + log.debug("EXTENDEDBOLUS: Updating record by _id from: " + Source.getString(extendedBolus.source) + " " + old.toString()); + updateEarliestDataChange(oldDate); + updateEarliestDataChange(old.date); + scheduleTreatmentChange(); + return true; + } + } + } + getDaoExtendedBolus().create(extendedBolus); + log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.toString()); + updateEarliestDataChange(extendedBolus.date); + scheduleTreatmentChange(); + return true; + } + if (extendedBolus.source == Source.USER) { + getDaoExtendedBolus().create(extendedBolus); + log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.toString()); + updateEarliestDataChange(extendedBolus.date); + scheduleTreatmentChange(); + return true; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + public void delete(ExtendedBolus extendedBolus) { + try { + getDaoExtendedBolus().delete(extendedBolus); + updateEarliestDataChange(extendedBolus.date); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleExtendedBolusChange(); + } + + public List getExtendedBolusDataFromTime(long mills, boolean ascending) { + try { + List extendedBoluses; + QueryBuilder queryBuilder = getDaoExtendedBolus().queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.ge("date", mills); + PreparedQuery preparedQuery = queryBuilder.prepare(); + extendedBoluses = getDaoExtendedBolus().query(preparedQuery); + return extendedBoluses; + } catch (SQLException e) { + e.printStackTrace(); + } + return new ArrayList(); + } + + public void deleteExtendedBolusById(String _id) { + ExtendedBolus stored = findExtendedBolusById(_id); + if (stored != null) { + log.debug("EXTENDEDBOLUS: Removing ExtendedBolus record from database: " + stored.toString()); + delete(stored); + updateEarliestDataChange(stored.date); + scheduleExtendedBolusChange(); + } + } + public ExtendedBolus findExtendedBolusById(String _id) { + try { + QueryBuilder queryBuilder = null; + queryBuilder = getDaoExtendedBolus().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", _id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoExtendedBolus().query(preparedQuery); + + if (list.size() == 1) { + return list.get(0); + } else { + return null; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /* +{ + "_id": "5924898d577eb0880e355337", + "eventType": "Combo Bolus", + "duration": 120, + "splitNow": 0, + "splitExt": 100, + "enteredinsulin": 1, + "relative": 1, + "created_at": "2017-05-23T19:12:14Z", + "enteredBy": "AndroidAPS", + "NSCLIENT_ID": 1495566734628, + "mills": 1495566734000, + "mgdl": 106 } + */ + + public void createExtendedBolusFromJsonIfNotExists(JSONObject trJson) { + try { + QueryBuilder queryBuilder = null; + queryBuilder = getDaoExtendedBolus().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills")); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoExtendedBolus().query(preparedQuery); + ExtendedBolus extendedBolus; + if (list.size() == 0) { + extendedBolus = new ExtendedBolus(); + extendedBolus.source = Source.NIGHTSCOUT; + if (Config.logIncommingData) + log.debug("Adding ExtendedBolus record to database: " + trJson.toString()); + // Record does not exists. add + } else if (list.size() == 1) { + extendedBolus = list.get(0); + if (Config.logIncommingData) + log.debug("Updating ExtendedBolus record in database: " + trJson.toString()); + } else { + log.error("Something went wrong"); + return; + } + extendedBolus.date = trJson.getLong("mills"); + extendedBolus.durationInMinutes = trJson.getInt("duration"); + extendedBolus.insulin = trJson.getDouble("relative"); + extendedBolus._id = trJson.getString("_id"); + createOrUpdate(extendedBolus); + } catch (SQLException | JSONException e) { + e.printStackTrace(); + } + } + + private static void scheduleExtendedBolusChange() { + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing EventExtendedBolusChange"); + MainApp.bus().post(new EventReloadTreatmentData()); + MainApp.bus().post(new EventExtendedBolusChange()); + if (earliestDataChange != null) + MainApp.bus().post(new EventNewHistoryData(earliestDataChange)); + earliestDataChange = null; + scheduledExtendedBolusPost = null; + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (scheduledExtendedBolusPost != null) + scheduledExtendedBolusPost.cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + scheduledExtendedBolusPost = extendedBolusWorker.schedule(task, sec, TimeUnit.SECONDS); + + } + + + // ------------ CareportalEvent handling --------------- + + public void createOrUpdate(CareportalEvent careportalEvent) { + careportalEvent.date = careportalEvent.date - careportalEvent.date % 1000; + try { + getDaoCareportalEvents().createOrUpdate(careportalEvent); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleCareportalEventChange(); + } + + public void delete(CareportalEvent careportalEvent) { + try { + getDaoCareportalEvents().delete(careportalEvent); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleCareportalEventChange(); + } + + @Nullable + public CareportalEvent getLastCareportalEvent(String event) { + try { + List careportalEvents; + QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder(); + queryBuilder.orderBy("date", false); + Where where = queryBuilder.where(); + where.eq("eventType", event); + queryBuilder.limit(1L); + PreparedQuery preparedQuery = queryBuilder.prepare(); + careportalEvents = getDaoCareportalEvents().query(preparedQuery); + if (careportalEvents.size() == 1) + return careportalEvents.get(0); + else + return null; + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + public List getCareportalEventsFromTime(long mills, boolean ascending) { + try { + List careportalEvents; + QueryBuilder queryBuilder = getDaoCareportalEvents().queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.ge("date", mills); + PreparedQuery preparedQuery = queryBuilder.prepare(); + careportalEvents = getDaoCareportalEvents().query(preparedQuery); + return careportalEvents; + } catch (SQLException e) { + e.printStackTrace(); + } + return new ArrayList(); + } + + public void deleteCareportalEventById(String _id) { + try { + QueryBuilder queryBuilder = null; + queryBuilder = getDaoCareportalEvents().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", _id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoCareportalEvents().query(preparedQuery); + + if (list.size() == 1) { + CareportalEvent record = list.get(0); + if (Config.logIncommingData) + log.debug("Removing CareportalEvent record from database: " + record.log()); + delete(record); + } else { + if (Config.logIncommingData) + log.debug("CareportalEvent not found database: " + _id); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public void createCareportalEventFromJsonIfNotExists(JSONObject trJson) { + try { + QueryBuilder queryBuilder = null; + queryBuilder = getDaoCareportalEvents().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", trJson.getString("_id")).or().eq("date", trJson.getLong("mills")); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoCareportalEvents().query(preparedQuery); + CareportalEvent careportalEvent; + if (list.size() == 0) { + careportalEvent = new CareportalEvent(); + careportalEvent.source = Source.NIGHTSCOUT; + if (Config.logIncommingData) + log.debug("Adding CareportalEvent record to database: " + trJson.toString()); + // Record does not exists. add + } else if (list.size() == 1) { + careportalEvent = list.get(0); + if (Config.logIncommingData) + log.debug("Updating CareportalEvent record in database: " + trJson.toString()); + } else { + log.error("Something went wrong"); + return; + } + careportalEvent.date = trJson.getLong("mills"); + careportalEvent.eventType = trJson.getString("eventType"); + careportalEvent.json = trJson.toString(); + careportalEvent._id = trJson.getString("_id"); + createOrUpdate(careportalEvent); + } catch (SQLException | JSONException e) { + e.printStackTrace(); + } + } + + private static void scheduleCareportalEventChange() { + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing scheduleCareportalEventChange"); + MainApp.bus().post(new EventCareportalEventChange()); + scheduledCareportalEventPost = null; + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (scheduledCareportalEventPost != null) + scheduledCareportalEventPost.cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + scheduledCareportalEventPost = careportalEventWorker.schedule(task, sec, TimeUnit.SECONDS); + + } + + // ---------------- ProfileSwitch handling --------------- + + public List getProfileSwitchData(boolean ascending) { + try { + Dao daoProfileSwitch = getDaoProfileSwitch(); + List profileSwitches; + QueryBuilder queryBuilder = daoProfileSwitch.queryBuilder(); + queryBuilder.orderBy("date", ascending); + queryBuilder.limit(20L); + PreparedQuery preparedQuery = queryBuilder.prepare(); + profileSwitches = daoProfileSwitch.query(preparedQuery); + return profileSwitches; + } catch (SQLException e) { + e.printStackTrace(); + } + return new ArrayList(); + } + + public boolean createOrUpdate(ProfileSwitch profileSwitch) { + try { + ProfileSwitch old; + profileSwitch.date = roundDateToSec(profileSwitch.date); + + if (profileSwitch.source == Source.NIGHTSCOUT) { + old = getDaoProfileSwitch().queryForId(profileSwitch.date); + if (old != null) { + if (!old.isEqual(profileSwitch)) { + getDaoProfileSwitch().delete(old); // need to delete/create because date may change too + old.copyFrom(profileSwitch); + getDaoProfileSwitch().create(old); + log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString()); + scheduleTemporaryTargetChange(); + return true; + } + return false; + } + // find by NS _id + if (profileSwitch._id != null) { + QueryBuilder queryBuilder = getDaoProfileSwitch().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", profileSwitch._id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List trList = getDaoProfileSwitch().query(preparedQuery); + if (trList.size() > 0) { + old = trList.get(0); + if (!old.isEqual(profileSwitch)) { + getDaoProfileSwitch().delete(old); // need to delete/create because date may change too + old.copyFrom(profileSwitch); + getDaoProfileSwitch().create(old); + log.debug("PROFILESWITCH: Updating record by _id from: " + Source.getString(profileSwitch.source) + " " + old.toString()); + scheduleTemporaryTargetChange(); + return true; + } + } + } + getDaoProfileSwitch().create(profileSwitch); + log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); + scheduleTemporaryTargetChange(); + return true; + } + if (profileSwitch.source == Source.USER) { + getDaoProfileSwitch().create(profileSwitch); + log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); + scheduleTemporaryTargetChange(); + return true; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + + public void delete(ProfileSwitch profileSwitch) { + try { + getDaoProfileSwitch().delete(profileSwitch); + scheduleProfileSwitchChange(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private static void scheduleProfileSwitchChange() { + class PostRunnable implements Runnable { + public void run() { + log.debug("Firing EventProfileSwitchChange"); + MainApp.bus().post(new EventProfileSwitchChange()); + scheduledProfileSwitchEventPost = null; + } + } + // prepare task for execution in 1 sec + // cancel waiting task to prevent sending multiple posts + if (scheduledProfileSwitchEventPost != null) + scheduledProfileSwitchEventPost.cancel(false); + Runnable task = new PostRunnable(); + final int sec = 1; + scheduledProfileSwitchEventPost = profileSwitchEventWorker.schedule(task, sec, TimeUnit.SECONDS); + + } + + /* +{ + "_id":"592fa43ed97496a80da913d2", + "created_at":"2017-06-01T05:20:06Z", + "eventType":"Profile Switch", + "profile":"2016 +30%", + "units":"mmol", + "enteredBy":"sony", + "NSCLIENT_ID":1496294454309, +} + */ + + public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) { + try { + ProfileSwitch profileSwitch = new ProfileSwitch(); + profileSwitch.date = trJson.getLong("mills"); + if (trJson.has("duration")) + profileSwitch.durationInMinutes = trJson.getInt("duration"); + profileSwitch._id = trJson.getString("_id"); + profileSwitch.profileName = trJson.getString("profile"); + profileSwitch.isCPP = trJson.has("CircadianPercentageProfile"); + profileSwitch.source = Source.NIGHTSCOUT; + if (trJson.has("timeshift")) + profileSwitch.timeshift = trJson.getInt("timeshift"); + if (trJson.has("percentage")) + profileSwitch.percentage = trJson.getInt("percentage"); + if (trJson.has("profileJson")) + profileSwitch.profileJson = trJson.getString("profileJson"); + if (trJson.has("profilePlugin")) + profileSwitch.profilePlugin = trJson.getString("profilePlugin"); + createOrUpdate(profileSwitch); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void deleteProfileSwitchById(String _id) { + ProfileSwitch stored = findProfileSwitchById(_id); + if (stored != null) { + log.debug("PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString()); + delete(stored); + scheduleTemporaryTargetChange(); + } + } + + public ProfileSwitch findProfileSwitchById(String _id) { + try { + QueryBuilder queryBuilder = getDaoProfileSwitch().queryBuilder(); + Where where = queryBuilder.where(); + where.eq("_id", _id); + PreparedQuery preparedQuery = queryBuilder.prepare(); + List list = getDaoProfileSwitch().query(preparedQuery); + + if (list.size() == 1) { + return list.get(0); + } else { + return null; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/db/DbRequest.java b/app/src/main/java/info/nightscout/androidaps/db/DbRequest.java index 0ecc5d4f32..203436661c 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DbRequest.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DbRequest.java @@ -19,15 +19,7 @@ import org.slf4j.LoggerFactory; public class DbRequest { private static Logger log = LoggerFactory.getLogger(DbRequest.class); - public String getNsClientID() { - return nsClientID; - } - - public void setNsClientID(String nsClientID) { - this.nsClientID = nsClientID; - } - - @DatabaseField(id = true, useGetSet = true) + @DatabaseField(id = true) public String nsClientID = null; @DatabaseField diff --git a/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java new file mode 100644 index 0000000000..d422a94211 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -0,0 +1,287 @@ +package info.nightscout.androidaps.db; + +/** + * Created by mike on 21.05.2017. + */ + +import android.graphics.Color; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.Objects; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.Interval; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +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.DecimalFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 21.05.2017. + */ + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_EXTENDEDBOLUSES) +public class ExtendedBolus implements Interval, DataPointWithLabelInterface { + private static Logger log = LoggerFactory.getLogger(ExtendedBolus.class); + + @DatabaseField(id = true) + public long date; + + @DatabaseField + public boolean isValid = true; + + @DatabaseField(index = true) + public long pumpId = 0; + + @DatabaseField + public int source = Source.NONE; + @DatabaseField + public String _id = null; // NS _id + + @DatabaseField + public double insulin = 0d; + @DatabaseField + public int durationInMinutes = 0; // duration == 0 means end of extended bolus + + @DatabaseField + public int insulinInterfaceID = InsulinInterface.FASTACTINGINSULIN; + @DatabaseField + public double dia = Constants.defaultDIA; + + public ExtendedBolus() { + } + + public ExtendedBolus(long date) { + this.date = date; + } + + public boolean isEqual(ExtendedBolus other) { + if (date != other.date) { + return false; + } + if (durationInMinutes != other.durationInMinutes) + return false; + if (insulin != other.insulin) + return false; + if (pumpId != other.pumpId) + return false; + if (!Objects.equals(_id, other._id)) + return false; + return true; + } + + public void copyFrom(ExtendedBolus t) { + date = t.date; + _id = t._id; + durationInMinutes = t.durationInMinutes; + insulin = t.insulin; + pumpId = t.pumpId; + } + + // -------- Interval interface --------- + + Long cuttedEnd = null; + + public long durationInMsec() { + return durationInMinutes * 60 * 1000L; + } + + public long start() { + return date; + } + + // planned end time at time of creation + public long originalEnd() { + return date + durationInMinutes * 60 * 1000L; + } + + // end time after cut + public long end() { + if (cuttedEnd != null) + return cuttedEnd; + return originalEnd(); + } + + public void cutEndTo(long end) { + cuttedEnd = end; + } + + public boolean match(long time) { + if (start() <= time && end() >= time) + return true; + return false; + } + + public boolean before(long time) { + if (end() < time) + return true; + return false; + } + + public boolean after(long time) { + if (start() > time) + return true; + return false; + } + + @Override + public boolean isInProgress() { + return match(new Date().getTime()); + } + + @Override + public boolean isEndingEvent() { + return durationInMinutes == 0; + } + + // -------- Interval interface end --------- + + public String log() { + return "Bolus{" + + "date= " + date + + ", date= " + DateUtil.dateAndTimeString(date) + + ", isValid=" + isValid + + ", _id= " + _id + + ", pumpId= " + pumpId + + ", insulin= " + insulin + + ", durationInMinutes= " + durationInMinutes + + "}"; + } + + public double absoluteRate() { + return Round.roundTo(insulin / durationInMinutes * 60, 0.01); + } + + public double insulinSoFar() { + return absoluteRate() * getRealDuration() / 60d; + } + + public IobTotal iobCalc(long time) { + IobTotal result = new IobTotal(time); + Profile profile = MainApp.getConfigBuilder().getProfile(time); + InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); + + if (profile == null) + return result; + + int realDuration = getDurationToTime(time); + + if (realDuration > 0) { + Double dia_ago = time - profile.getDia() * 60 * 60 * 1000; + int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); + double spacing = realDuration / aboutFiveMinIntervals; + + for (Long j = 0L; j < aboutFiveMinIntervals; j++) { + // find middle of the interval + Long calcdate = (long) (date + j * spacing * 60 * 1000 + 0.5d * spacing * 60 * 1000); + + if (calcdate > dia_ago && calcdate <= time) { + double tempBolusSize = absoluteRate() * spacing / 60d; + + Treatment tempBolusPart = new Treatment(insulinInterface); + tempBolusPart.insulin = tempBolusSize; + tempBolusPart.date = calcdate; + + Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, profile.getDia()); + result.iob += aIOB.iobContrib; + result.activity += aIOB.activityContrib; + result.extendedBolusInsulin += tempBolusPart.insulin; + } + } + } + return result; + } + + public int getRealDuration() { + return getDurationToTime(new Date().getTime()); + } + + private int getDurationToTime(long time) { + long endTime = Math.min(time, end()); + long msecs = endTime - date; + return Math.round(msecs / 60f / 1000); + } + + public int getPlannedRemainingMinutes() { + float remainingMin = (end() - new Date().getTime()) / 1000f / 60; + return (remainingMin < 0) ? 0 : Math.round(remainingMin); + } + + public String toString() { + return "E " + DecimalFormatter.to2Decimal(absoluteRate()) + "U/h @" + + DateUtil.timeString(date) + + " " + getRealDuration() + "/" + durationInMinutes + "min"; + } + + public String toStringShort() { + return "E " + DecimalFormatter.to2Decimal(absoluteRate()) + "U/h "; + } + + public String toStringMedium() { + return "E " + DecimalFormatter.to2Decimal(absoluteRate()) + "U/h (" + + getRealDuration() + "/" + durationInMinutes + ") "; + } + + public String toStringTotal() { + return DecimalFormatter.to2Decimal(insulin) + "U ( " + + DecimalFormatter.to2Decimal(absoluteRate()) + " U/h )"; + } + + // -------- DataPointWithLabelInterface -------- + @Override + public double getX() { + return date; + } + + // default when no sgv around available + private double yValue = 0; + + + @Override + public double getY() { + return yValue; + } + + @Override + public void setY(double y) { + yValue = y; + } + + @Override + public String getLabel() { + return toStringTotal(); + } + + @Override + public long getDuration() { + return durationInMinutes * 60 * 1000L; + } + + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + return PointsWithLabelGraphSeries.Shape.EXTENDEDBOLUS; + } + + @Override + public float getSize() { + return 10; + } + + @Override + public int getColor() { + return Color.CYAN; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java new file mode 100644 index 0000000000..448f6cdd51 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java @@ -0,0 +1,202 @@ +package info.nightscout.androidaps.db; + +import android.graphics.Color; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.Objects; + +import info.nightscout.androidaps.interfaces.Interval; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.utils.DateUtil; + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES) +public class ProfileSwitch implements Interval, DataPointWithLabelInterface { + private static Logger log = LoggerFactory.getLogger(ProfileSwitch.class); + + @DatabaseField(id = true) + public long date; + + @DatabaseField + public boolean isValid = true; + + @DatabaseField + public int source = Source.NONE; + @DatabaseField + public String _id = null; // NS _id + + @DatabaseField + public boolean isCPP = false; // CPP NS="CircadianPercentageProfile" + @DatabaseField + public int timeshift = 0; // CPP NS="timeshift" + @DatabaseField + public int percentage = 100; // CPP NS="percentage" + + @DatabaseField + public String profileName = null; + + @DatabaseField + public String profileJson = null; + + @DatabaseField + public String profilePlugin = null; // NSProfilePlugin.class.getName(); + + @DatabaseField + public int durationInMinutes = 0; + + public boolean isEqual(ProfileSwitch other) { + if (date != other.date) { + return false; + } + if (durationInMinutes != other.durationInMinutes) + return false; + if (percentage != other.percentage) + return false; + if (timeshift != other.timeshift) + return false; + if (isCPP != other.isCPP) + return false; + if (!Objects.equals(_id, other._id)) + return false; + if (!Objects.equals(profilePlugin, other.profilePlugin)) + return false; + if (!Objects.equals(profileJson, other.profileJson)) + return false; + if (!Objects.equals(profileName, other.profileName)) + return false; + return true; + } + + public void copyFrom(ProfileSwitch t) { + date = t.date; + _id = t._id; + durationInMinutes = t.durationInMinutes; + percentage = t.percentage; + timeshift = t.timeshift; + isCPP = t.isCPP; + profilePlugin = t.profilePlugin; + profileJson = t.profileJson; + profileName = t.profileName; + } + + // -------- Interval interface --------- + + Long cuttedEnd = null; + + public long durationInMsec() { + return durationInMinutes * 60 * 1000L; + } + + public long start() { + return date; + } + + // planned end time at time of creation + public long originalEnd() { + return date + durationInMinutes * 60 * 1000L; + } + + // end time after cut + public long end() { + if (cuttedEnd != null) + return cuttedEnd; + return originalEnd(); + } + + public void cutEndTo(long end) { + cuttedEnd = end; + } + + public boolean match(long time) { + if (start() <= time && end() >= time) + return true; + return false; + } + + public boolean before(long time) { + if (end() < time) + return true; + return false; + } + + public boolean after(long time) { + if (start() > time) + return true; + return false; + } + + @Override + public boolean isInProgress() { + return match(new Date().getTime()); + } + + @Override + public boolean isEndingEvent() { + return durationInMinutes == 0; + } + + // -------- Interval interface end --------- + + // ----------------- DataPointInterface -------------------- + @Override + public double getX() { + return date; + } + + // default when no sgv around available + private double yValue = 0; + + @Override + public double getY() { + return yValue; + } + + @Override + public void setY(double y) { + yValue = y; + } + + @Override + public String getLabel() { + return profileName; + } + + @Override + public long getDuration() { + return 0; + } + + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + return PointsWithLabelGraphSeries.Shape.PROFILE; + } + + @Override + public float getSize() { + return 10; + } + + @Override + public int getColor() { + return Color.CYAN; + } + + public String log() { + return "ProfileSwitch{" + + "date=" + date + + "date=" + DateUtil.dateAndTimeString(date) + + ", isValid=" + isValid + + ", duration=" + durationInMinutes + + ", profileName=" + profileName + + ", percentage=" + percentage + + ", timeshift=" + timeshift + + '}'; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/db/Source.java b/app/src/main/java/info/nightscout/androidaps/db/Source.java new file mode 100644 index 0000000000..c126794769 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/Source.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.db; + +/** + * Created by mike on 21.05.2017. + */ + +public class Source { + public final static int NONE = 0; + public final static int PUMP = 1; // Pump history + public final static int NIGHTSCOUT = 2; // created in NS + public final static int USER = 3; // created by user or driver not using history + + public static String getString(int source) { + switch (source) { + case PUMP: + return "PUMP"; + case NIGHTSCOUT: + return "NIGHTSCOUT"; + case USER: + return "USER"; + } + return "NONE"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java deleted file mode 100644 index 149d188b7c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java +++ /dev/null @@ -1,230 +0,0 @@ -package info.nightscout.androidaps.db; - -import com.j256.ormlite.field.DatabaseField; -import com.j256.ormlite.table.DatabaseTable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Date; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; - -@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPBASALS) -public class TempBasal { - private static Logger log = LoggerFactory.getLogger(TempBasal.class); - - public long getTimeIndex() { - return timeStart.getTime(); - } - - public void setTimeIndex(long timeIndex) { - this.timeIndex = timeIndex; - } - - @DatabaseField(id = true, useGetSet = true) - public long timeIndex; - - @DatabaseField - public Date timeStart; - - @DatabaseField - public Date timeEnd; - - @DatabaseField - public int percent; // In % of current basal. 100% == current basal - - @DatabaseField - public Double absolute; // Absolute value in U - - @DatabaseField - public int duration; // in minutes - - @DatabaseField - public boolean isExtended = false; // true if set as extended bolus - - @DatabaseField - public boolean isAbsolute = false; // true if if set as absolute value in U - - - public IobTotal iobCalc(Date time) { - IobTotal result = new IobTotal(time.getTime()); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - - if (profile == null) - return result; - - Double basalRate = profile.getBasal(profile.secondsFromMidnight(time)); - - if (basalRate == null) - return result; - - int realDuration = getRealDuration(); - - if (realDuration > 0) { - Double netBasalRate = 0d; - Double tempBolusSize = 0.05; - - if (isExtended) { - netBasalRate = this.absolute; - } else { - if (this.isAbsolute) { - netBasalRate = this.absolute - basalRate; - } else { - netBasalRate = (this.percent - 100) / 100d * basalRate; - } - } - - result.netRatio = netBasalRate; - Double netBasalAmount = Math.round(netBasalRate * realDuration * 10 / 6) / 100d; - result.netInsulin = netBasalAmount; - if (netBasalAmount < 0.1) { - tempBolusSize = 0.01; - } - if (netBasalRate < 0) { - tempBolusSize = -tempBolusSize; - } - Long tempBolusCount = Math.round(netBasalAmount / tempBolusSize); - if (tempBolusCount > 0) { - Long tempBolusSpacing = realDuration / tempBolusCount; - for (Long j = 0l; j < tempBolusCount; j++) { - Treatment tempBolusPart = new Treatment(); - tempBolusPart.insulin = tempBolusSize; - Long date = this.timeStart.getTime() + j * tempBolusSpacing * 60 * 1000; - tempBolusPart.created_at = new Date(date); - - Iob aIOB = tempBolusPart.iobCalc(time, profile.getDia()); - result.basaliob += aIOB.iobContrib; - result.activity += aIOB.activityContrib; - Double dia_ago = time.getTime() - profile.getDia() * 60 * 60 * 1000; - if (date > dia_ago && date <= time.getTime()) { - result.netbasalinsulin += tempBolusPart.insulin; - if (tempBolusPart.insulin > 0) { - result.hightempinsulin += tempBolusPart.insulin; - } - } - } - } - } - return result; - } - - // Determine end of basal - public Date getTimeEnd() { - Date tempBasalTimePlannedEnd = getPlannedTimeEnd(); - Date now = new Date(); - - if (timeEnd != null && timeEnd.getTime() < tempBasalTimePlannedEnd.getTime()) { - tempBasalTimePlannedEnd = timeEnd; - } - - if (now.getTime() < tempBasalTimePlannedEnd.getTime()) - tempBasalTimePlannedEnd = now; - - return tempBasalTimePlannedEnd; - } - - public Date getPlannedTimeEnd() { - return new Date(timeStart.getTime() + 60 * 1_000 * duration); - } - - public int getRealDuration() { - Long msecs = getTimeEnd().getTime() - timeStart.getTime(); - return Math.round(msecs / 60f / 1000); - } - - public long getMillisecondsFromStart() { - return new Date().getTime() - timeStart.getTime(); - } - - public int getPlannedRemainingMinutes() { - if (timeEnd != null) return 0; - float remainingMin = (getPlannedTimeEnd().getTime() - new Date().getTime()) / 1000f / 60; - return (remainingMin < 0) ? 0 : Math.round(remainingMin); - } - - public boolean isInProgress() { - return isInProgress(new Date()); - } - - public double tempBasalConvertedToAbsolute(Date time) { - if (isExtended) { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - double absval = profile.getBasal(NSProfile.secondsFromMidnight(time)) + absolute; - return absval; - } else { - if (isAbsolute) return absolute; - else { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - double absval = profile.getBasal(NSProfile.secondsFromMidnight(time)) * percent / 100; - return absval; - } - } - } - - public boolean isInProgress(Date time) { - if (timeStart.getTime() > time.getTime()) return false; // in the future - if (timeEnd == null) { // open end - if (timeStart.getTime() < time.getTime() && getPlannedTimeEnd().getTime() > time.getTime()) - return true; // in interval - return false; - } - // closed end - if (timeStart.getTime() < time.getTime() && timeEnd.getTime() > time.getTime()) return true; // in interval - return false; - } - - public String log() { - return "TempBasal{" + - "timeIndex=" + timeIndex + - ", timeStart=" + timeStart + - ", timeEnd=" + timeEnd + - ", percent=" + percent + - ", absolute=" + absolute + - ", duration=" + duration + - ", isAbsolute=" + isAbsolute + - ", isExtended=" + isExtended + - '}'; - } - - public String toString() { - String extended = isExtended ? "E " : ""; - - if (isAbsolute) { - return extended + DecimalFormatter.to2Decimal(absolute) + "U/h @" + - DateUtil.timeString(timeStart) + - " " + getRealDuration() + "/" + duration + "min"; - } else { // percent - return percent + "% @" + - DateUtil.timeString(timeStart) + - " " + getRealDuration() + "/" + duration + "min"; - } - } - - public String toStringShort() { - String extended = isExtended ? "E" : ""; - - if (isAbsolute) { - return extended + DecimalFormatter.to2Decimal(absolute) + "U/h "; - } else { // percent - return percent + "% "; - } - } - - public String toStringMedium() { - String extended = isExtended ? "E" : ""; - - if (isAbsolute) { - return extended + DecimalFormatter.to2Decimal(absolute) + "U/h (" - + getRealDuration() + "/" + duration + ") "; - } else { // percent - return percent + "% (" + getRealDuration() + "/" + duration + ") "; - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java index 051a1d3d40..7afe994437 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/db/TempTarget.java @@ -7,29 +7,27 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; +import java.util.Objects; import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; +import info.nightscout.androidaps.interfaces.Interval; +import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPTARGETS) -public class TempTarget { +public class TempTarget implements Interval { private static Logger log = LoggerFactory.getLogger(TempTarget.class); - public long getTimeIndex() { - return timeStart.getTime() - timeStart.getTime() % 1000; - } - - public void setTimeIndex(long timeIndex) { - this.timeIndex = timeIndex; - } - - @DatabaseField(id = true, useGetSet = true) - public long timeIndex; + @DatabaseField(id = true) + public long date; @DatabaseField - public Date timeStart; + public boolean isValid = true; + + @DatabaseField + public int source = Source.NONE; + @DatabaseField + public String _id = null; // NS _id @DatabaseField public double low; // in mgdl @@ -41,15 +39,92 @@ public class TempTarget { public String reason; @DatabaseField - public int duration; // in minutes + public int durationInMinutes; - @DatabaseField - public String _id; // NS _id - - public Date getPlannedTimeEnd() { - return new Date(timeStart.getTime() + 60 * 1_000 * duration); + public boolean isEqual(TempTarget other) { + if (date != other.date) { + return false; + } + if (durationInMinutes != other.durationInMinutes) + return false; + if (low != other.low) + return false; + if (high != other.high) + return false; + if (reason != other.reason) + return false; + if (!Objects.equals(_id, other._id)) + return false; + return true; } + public void copyFrom(TempTarget t) { + date = t.date; + _id = t._id; + durationInMinutes = t.durationInMinutes; + low = t.low; + high = t.high; + reason = t.reason; + } + + // -------- Interval interface --------- + + Long cuttedEnd = null; + + public long durationInMsec() { + return durationInMinutes * 60 * 1000L; + } + + public long start() { + return date; + } + + // planned end time at time of creation + public long originalEnd() { + return date + durationInMinutes * 60 * 1000L; + } + + // end time after cut + public long end() { + if (cuttedEnd != null) + return cuttedEnd; + return originalEnd(); + } + + public void cutEndTo(long end) { + cuttedEnd = end; + } + + public boolean match(long time) { + if (start() <= time && end() >= time) + return true; + return false; + } + + public boolean before(long time) { + if (end() < time) + return true; + return false; + } + + public boolean after(long time) { + if (start() > time) + return true; + return false; + } + + @Override + public boolean isInProgress() { + return match(new Date().getTime()); + } + + @Override + public boolean isEndingEvent() { + return durationInMinutes == 0; + } + + // -------- Interval interface end --------- + public String lowValueToUnitsToString(String units) { if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(low); else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL); @@ -60,15 +135,12 @@ public class TempTarget { else return DecimalFormatter.to1Decimal(low * Constants.MGDL_TO_MMOLL); } - public boolean isInProgress() { - return ((TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class)).getTempTargetInProgress(new Date().getTime()) == this; - } - - public String log() { - return "TempTarget{" + - "timeIndex=" + timeIndex + - ", timeStart=" + timeStart + - ", duration=" + duration + + public String toString() { + return "TemporaryTarget{" + + "date=" + date + + "date=" + DateUtil.dateAndTimeString(date) + + ", isValid=" + isValid + + ", duration=" + durationInMinutes + ", reason=" + reason + ", low=" + low + ", high=" + high + diff --git a/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java new file mode 100644 index 0000000000..4bf668411d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -0,0 +1,289 @@ +package info.nightscout.androidaps.db; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.Objects; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.Interval; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; + +/** + * Created by mike on 21.05.2017. + */ + +@DatabaseTable(tableName = DatabaseHelper.DATABASE_TEMPORARYBASALS) +public class TemporaryBasal implements Interval { + private static Logger log = LoggerFactory.getLogger(TemporaryBasal.class); + + @DatabaseField(id = true) + public long date; + + @DatabaseField + public boolean isValid = true; + + @DatabaseField(index = true) + public long pumpId = 0; + + @DatabaseField + public int source = Source.NONE; + @DatabaseField + public String _id = null; // NS _id + + @DatabaseField + public int durationInMinutes = 0; // duration == 0 means end of temp basal + @DatabaseField + public boolean isAbsolute = false; + @DatabaseField + public int percentRate = 0; + @DatabaseField + public double absoluteRate = 0d; + + public TemporaryBasal() { + } + + public TemporaryBasal(long date) { + this.date = date; + } + + public TemporaryBasal(ExtendedBolus extendedBolus) { + double basal = MainApp.getConfigBuilder().getProfile(extendedBolus.date).getBasal(extendedBolus.date); + this.date = extendedBolus.date; + this.isValid = extendedBolus.isValid; + this.source = extendedBolus.source; + this._id = extendedBolus._id; + this.durationInMinutes = extendedBolus.durationInMinutes; + this.isAbsolute = true; + this.absoluteRate = basal + extendedBolus.absoluteRate(); + } + + public TemporaryBasal clone() { + TemporaryBasal t = new TemporaryBasal(); + t.date = date; + t.isValid = isValid; + t.source = source; + t._id = _id; + t.pumpId = pumpId; + t.durationInMinutes = durationInMinutes; + t.isAbsolute = isAbsolute; + t.percentRate = percentRate; + t.absoluteRate = absoluteRate; + return t; + } + + public boolean isEqual(TemporaryBasal other) { + if (date != other.date) { + return false; + } + if (durationInMinutes != other.durationInMinutes) + return false; + if (isAbsolute != other.isAbsolute) + return false; + if (percentRate != other.percentRate) + return false; + if (absoluteRate != other.absoluteRate) + return false; + if (pumpId != other.pumpId) + return false; + if (!Objects.equals(_id, other._id)) + return false; + return true; + } + + public void copyFrom(TemporaryBasal t) { + date = t.date; + _id = t._id; + durationInMinutes = t.durationInMinutes; + isAbsolute = t.isAbsolute; + percentRate = t.percentRate; + absoluteRate = t.absoluteRate; + pumpId = t.pumpId; + } + + // -------- Interval interface --------- + + Long cuttedEnd = null; + + public long durationInMsec() { + return durationInMinutes * 60 * 1000L; + } + + public long start() { + return date; + } + + // planned end time at time of creation + public long originalEnd() { + return date + durationInMinutes * 60 * 1000L; + } + + // end time after cut + public long end() { + if (cuttedEnd != null) + return cuttedEnd; + return originalEnd(); + } + + public void cutEndTo(long end) { + cuttedEnd = end; + } + + public boolean match(long time) { + if (start() <= time && end() >= time) + return true; + return false; + } + + public boolean before(long time) { + if (end() < time) + return true; + return false; + } + + public boolean after(long time) { + if (start() > time) + return true; + return false; + } + + @Override + public boolean isInProgress() { + return match(new Date().getTime()); + } + + @Override + public boolean isEndingEvent() { + return durationInMinutes == 0; + } + + // -------- Interval interface end --------- + + public IobTotal iobCalc(long time) { + IobTotal result = new IobTotal(time); + Profile profile = MainApp.getConfigBuilder().getProfile(time); + InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); + + int realDuration = getDurationToTime(time); + Double netBasalAmount = 0d; + + if (realDuration > 0) { + Double netBasalRate = 0d; + + Double dia_ago = time - profile.getDia() * 60 * 60 * 1000; + int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); + double tempBolusSpacing = realDuration / aboutFiveMinIntervals; + + for (Long j = 0L; j < aboutFiveMinIntervals; j++) { + // find middle of the interval + Long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000); + + Double basalRate = profile.getBasal(calcdate); + + if (basalRate == null) + continue; + if (isAbsolute) { + netBasalRate = absoluteRate - basalRate; + } else { + netBasalRate = (percentRate - 100) / 100d * basalRate; + } + + if (calcdate > dia_ago && calcdate <= time) { + double tempBolusSize = netBasalRate * tempBolusSpacing / 60d; + netBasalAmount += tempBolusSize; + + Treatment tempBolusPart = new Treatment(insulinInterface); + tempBolusPart.insulin = tempBolusSize; + tempBolusPart.date = calcdate; + + Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, profile.getDia()); + result.basaliob += aIOB.iobContrib; + result.activity += aIOB.activityContrib; + result.netbasalinsulin += tempBolusPart.insulin; + if (tempBolusPart.insulin > 0) { + result.hightempinsulin += tempBolusPart.insulin; + } + } + result.netRatio = netBasalRate; // ratio at the end of interval + } + } + result.netInsulin = netBasalAmount; + return result; + } + + public int getRealDuration() { + return getDurationToTime(new Date().getTime()); + } + + private int getDurationToTime(long time) { + long endTime = Math.min(time, end()); + long msecs = endTime - date; + return Math.round(msecs / 60f / 1000); + } + + public int getPlannedRemainingMinutes() { + float remainingMin = (end() - new Date().getTime()) / 1000f / 60; + return (remainingMin < 0) ? 0 : Math.round(remainingMin); + } + + public double tempBasalConvertedToAbsolute(long time) { + if (isAbsolute) return absoluteRate; + else { + return MainApp.getConfigBuilder().getProfile(time).getBasal(time) * percentRate / 100; + } + } + + public String toString() { + return "TemporaryBasal{" + + "date=" + date + + ", date=" + DateUtil.dateAndTimeString(date) + + ", isValid=" + isValid + + ", pumpId=" + pumpId + + ", _id=" + _id + + ", percentRate=" + percentRate + + ", absoluteRate=" + absoluteRate + + ", durationInMinutes=" + durationInMinutes + + ", isAbsolute=" + isAbsolute + + '}'; + } + + public String toStringFull() { + if (isAbsolute) { + return DecimalFormatter.to2Decimal(absoluteRate) + "U/h @" + + DateUtil.timeString(date) + + " " + getRealDuration() + "/" + durationInMinutes + "min"; + } else { // percent + return percentRate + "% @" + + DateUtil.timeString(date) + + " " + getRealDuration() + "/" + durationInMinutes + "min"; + } + } + + public String toStringShort() { + if (isAbsolute) { + return DecimalFormatter.to2Decimal(absoluteRate) + "U/h "; + } else { // percent + return percentRate + "% "; + } + } + + public String toStringMedium() { + if (isAbsolute) { + return DecimalFormatter.to2Decimal(absoluteRate) + "U/h (" + + getRealDuration() + "/" + durationInMinutes + ") "; + } else { // percent + return percentRate + "% (" + getRealDuration() + "/" + durationInMinutes + ") "; + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java b/app/src/main/java/info/nightscout/androidaps/db/Treatment.java index a8afacd767..e386a195b8 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java +++ b/app/src/main/java/info/nightscout/androidaps/db/Treatment.java @@ -1,21 +1,25 @@ package info.nightscout.androidaps.db; +import android.graphics.Color; + import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; -import org.json.JSONException; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; import java.util.List; +import java.util.Objects; +import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -23,85 +27,102 @@ import info.nightscout.utils.DecimalFormatter; public class Treatment implements DataPointWithLabelInterface { private static Logger log = LoggerFactory.getLogger(Treatment.class); - public long getTimeIndex() { - return created_at.getTime(); - } + @DatabaseField(id = true) + public long date; - public void setTimeIndex(long timeIndex) { - this.timeIndex = timeIndex; - } + @DatabaseField + public boolean isValid = true; - @DatabaseField(id = true, useGetSet = true) - public long timeIndex; + @DatabaseField(index = true) + public long pumpId = 0; + @DatabaseField + public int source = Source.NONE; @DatabaseField public String _id; @DatabaseField - public Date created_at; - + public double insulin = 0d; @DatabaseField - public Double insulin = 0d; - - @DatabaseField - public Double carbs = 0d; - + public double carbs = 0d; @DatabaseField public boolean mealBolus = true; // true for meal bolus , false for correction bolus - public void copyFrom(Treatment t) { - this._id = t._id; - this.created_at = t.created_at; - this.insulin = t.insulin; - this.carbs = t.carbs; - this.mealBolus = t.mealBolus; + @DatabaseField + public int insulinInterfaceID = InsulinInterface.FASTACTINGINSULIN; + @DatabaseField + public double dia = Constants.defaultDIA; + + public Treatment() { } - public Iob iobCalc(Date time, Double dia) { - Iob result = new Iob(); + public Treatment(long date) { + this.date = date; + } - Double scaleFactor = 3.0 / dia; - Double peak = 75d; - Double end = 180d; - - if (this.insulin != 0d) { - Long bolusTime = this.created_at.getTime(); - Double minAgo = scaleFactor * (time.getTime() - bolusTime) / 1000d / 60d; - - if (minAgo < peak) { - Double x1 = minAgo / 5d + 1; - result.iobContrib = this.insulin * (1 - 0.001852 * x1 * x1 + 0.001852 * x1); - // units: BG (mg/dL) = (BG/U) * U insulin * scalar - result.activityContrib = this.insulin * (2 / dia / 60 / peak) * minAgo; - - } else if (minAgo < end) { - Double x2 = (minAgo - 75) / 5; - result.iobContrib = this.insulin * (0.001323 * x2 * x2 - 0.054233 * x2 + 0.55556); - result.activityContrib = this.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * 3 - peak)); - } - } - return result; + public Treatment(InsulinInterface insulin) { + insulinInterfaceID = insulin.getId(); + dia = insulin.getDia(); } public long getMillisecondsFromStart() { - return new Date().getTime() - created_at.getTime(); + return new Date().getTime() - date; } - public String log() { + public String toString() { return "Treatment{" + - "timeIndex: " + timeIndex + - ", _id: " + _id + - ", insulin: " + insulin + - ", carbs: " + carbs + - ", mealBolus: " + mealBolus + - ", created_at: " + + "date= " + date + + ", date= " + DateUtil.dateAndTimeString(date) + + ", isValid= " + isValid + + ", _id= " + _id + + ", pumpId= " + pumpId + + ", insulin= " + insulin + + ", carbs= " + carbs + + ", mealBolus= " + mealBolus + "}"; } - // DataPointInterface + public boolean isDataChanging(Treatment other) { + if (date != other.date) { + return true; + } + if (insulin != other.insulin) + return true; + if (carbs != other.carbs) + return true; + return false; + } + + public boolean isEqual(Treatment other) { + if (date != other.date) { + return false; + } + if (insulin != other.insulin) + return false; + if (carbs != other.carbs) + return false; + if (mealBolus != other.mealBolus) + return false; + if (pumpId != other.pumpId) + return false; + if (!Objects.equals(_id, other._id)) + return false; + return true; + } + + public void copyFrom(Treatment t) { + date = t.date; + _id = t._id; + insulin = t.insulin; + carbs = t.carbs; + mealBolus = t.mealBolus; + pumpId = t.pumpId; + } + + // ----------------- DataPointInterface -------------------- @Override public double getX() { - return timeIndex; + return date; } // default when no sgv around available @@ -117,36 +138,42 @@ public class Treatment implements DataPointWithLabelInterface { String label = ""; if (insulin > 0) label += DecimalFormatter.to2Decimal(insulin) + "U"; if (carbs > 0) - label += (label.equals("") ? "" : " ") + DecimalFormatter.to0Decimal(carbs) + "g"; + label += "~" + DecimalFormatter.to0Decimal(carbs) + "g"; return label; } - public void setYValue(List bgReadingsArray) { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile == null) return; - for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { - BgReading reading = bgReadingsArray.get(r); - if (reading.timeIndex > timeIndex) continue; - yValue = NSProfile.fromMgdlToUnits(reading.value, profile.getUnits()); - break; - } + @Override + public long getDuration() { + return 0; } - public void sendToNSClient() { - JSONObject data = new JSONObject(); - try { - if (mealBolus) - data.put("eventType", "Meal Bolus"); - else - data.put("eventType", "Correction Bolus"); - if (insulin != 0d) data.put("insulin", insulin); - if (carbs != 0d) data.put("carbs", carbs.intValue()); - data.put("created_at", DateUtil.toISOString(created_at)); - data.put("timeIndex", timeIndex); - } catch (JSONException e) { - e.printStackTrace(); - } - ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + @Override + public PointsWithLabelGraphSeries.Shape getShape() { + return PointsWithLabelGraphSeries.Shape.BOLUS; } + @Override + public float getSize() { + return 10; + } + + @Override + public int getColor() { + return Color.CYAN; + } + + @Override + public void setY(double y) { + yValue = y; + } + + // ----------------- DataPointInterface end -------------------- + + public Iob iobCalc(long time, double dia) { + InsulinInterface insulinInterface = MainApp.getInsulinIterfaceById(insulinInterfaceID); + if (insulinInterface == null) + insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); + + return insulinInterface.iobCalcForTreatment(this, time, dia); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java new file mode 100644 index 0000000000..d86fe679fb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventCareportalEventChange.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 25.05.2017. + */ + +public class EventCareportalEventChange { +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java new file mode 100644 index 0000000000..78dee60388 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventExtendedBolusChange.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 15.05.2017. + */ + +public class EventExtendedBolusChange { +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java index 3e270e8a1b..1309625b98 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventNewBasalProfile.java @@ -1,14 +1,7 @@ package info.nightscout.androidaps.events; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; - /** * Created by mike on 04.06.2016. */ public class EventNewBasalProfile { - public NSProfile newNSProfile = null; - - public EventNewBasalProfile(NSProfile newProfile) { - newNSProfile = newProfile; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java new file mode 100644 index 0000000000..476a571d70 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventProfileSwitchChange.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 02.06.2017. + */ + +public class EventProfileSwitchChange { +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java new file mode 100644 index 0000000000..38b1b86186 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTempBasalData.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 29.05.2017. + */ + +public class EventReloadTempBasalData { +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java new file mode 100644 index 0000000000..a488a9c7a4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadTreatmentData.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 29.05.2017. + */ + +public class EventReloadTreatmentData { +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java new file mode 100644 index 0000000000..d0ef42d830 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventTempTargetChange.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 13.01.2017. + */ + +public class EventTempTargetChange { +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/FragmentBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/FragmentBase.java deleted file mode 100644 index 79bfc75154..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/FragmentBase.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.interfaces; - -/** - * Created by mike on 05.08.2016. - */ -public interface FragmentBase { -} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java new file mode 100644 index 0000000000..20c563dede --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.interfaces; + +import java.util.Date; + +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Treatment; + +/** + * Created by mike on 17.04.2017. + */ + +public interface InsulinInterface { + final int FASTACTINGINSULIN = 0; + final int FASTACTINGINSULINPROLONGED = 1; + + int getId(); + String getFriendlyName(); + String getComment(); + double getDia(); + public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia); +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java b/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java new file mode 100644 index 0000000000..f3b4111642 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/Interval.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.interfaces; + +/** + * Created by mike on 21.05.2017. + */ + +public interface Interval { + long durationInMsec(); + long start(); + + // planned end time at time of creation + long originalEnd(); + + // end time after cut + long end(); + + void cutEndTo(long end); + boolean match(long time); + boolean before(long time); + boolean after(long time); + + boolean isInProgress(); + boolean isEndingEvent(); +} \ No newline at end of file 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 4442b83041..ba4faf4ba6 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -8,14 +8,15 @@ import java.util.Date; public interface PluginBase { int GENERAL = 1; int TREATMENT = 2; - int TEMPBASAL = 3; + //int TEMPBASAL = 3; int PROFILE = 4; int APS = 5; int PUMP = 6; int CONSTRAINTS = 7; int LOOP = 8; int BGSOURCE = 9; - int LAST = 10; // keep always highest number + int INSULIN = 10; + int LAST = 11; // keep always highest number int getType(); String getFragmentClass(); @@ -25,6 +26,8 @@ public interface PluginBase { boolean isEnabled(int type); boolean isVisibleInTabs(int type); boolean canBeHidden(int type); + boolean hasFragment(); + boolean showInList(int type); void setFragmentEnabled(int type, boolean fragmentEnabled); void setFragmentVisible(int type, boolean fragmentVisible); } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java index 0924723776..64fffa3e57 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/ProfileInterface.java @@ -2,12 +2,13 @@ package info.nightscout.androidaps.interfaces; import android.support.annotation.Nullable; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; /** * Created by mike on 14.06.2016. */ public interface ProfileInterface { @Nullable - NSProfile getProfile(); + ProfileStore getProfile(); + String getProfileName(); } 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 78a111d468..d37693d494 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java @@ -6,29 +6,29 @@ package info.nightscout.androidaps.interfaces; public class PumpDescription { public static final int NONE = 0; - public static final int PERCENT = 1; - public static final int ABSOLUTE = 2; - public static final int EXTENDED = 4; + public static final int PERCENT = 0x01; + public static final int ABSOLUTE = 0x02; public boolean isBolusCapable = true; public double bolusStep = 0.1d; public boolean isExtendedBolusCapable = true; public double extendedBolusStep = 0.1d; + public double extendedBolusDurationStep = 30; + public double extendedBolusMaxDuration = 12 * 60; public boolean isTempBasalCapable = true; - public int lowTempBasalStyle = PERCENT; - public int highTempBasalStyle = PERCENT; - public double maxHighTempPercent = 200; - public double maxHighTempAbsolute = 0; // zero = no limit - public double lowTempPercentStep = 10; - public double lowTempAbsoluteStep = 0.05d; - public int lowTempPercentDuration = 30; - public int lowTempAbsoluteDuration = 30; - public double highTempPercentStep = 10; - public double highTempAbsoluteStep = 0.05d; - public int highTempPercentDuration = 30; - public int highTempAbsoluteDuration = 30; + public int tempBasalStyle = PERCENT; + + public int maxTempPercent = 200; + public int tempPercentStep = 10; + + public double maxTempAbsolute = 10; + public double tempAbsoluteStep = 0.05d; + + public int tempDurationStep = 60; + public int tempMaxDuration = 12 * 60; + public boolean isSetBasalProfileCapable = true; public double basalStep = 0.01d; diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index 6b6d8e856f..dbbdec2ce1 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -1,14 +1,12 @@ package info.nightscout.androidaps.interfaces; -import android.content.Context; - import org.json.JSONObject; import java.util.Date; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; /** * Created by mike on 04.06.2016. @@ -19,27 +17,19 @@ public interface PumpInterface { boolean isSuspended(); boolean isBusy(); - boolean isTempBasalInProgress(); - boolean isExtendedBoluslInProgress(); - // Upload to pump new basal profile int SUCCESS = 0; int FAILED = 1; int NOT_NEEDED = 2; - int setNewBasalProfile(NSProfile profile); - boolean isThisProfileSet(NSProfile profile); + int setNewBasalProfile(Profile profile); + boolean isThisProfileSet(Profile profile); Date lastDataTime(); void refreshDataFromPump(String reason); double getBaseBasalRate(); // base basal rate, not temp basal - double getTempBasalAbsoluteRate(); - double getTempBasalRemainingMinutes(); - TempBasal getTempBasal(Date time); - TempBasal getTempBasal(); - TempBasal getExtendedBolus(); - PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context); + PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); void stopBolusDelivering(); PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes); PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes); @@ -56,4 +46,6 @@ public interface PumpInterface { // Short info for SMS, Wear etc String shortStatus(boolean veryShort); + + boolean isFakingTempsByExtendedBoluses(); } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/TempBasalsInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/TempBasalsInterface.java deleted file mode 100644 index aa01d77adb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TempBasalsInterface.java +++ /dev/null @@ -1,20 +0,0 @@ -package info.nightscout.androidaps.interfaces; - -import java.util.Date; - -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.data.IobTotal; - -/** - * Created by mike on 14.06.2016. - */ -public interface TempBasalsInterface { - void updateTotalIOB(); - IobTotal getLastCalculation(); - IobTotal getCalculationToTime(long time); - - TempBasal getTempBasal (Date time); - TempBasal getExtendedBolus (Date time); - - long oldestDataAvaialable(); -} 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 efb5f85fd0..d9e3742c70 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -2,18 +2,63 @@ package info.nightscout.androidaps.interfaces; import java.util.List; -import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.data.OverlappingIntervals; +import info.nightscout.androidaps.data.ProfileIntervals; /** * Created by mike on 14.06.2016. */ public interface TreatmentsInterface { - void updateTotalIOB(); - IobTotal getLastCalculation(); - IobTotal getCalculationToTime(long time); + void updateTotalIOBTreatments(); + void updateTotalIOBTempBasals(); + + IobTotal getLastCalculationTreatments(); + IobTotal getCalculationToTimeTreatments(long time); + IobTotal getLastCalculationTempBasals(); + IobTotal getCalculationToTimeTempBasals(long time); + MealData getMealData(); - List getTreatments(); + + List getTreatmentsFromHistory(); + List getTreatments5MinBackFromHistory(long time); + + // real basals (not faked by extended bolus) + boolean isInHistoryRealTempBasalInProgress(); + TemporaryBasal getRealTempBasalFromHistory(long time); + + boolean addToHistoryTempBasal(TemporaryBasal tempBasal); + + // basal that can be faked by extended boluses + boolean isTempBasalInProgress(); + TemporaryBasal getTempBasalFromHistory(long time); + double getTempBasalAbsoluteRateHistory(); + double getTempBasalRemainingMinutesFromHistory(); + OverlappingIntervals getTemporaryBasalsFromHistory(); + + boolean isInHistoryExtendedBoluslInProgress(); + ExtendedBolus getExtendedBolusFromHistory(long time); + OverlappingIntervals getExtendedBolusesFromHistory(); + + boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus); + + boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo); + + TempTarget getTempTargetFromHistory(long time); + OverlappingIntervals getTempTargetsFromHistory(); + + ProfileSwitch getProfileSwitchFromHistory(long time); + ProfileIntervals getProfileSwitchesFromHistory(); + void addToHistoryProfileSwitch(ProfileSwitch profileSwitch); + + long oldestDataAvailable(); + } 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 c3ea14dc79..77e5b40250 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java @@ -3,6 +3,8 @@ package info.nightscout.androidaps.plugins.Actions; import android.app.Activity; import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; @@ -10,24 +12,32 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import com.crashlytics.android.answers.Answers; +import com.crashlytics.android.answers.CustomEvent; import com.squareup.otto.Subscribe; +import java.util.Date; + import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventRefreshGui; -import info.nightscout.androidaps.interfaces.FragmentBase; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; -import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; -import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Actions.dialogs.NewExtendedBolusDialog; import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog; +import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; +import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; /** * A simple {@link Fragment} subclass. */ -public class ActionsFragment extends Fragment implements FragmentBase, View.OnClickListener { +public class ActionsFragment extends Fragment implements View.OnClickListener { static ActionsPlugin actionsPlugin = new ActionsPlugin(); @@ -38,10 +48,20 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl Button profileSwitch; Button tempTarget; Button extendedBolus; + Button extendedBolusCancel; Button tempBasal; Button fill; + private static Handler sHandler; + private static HandlerThread sHandlerThread; + public ActionsFragment() { + super(); + if (sHandlerThread == null) { + sHandlerThread = new HandlerThread(ActionsFragment.class.getSimpleName()); + sHandlerThread.start(); + sHandler = new Handler(sHandlerThread.getLooper()); + } } @@ -53,12 +73,14 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl profileSwitch = (Button) view.findViewById(R.id.actions_profileswitch); tempTarget = (Button) view.findViewById(R.id.actions_temptarget); extendedBolus = (Button) view.findViewById(R.id.actions_extendedbolus); + extendedBolusCancel = (Button) view.findViewById(R.id.actions_extendedbolus_cancel); tempBasal = (Button) view.findViewById(R.id.actions_settempbasal); fill = (Button) view.findViewById(R.id.actions_fill); profileSwitch.setOnClickListener(this); tempTarget.setOnClickListener(this); extendedBolus.setOnClickListener(this); + extendedBolusCancel.setOnClickListener(this); tempBasal.setOnClickListener(this); fill.setOnClickListener(this); @@ -88,21 +110,42 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl updateGUIIfVisible(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + updateGUIIfVisible(); + } + + @Subscribe + public void onStatusEvent(final EventTempBasalChange ev) { + updateGUIIfVisible(); + } + void updateGUIIfVisible() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) + if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() == null) + return; + boolean allowProfileSwitch = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile().getProfileList().size() > 1; + if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !allowProfileSwitch) profileSwitch.setVisibility(View.GONE); else profileSwitch.setVisibility(View.VISIBLE); - if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) + if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() || MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) extendedBolus.setVisibility(View.GONE); - else + else { extendedBolus.setVisibility(View.VISIBLE); - if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) + } + if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() || MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) + extendedBolusCancel.setVisibility(View.GONE); + else { + extendedBolusCancel.setVisibility(View.VISIBLE); + ExtendedBolus running = MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()); + extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + running.toString()); + } + if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || MainApp.getConfigBuilder().isTempBasalInProgress()) tempBasal.setVisibility(View.GONE); else tempBasal.setVisibility(View.VISIBLE); @@ -122,6 +165,7 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl @Override public void onClick(View view) { FragmentManager manager = getFragmentManager(); + final PumpInterface pump = MainApp.getConfigBuilder(); switch (view.getId()) { case R.id.actions_profileswitch: NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); @@ -141,6 +185,17 @@ public class ActionsFragment extends Fragment implements FragmentBase, View.OnCl NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog(); newExtendedDialog.show(manager, "NewExtendedDialog"); break; + case R.id.actions_extendedbolus_cancel: + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + sHandler.post(new Runnable() { + @Override + public void run() { + pump.cancelExtendedBolus(); + Answers.getInstance().logCustom(new CustomEvent("CancelExtended")); + } + }); + } + break; case R.id.actions_settempbasal: NewTempBasalDialog newTempDialog = new NewTempBasalDialog(); newTempDialog.show(manager, "NewTempDialog"); 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 eedd0e4baf..d6ef13b29d 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 @@ -54,6 +54,16 @@ public class ActionsPlugin implements PluginBase { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; 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 8f50ac28e0..834206ca34 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 @@ -26,7 +26,9 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.DecimalFormatter; @@ -159,7 +161,12 @@ public class FillDialog extends DialogFragment implements OnClickListener { mHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = pump.deliverTreatment(finalInsulinAfterConstraints, 0, context, false); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.addToTreatments = false; + detailedBolusInfo.source = Source.NONE; + PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); if (!result.success) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java index ee726efb4d..c85d5c4540 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewExtendedBolusDialog.java @@ -29,15 +29,8 @@ import info.nightscout.utils.SafeParse; public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener { - Button okButton; - EditText insulinEdit; - RadioButton h05Radio; - RadioButton h10Radio; - RadioButton h20Radio; - RadioButton h30Radio; - RadioButton h40Radio; - PlusMinusEditText editInsulin; + PlusMinusEditText editDuration; Handler mHandler; public static HandlerThread mHandlerThread; @@ -54,18 +47,16 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli getDialog().setTitle(getString(R.string.overview_extendedbolus_button)); View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false); - okButton = (Button) view.findViewById(R.id.overview_newextendedbolus_okbutton); - insulinEdit = (EditText) view.findViewById(R.id.overview_newextendedbolus_insulin); - h05Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_05h); - h10Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_1h); - h20Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_2h); - h30Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_3h); - h40Radio = (RadioButton) view.findViewById(R.id.overview_newextendedbolus_4h); Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); editInsulin = new PlusMinusEditText(view, R.id.overview_newextendedbolus_insulin, R.id.overview_newextendedbolus_insulin_plus, R.id.overview_newextendedbolus_insulin_minus, 0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false); - okButton.setOnClickListener(this); + double extendedDurationStep = MainApp.getConfigBuilder().getPumpDescription().extendedBolusDurationStep; + double extendedMaxDuration = MainApp.getConfigBuilder().getPumpDescription().extendedBolusMaxDuration; + editDuration = new PlusMinusEditText(view, R.id.overview_newextendedbolus_duration, R.id.overview_newextendedbolus_duration_plus, R.id.overview_newextendedbolus_duration_minus, extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false); + + view.findViewById(R.id.ok).setOnClickListener(this); + view.findViewById(R.id.cancel).setOnClickListener(this); return view; } @@ -79,14 +70,10 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli @Override public void onClick(View view) { switch (view.getId()) { - case R.id.overview_newextendedbolus_okbutton: + case R.id.ok: try { - Double insulin = SafeParse.stringToDouble(insulinEdit.getText().toString()); - int durationInMinutes = 30; - if (h10Radio.isChecked()) durationInMinutes = 60; - if (h20Radio.isChecked()) durationInMinutes = 120; - if (h30Radio.isChecked()) durationInMinutes = 180; - if (h40Radio.isChecked()) durationInMinutes = 240; + Double insulin = SafeParse.stringToDouble(editInsulin.getText()); + int durationInMinutes = SafeParse.stringToInt(editDuration.getText()); String confirmMessage = getString(R.string.setextendedbolusquestion); @@ -130,6 +117,10 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli } catch (Exception e) { e.printStackTrace(); } + break; + case R.id.cancel: + dismiss(); + break; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java index 2d5a4580c4..51effccb86 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/NewTempBasalDialog.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.Actions.dialogs; +import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; @@ -10,45 +11,38 @@ import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RadioButton; import android.widget.RadioGroup; +import android.widget.RelativeLayout; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import java.text.DecimalFormat; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.PlusMinusEditText; import info.nightscout.utils.SafeParse; public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener { - Button okButton; - EditText basalPercentEdit; - EditText basalAbsoluteEdit; RadioButton percentRadio; RadioButton absoluteRadio; RadioGroup basalTypeRadioGroup; - RadioButton h05Radio; - RadioButton h10Radio; - RadioButton h20Radio; - RadioButton h30Radio; - RadioButton h40Radio; + RelativeLayout typeSelectorLayout; LinearLayout percentLayout; LinearLayout absoluteLayout; - PlusMinusEditText basalPercentPM; - PlusMinusEditText basalAbsolutePM; + PlusMinusEditText basalPercent; + PlusMinusEditText basalAbsolute; + PlusMinusEditText duration; Handler mHandler; public static HandlerThread mHandlerThread; @@ -65,31 +59,50 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi getDialog().setTitle(getString(R.string.overview_tempbasal_button)); View view = inflater.inflate(R.layout.overview_newtempbasal_dialog, container, false); - okButton = (Button) view.findViewById(R.id.overview_newtempbasal_okbutton); - basalPercentEdit = (EditText) view.findViewById(R.id.overview_newtempbasal_basalpercentinput); - basalAbsoluteEdit = (EditText) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput); + percentLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_percent_layout); absoluteLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_absolute_layout); percentRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_percent_radio); basalTypeRadioGroup = (RadioGroup) view.findViewById(R.id.overview_newtempbasal_radiogroup); absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio); - h05Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_05h); - h10Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_1h); - h20Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_2h); - h30Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_3h); - h40Radio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_4h); + typeSelectorLayout = (RelativeLayout) view.findViewById(R.id.overview_newtempbasal_typeselector_layout); - Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit); - basalPercentPM = new PlusMinusEditText(view, R.id.overview_newtempbasal_basalpercentinput, R.id.overview_newtempbasal_basalpercent_plus, R.id.overview_newtempbasal_basalpercent_minus, 100d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true); + PumpDescription pumpDescription = MainApp.getConfigBuilder().getPumpDescription(); - Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - Double currentBasal = 0d; - if (profile != null) currentBasal = profile.getBasal(NSProfile.secondsFromMidnight()); - basalAbsolutePM = new PlusMinusEditText(view, R.id.overview_newtempbasal_basalabsoluteinput, R.id.overview_newtempbasal_basalabsolute_plus, R.id.overview_newtempbasal_basalabsolute_minus, currentBasal, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true); + basalPercent = new PlusMinusEditText(view, R.id.overview_newtempbasal_basalpercentinput, R.id.overview_newtempbasal_basalpercent_plus, R.id.overview_newtempbasal_basalpercent_minus, + 100d, 0d, (double) pumpDescription.maxTempPercent, (double) pumpDescription.tempPercentStep, new DecimalFormat("0"), true); - absoluteLayout.setVisibility(View.GONE); - okButton.setOnClickListener(this); + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double currentBasal = profile.getBasal(); + basalAbsolute = new PlusMinusEditText(view, R.id.overview_newtempbasal_basalabsoluteinput, R.id.overview_newtempbasal_basalabsolute_plus, R.id.overview_newtempbasal_basalabsolute_minus, + currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true); + + double tempDurationStep = MainApp.getConfigBuilder().getPumpDescription().tempDurationStep; + double tempMaxDuration = MainApp.getConfigBuilder().getPumpDescription().tempMaxDuration; + duration = new PlusMinusEditText(view, R.id.overview_newtempbasal_duration, R.id.overview_newtempbasal_duration_plus, R.id.overview_newtempbasal_duration_minus, + tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false); + + if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT && (pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) { + // Both allowed + typeSelectorLayout.setVisibility(View.VISIBLE); + } else { + typeSelectorLayout.setVisibility(View.GONE); + } + + if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT) { + percentRadio.setChecked(true); + absoluteRadio.setChecked(false); + percentLayout.setVisibility(View.VISIBLE); + absoluteLayout.setVisibility(View.GONE); + } else if ((pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) { + percentRadio.setChecked(false); + absoluteRadio.setChecked(true); + percentLayout.setVisibility(View.GONE); + absoluteLayout.setVisibility(View.VISIBLE); + } + + view.findViewById(R.id.ok).setOnClickListener(this); + view.findViewById(R.id.cancel).setOnClickListener(this); basalTypeRadioGroup.setOnCheckedChangeListener(this); return view; } @@ -104,36 +117,32 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi @Override public void onClick(View view) { switch (view.getId()) { - case R.id.overview_newtempbasal_okbutton: + case R.id.ok: try { - int basalPercent = 0; - Double basalAbsolute = 0d; + int percent = 0; + Double absolute = 0d; final boolean setAsPercent = percentRadio.isChecked(); - int durationInMinutes = 30; - if (h10Radio.isChecked()) durationInMinutes = 60; - if (h20Radio.isChecked()) durationInMinutes = 120; - if (h30Radio.isChecked()) durationInMinutes = 180; - if (h40Radio.isChecked()) durationInMinutes = 240; + int durationInMinutes = SafeParse.stringToInt(duration.getText()); String confirmMessage = getString(R.string.setbasalquestion); if (setAsPercent) { - int basalPercentInput = SafeParse.stringToDouble(basalPercentEdit.getText().toString()).intValue(); - basalPercent = MainApp.getConfigBuilder().applyBasalConstraints(basalPercentInput); - confirmMessage += "\n" + basalPercent + "% "; + int basalPercentInput = SafeParse.stringToInt(basalPercent.getText()); + percent = MainApp.getConfigBuilder().applyBasalConstraints(basalPercentInput); + confirmMessage += "\n" + percent + "% "; confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?"; - if (basalPercent != basalPercentInput) + if (percent != basalPercentInput) confirmMessage += "\n" + getString(R.string.constraintapllied); } else { - Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsoluteEdit.getText().toString()); - basalAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(basalAbsoluteInput); - confirmMessage += "\n" + basalAbsolute + " U/h "; + Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsolute.getText()); + absolute = MainApp.getConfigBuilder().applyBasalConstraints(basalAbsoluteInput); + confirmMessage += "\n" + absolute + " U/h "; confirmMessage += "\n" + getString(R.string.duration) + " " + durationInMinutes + "min ?"; - if (basalAbsolute - basalAbsoluteInput != 0d) + if (absolute - basalAbsoluteInput != 0d) confirmMessage += "\n" + getString(R.string.constraintapllied); } - final int finalBasalPercent = basalPercent; - final Double finalBasal = basalAbsolute; + final int finalBasalPercent = percent; + final Double finalBasal = absolute; final int finalDurationInMinutes = durationInMinutes; final Context context = getContext(); @@ -153,6 +162,12 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes); } if (!result.success) { + if (context instanceof Activity) { + Activity activity = (Activity) context; + if (activity.isFinishing()) { + return; + } + } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); builder.setMessage(result.comment); @@ -171,6 +186,10 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi } catch (Exception e) { e.printStackTrace(); } + break; + case R.id.cancel: + dismiss(); + break; } } 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 69db12c29b..c016f5ec61 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 @@ -1,21 +1,32 @@ package info.nightscout.androidaps.plugins.Careportal; +import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; +import com.squareup.otto.Subscribe; + +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; -public class CareportalFragment extends Fragment implements FragmentBase, View.OnClickListener { +public class CareportalFragment extends Fragment implements View.OnClickListener { static CareportalPlugin careportalPlugin; + TextView iage; + TextView cage; + TextView sage; + TextView pbage; + static public CareportalPlugin getPlugin() { if (careportalPlugin == null) { careportalPlugin = new CareportalPlugin(); @@ -24,25 +35,26 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O } // bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget - final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false, false); - final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false, false); - final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false, false); - final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false, false); - final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false, false); - final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true, false); - final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false, false); - final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false, false); - final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false, false); - final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false, false); - final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false, false); - final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false); - final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false); - final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false); - final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false); - final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false); - final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false, false); - final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false); - final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true); + static final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false, false); + static final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false, false); + static final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false, false); + static final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false, false); + static final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false, false); + static final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true, false); + static final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false, false); + static final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false, false); + static final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false, false); + static final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow pumpbatterychange = new OptionsToShow(R.id.careportal_pumpbatterychange, R.string.careportal_pumpbatterychange, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false); + static final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false); + static final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, true, false, false, true, false, false); + static final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false); + static final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -58,6 +70,7 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O view.findViewById(R.id.careportal_carbscorrection).setOnClickListener(this); view.findViewById(R.id.careportal_exercise).setOnClickListener(this); view.findViewById(R.id.careportal_insulincartridgechange).setOnClickListener(this); + view.findViewById(R.id.careportal_pumpbatterychange).setOnClickListener(this); view.findViewById(R.id.careportal_mealbolus).setOnClickListener(this); view.findViewById(R.id.careportal_note).setOnClickListener(this); view.findViewById(R.id.careportal_profileswitch).setOnClickListener(this); @@ -68,14 +81,24 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O view.findViewById(R.id.careportal_tempbasalstart).setOnClickListener(this); view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this); view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this); + + iage = (TextView) view.findViewById(R.id.careportal_insulinage); + cage = (TextView) view.findViewById(R.id.careportal_canulaage); + sage = (TextView) view.findViewById(R.id.careportal_sensorage); + pbage = (TextView) view.findViewById(R.id.careportal_pbage); + + updateGUI(); return view; } @Override public void onClick(View view) { - FragmentManager manager = getFragmentManager(); + action(view.getId(), getFragmentManager()); + } + + public static void action(int id, FragmentManager manager) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - switch (view.getId()) { + switch (id) { case R.id.careportal_bgcheck: newDialog.setOptions(bgcheck); break; @@ -103,6 +126,9 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O case R.id.careportal_insulincartridgechange: newDialog.setOptions(insulinchange); break; + case R.id.careportal_pumpbatterychange: + newDialog.setOptions(pumpbatterychange); + break; case R.id.careportal_mealbolus: newDialog.setOptions(mealbolus); break; @@ -140,4 +166,55 @@ public class CareportalFragment extends Fragment implements FragmentBase, View.O newDialog.show(manager, "NewNSTreatmentDialog"); } + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventCareportalEventChange c) { + updateGUI(); + } + + void updateGUI() { + Activity activity = getActivity(); + updateAge(activity, sage, iage, cage, pbage); + } + + public static void updateAge(Activity activity, final TextView sage, final TextView iage, final TextView cage, final TextView pbage) { + if (activity != null) { + activity.runOnUiThread( + new Runnable() { + @Override + public void run() { + CareportalEvent careportalEvent; + if (sage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE); + sage.setText(careportalEvent != null ? careportalEvent.age() : MainApp.sResources.getString(R.string.notavailable)); + } + if (iage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); + iage.setText(careportalEvent != null ? careportalEvent.age() : MainApp.sResources.getString(R.string.notavailable)); + } + if (cage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); + cage.setText(careportalEvent != null ? careportalEvent.age() : MainApp.sResources.getString(R.string.notavailable)); + } + if (pbage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE); + pbage.setText(careportalEvent != null ? careportalEvent.age() : MainApp.sResources.getString(R.string.notavailable)); + } + } + } + ); + } + } + } 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 9fd4cbca85..fed3ff1a43 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 @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.Careportal; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; @@ -50,6 +51,16 @@ public class CareportalPlugin implements PluginBase { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return !Config.NSCLIENT; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java index 68d24b7dda..f1e5f09ebd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/Dialogs/NewNSTreatmentDialog.java @@ -7,7 +7,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextWatcher; @@ -21,12 +20,12 @@ import android.widget.CompoundButton; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RadioButton; +import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TextView; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; -import com.j256.ormlite.dao.Dao; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; @@ -36,7 +35,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; @@ -46,45 +44,50 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; -import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.PlusMinusEditText; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; -import info.nightscout.utils.ToastUtils; import info.nightscout.utils.Translator; public class NewNSTreatmentDialog extends DialogFragment implements View.OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener { private static Logger log = LoggerFactory.getLogger(NewNSTreatmentDialog.class); - private FragmentActivity context; + private Activity context; private static OptionsToShow options; - NSProfile profile; + Profile profile; + ProfileStore profileStore; String units; - LinearLayout layoutBg; + RelativeLayout layoutBg; LinearLayout layoutBgSource; - LinearLayout layoutInsulin; - LinearLayout layoutCarbs; - LinearLayout layoutSplit; - LinearLayout layoutDuration; - LinearLayout layoutPercent; - LinearLayout layoutAbsolute; - LinearLayout layoutCarbTime; - LinearLayout layoutProfile; + RelativeLayout layoutInsulin; + RelativeLayout layoutCarbs; + RelativeLayout layoutSplit; + RelativeLayout layoutDuration; + RelativeLayout layoutPercent; + RelativeLayout layoutAbsolute; + RelativeLayout layoutCarbTime; + RelativeLayout layoutProfile; LinearLayout layoutTempTarget; Button dateButton; Button timeButton; Button okButton; + Button cancelButton; TextView bgUnitsView; RadioButton meterRadioButton; @@ -134,7 +137,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick @Override public void onAttach(Activity activity) { - context = (FragmentActivity) activity; + context = activity; super.onAttach(activity); } @@ -142,18 +145,19 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { getDialog().setTitle(getString(options.eventName)); + setStyle(DialogFragment.STYLE_NORMAL, getTheme()); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); - layoutBg = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout); + layoutBg = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout); layoutBgSource = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bgsource_layout); - layoutInsulin = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_insulin_layout); - layoutCarbs = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbs_layout); - layoutSplit = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_split_layout); - layoutDuration = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_duration_layout); - layoutPercent = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_percent_layout); - layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout); - layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout); - layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout); + layoutInsulin = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_insulin_layout); + layoutCarbs = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_carbs_layout); + layoutSplit = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_split_layout); + layoutDuration = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_duration_layout); + layoutPercent = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_percent_layout); + layoutAbsolute = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout); + layoutCarbTime = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout); + layoutProfile = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout); layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout); bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits); @@ -218,30 +222,25 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick dateButton.setOnClickListener(this); timeButton.setOnClickListener(this); - okButton = (Button) view.findViewById(R.id.careportal_newnstreatment_ok); + okButton = (Button) view.findViewById(R.id.ok); okButton.setOnClickListener(this); + cancelButton = (Button) view.findViewById(R.id.cancel); + cancelButton.setOnClickListener(this); // profile - profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + profile = MainApp.getConfigBuilder().getProfile(); + profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); ArrayList profileList; units = Constants.MGDL; - if (profile == null) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), context.getString(R.string.noprofile)); - profileList = new ArrayList(); - } else { - units = profile.getUnits(); - profileList = profile.getProfileList(); - } + units = profile.getUnits(); + profileList = profileStore.getProfileList(); ArrayAdapter adapter = new ArrayAdapter(getContext(), - android.R.layout.simple_spinner_item, profileList); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_centered, profileList); profileSpinner.setAdapter(adapter); - if (profile != null) { - // set selected to actual profile - for (int p = 0; p < profileList.size(); p++) { - if (profileList.get(p).equals(profile.getActiveProfile())) - profileSpinner.setSelection(p); - } + // set selected to actual profile + for (int p = 0; p < profileList.size(); p++) { + if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName())) + profileSpinner.setSelection(p); } // temp target @@ -250,8 +249,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick reasonList.add(MainApp.sResources.getString(R.string.activity)); reasonList.add(MainApp.sResources.getString(R.string.manual)); ArrayAdapter adapterReason = new ArrayAdapter(getContext(), - android.R.layout.simple_spinner_item, reasonList); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_centered, reasonList); reasonSpinner.setAdapter(adapterReason); // bg @@ -267,7 +265,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick // meterRadioButton.setChecked(true); // } - Double bg = NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL); + Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL); if (profile == null) editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false); else if (profile.getUnits().equals(Constants.MMOL)) @@ -276,9 +274,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, bg, 0d, 500d, 1d, new DecimalFormat("0"), false); bgInputEdit.addTextChangedListener(new TextWatcher() { - public void afterTextChanged(Editable s) {} + public void afterTextChanged(Editable s) { + } - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } public void onTextChanged(CharSequence s, int start, int before, int count) { if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true); @@ -287,9 +287,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - if (profile == null) return; - Double bg = NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()); + Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()); editBg.setValue(bg); } }); @@ -361,14 +359,17 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick tpd.dismissOnPause(true); tpd.show(context.getFragmentManager(), "Timepickerdialog"); break; - case R.id.careportal_newnstreatment_ok: + case R.id.ok: createNSTreatment(); dismiss(); break; + case R.id.cancel: + dismiss(); + break; } } - private void showOrHide(LinearLayout layout, boolean visible) { + private void showOrHide(ViewGroup layout, boolean visible) { if (visible) layout.setVisibility(View.VISIBLE); else layout.setVisibility(View.GONE); } @@ -398,14 +399,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("created_at", DateUtil.toISOString(eventTime)); switch (options.eventType) { case R.id.careportal_bgcheck: - data.put("eventType", "BG Check"); + data.put("eventType", CareportalEvent.BGCHECK); break; case R.id.careportal_announcement: - data.put("eventType", "Announcement"); + data.put("eventType", CareportalEvent.ANNOUNCEMENT); data.put("isAnnouncement", true); break; case R.id.careportal_cgmsensorinsert: - data.put("eventType", "Sensor Change"); + data.put("eventType", CareportalEvent.SENSORCHANGE); break; case R.id.careportal_cgmsensorstart: data.put("eventType", "Sensor Start"); @@ -413,7 +414,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick case R.id.careportal_combobolus: data.put("splitNow", SafeParse.stringToDouble(splitEdit.getText().toString())); data.put("splitExt", 100 - SafeParse.stringToDouble(splitEdit.getText().toString())); - data.put("eventType", "Combo Bolus"); + data.put("eventType", CareportalEvent.COMBOBOLUS); break; case R.id.careportal_correctionbolus: data.put("eventType", "Correction Bolus"); @@ -422,40 +423,44 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick data.put("eventType", "Carb Correction"); break; case R.id.careportal_exercise: - data.put("eventType", "Exercise"); + data.put("eventType", CareportalEvent.EXERCISE); break; case R.id.careportal_insulincartridgechange: - data.put("eventType", "Insulin Change"); + data.put("eventType", CareportalEvent.INSULINCHANGE); + break; + case R.id.careportal_pumpbatterychange: + data.put("eventType", CareportalEvent.PUMPBATTERYCHANGE); break; case R.id.careportal_mealbolus: data.put("eventType", "Meal Bolus"); break; case R.id.careportal_note: - data.put("eventType", "Note"); + data.put("eventType", CareportalEvent.NOTE); break; case R.id.careportal_profileswitch: - data.put("eventType", "Profile Switch"); + data.put("eventType", CareportalEvent.PROFILESWITCH); + allowZeroDuration = true; break; case R.id.careportal_pumpsitechange: - data.put("eventType", "Site Change"); + data.put("eventType", CareportalEvent.SITECHANGE); break; case R.id.careportal_question: - data.put("eventType", "Question"); + data.put("eventType", CareportalEvent.QUESTION); break; case R.id.careportal_snackbolus: data.put("eventType", "Snack Bolus"); break; case R.id.careportal_tempbasalstart: - data.put("eventType", "Temp Basal"); + data.put("eventType", CareportalEvent.TEMPBASAL); break; case R.id.careportal_tempbasalend: - data.put("eventType", "Temp Basal"); + data.put("eventType", CareportalEvent.TEMPBASAL); break; case R.id.careportal_openapsoffline: - data.put("eventType", "OpenAPS Offline"); + data.put("eventType", CareportalEvent.OPENAPSOFFLINE); break; case R.id.careportal_temporarytarget: - data.put("eventType", "Temporary Target"); + data.put("eventType", CareportalEvent.TEMPORARYTARGET); if (!reasonSpinner.getSelectedItem().toString().equals("")) data.put("reason", reasonSpinner.getSelectedItem().toString()); if (SafeParse.stringToDouble(low.getText().toString()) != 0d) @@ -611,24 +616,30 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick @Override public void run() { try { - String profile = data.getString("profile"); - NSProfile nsProfile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - nsProfile.setActiveProfile(profile); + String profileName = data.getString("profile"); + ProfileSwitch profileSwitch = new ProfileSwitch(); + profileSwitch.date = new Date().getTime(); + profileSwitch.source = Source.PUMP; + profileSwitch.profileName = profileName; + profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).toString(); + profileSwitch.profilePlugin = MainApp.getConfigBuilder().getActiveProfileInterface().getClass().getName(); + profileSwitch.durationInMinutes = data.getInt("duration"); + if (ConfigBuilderPlugin.getActiveProfileInterface() instanceof CircadianPercentageProfilePlugin) { + CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) MainApp.getConfigBuilder().getActiveProfileInterface(); + profileSwitch.isCPP = true; + profileSwitch.timeshift = cpp.timeshift; + profileSwitch.percentage = cpp.percentage; + } + MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch); + PumpInterface pump = MainApp.getConfigBuilder(); if (pump != null) { - pump.setNewBasalProfile(nsProfile); + pump.setNewBasalProfile(profileStore.getSpecificProfile(profileName)); log.debug("Setting new profile: " + profile); - MainApp.bus().post(new EventNewBasalProfile(nsProfile)); + MainApp.bus().post(new EventNewBasalProfile()); } else { log.error("No active pump selected"); } - if (ConfigBuilderPlugin.getActiveProfile() instanceof CircadianPercentageProfilePlugin) { - CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) ConfigBuilderPlugin.getActiveProfile(); - data.put("CircadianPercentageProfile", true); - data.put("timeshift", cpp.timeshift); - data.put("percentage", cpp.percentage); - } - ConfigBuilderPlugin.uploadCareportalEntryToNS(data); Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); } catch (JSONException e) { e.printStackTrace(); @@ -638,30 +649,28 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } } else if (options.executeTempTarget) { try { - if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration")&& data.getInt("duration") == 0)) { + if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) { sHandler.post(new Runnable() { @Override public void run() { try { TempTarget tempTarget = new TempTarget(); - tempTarget.timeStart = eventTime; - tempTarget.duration = data.getInt("duration"); + tempTarget.date = eventTime.getTime(); + tempTarget.durationInMinutes = data.getInt("duration"); tempTarget.reason = data.getString("reason"); - if(tempTarget.duration != 0) { - tempTarget.low = NSProfile.toMgdl(data.getDouble("targetBottom"), ConfigBuilderPlugin.getActiveProfile().getProfile().getUnits()); - tempTarget.high = NSProfile.toMgdl(data.getDouble("targetTop"), ConfigBuilderPlugin.getActiveProfile().getProfile().getUnits()); + tempTarget.source = Source.USER; + if (tempTarget.durationInMinutes != 0) { + tempTarget.low = Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits()); + tempTarget.high = Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits()); } else { tempTarget.low = 0; tempTarget.high = 0; } - tempTarget.setTimeIndex(tempTarget.getTimeIndex()); - Dao dao = MainApp.getDbHelper().getDaoTempTargets(); - log.debug("Creating new TempTarget db record: " + tempTarget.log()); - dao.createIfNotExists(tempTarget); - MainApp.bus().post(new EventTempTargetRangeChange()); - ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + log.debug("Creating new TempTarget db record: " + tempTarget.toString()); + MainApp.getDbHelper().createOrUpdate(tempTarget); + NSUpload.uploadCareportalEntryToNS(data); Answers.getInstance().logCustom(new CustomEvent("TempTarget")); - } catch (JSONException | SQLException e) { + } catch (JSONException e) { e.printStackTrace(); } } @@ -671,7 +680,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick e.printStackTrace(); } } else { - ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + NSUpload.uploadCareportalEntryToNS(data); Answers.getInstance().logCustom(new CustomEvent("NSTreatment")); } } 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 6436441890..2445f262df 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 @@ -5,6 +5,7 @@ import android.content.Context; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,6 +22,7 @@ import com.crashlytics.android.answers.CustomEvent; import java.util.ArrayList; +import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventConfigBuilderChange; @@ -28,16 +30,17 @@ import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.FragmentBase; +import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin; -import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingPlugin; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.utils.PasswordProtection; -public class ConfigBuilderFragment extends Fragment implements FragmentBase { +public class ConfigBuilderFragment extends Fragment { static ConfigBuilderPlugin configBuilderPlugin = new ConfigBuilderPlugin(); @@ -45,15 +48,17 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { return configBuilderPlugin; } + ListView insulinListView; ListView bgsourceListView; + TextView bgsourceLabel; ListView pumpListView; TextView pumpLabel; ListView loopListView; TextView loopLabel; ListView treatmentsListView; - ListView tempsListView; - TextView tempsLabel; + TextView treatmentsLabel; ListView profileListView; + TextView profileLabel; ListView apsListView; TextView apsLabel; ListView constraintsListView; @@ -62,18 +67,20 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { TextView nsclientVerView; TextView nightscoutVerView; + LinearLayout mainLayout; + Button unlock; + + PluginCustomAdapter insulinDataAdapter = null; PluginCustomAdapter bgsourceDataAdapter = null; PluginCustomAdapter pumpDataAdapter = null; PluginCustomAdapter loopDataAdapter = null; PluginCustomAdapter treatmentsDataAdapter = null; - PluginCustomAdapter tempsDataAdapter = null; PluginCustomAdapter profileDataAdapter = null; PluginCustomAdapter apsDataAdapter = null; PluginCustomAdapter constraintsDataAdapter = null; PluginCustomAdapter generalDataAdapter = null; - LinearLayout mainLayout; - Button unlock; + boolean smallWidth; // TODO: sorting @@ -81,15 +88,24 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.configbuilder_fragment, container, false); + + //check screen width + final DisplayMetrics dm = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + int screen_width = dm.widthPixels; + smallWidth = screen_width < Constants.SMALL_WIDTH; + + insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview); bgsourceListView = (ListView) view.findViewById(R.id.configbuilder_bgsourcelistview); + bgsourceLabel = (TextView) view.findViewById(R.id.configbuilder_bgsourcelabel); pumpListView = (ListView) view.findViewById(R.id.configbuilder_pumplistview); pumpLabel = (TextView) view.findViewById(R.id.configbuilder_pumplabel); loopListView = (ListView) view.findViewById(R.id.configbuilder_looplistview); loopLabel = (TextView) view.findViewById(R.id.configbuilder_looplabel); treatmentsListView = (ListView) view.findViewById(R.id.configbuilder_treatmentslistview); - tempsListView = (ListView) view.findViewById(R.id.configbuilder_tempslistview); - tempsLabel = (TextView) view.findViewById(R.id.configbuilder_tempslabel); + treatmentsLabel = (TextView) view.findViewById(R.id.configbuilder_treatmentslabel); profileListView = (ListView) view.findViewById(R.id.configbuilder_profilelistview); + profileLabel = (TextView) view.findViewById(R.id.configbuilder_profilelabel); apsListView = (ListView) view.findViewById(R.id.configbuilder_apslistview); apsLabel = (TextView) view.findViewById(R.id.configbuilder_apslabel); constraintsListView = (ListView) view.findViewById(R.id.configbuilder_constraintslistview); @@ -98,6 +114,9 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { nsclientVerView = (TextView) view.findViewById(R.id.configbuilder_nsclientversion); nightscoutVerView = (TextView) view.findViewById(R.id.configbuilder_nightscoutversion); + mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout); + unlock = (Button) view.findViewById(R.id.configbuilder_unlock); + nsclientVerView.setText(ConfigBuilderPlugin.nsClientVersionName); nightscoutVerView.setText(ConfigBuilderPlugin.nightscoutVersionName); if (ConfigBuilderPlugin.nsClientVersionCode < 117) nsclientVerView.setTextColor(Color.RED); @@ -105,9 +124,6 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { nightscoutVerView.setTextColor(Color.RED); setViews(); - unlock = (Button) view.findViewById(R.id.configbuilder_unlock); - mainLayout = (LinearLayout) view.findViewById(R.id.configbuilder_mainlayout); - if (PasswordProtection.isLocked("settings_password")) { mainLayout.setVisibility(View.GONE); unlock.setOnClickListener(new View.OnClickListener() { @@ -129,41 +145,45 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { } void setViews() { - bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class), PluginBase.BGSOURCE); + insulinDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginBase.INSULIN), PluginBase.INSULIN); + insulinListView.setAdapter(insulinDataAdapter); + setListViewHeightBasedOnChildren(insulinListView); + bgsourceDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginBase.BGSOURCE), PluginBase.BGSOURCE); bgsourceListView.setAdapter(bgsourceDataAdapter); + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.BGSOURCE).size() == 0) + bgsourceLabel.setVisibility(View.GONE); setListViewHeightBasedOnChildren(bgsourceListView); - pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.PUMP), PluginBase.PUMP); + pumpDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP), PluginBase.PUMP); pumpListView.setAdapter(pumpDataAdapter); - if (MainApp.getSpecificPluginsList(PluginBase.PUMP).size() == 0) + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP).size() == 0) pumpLabel.setVisibility(View.GONE); setListViewHeightBasedOnChildren(pumpListView); - loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.LOOP), PluginBase.LOOP); + loopDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP), PluginBase.LOOP); loopListView.setAdapter(loopDataAdapter); setListViewHeightBasedOnChildren(loopListView); - if (MainApp.getSpecificPluginsList(PluginBase.LOOP).size() == 0) + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.LOOP).size() == 0) loopLabel.setVisibility(View.GONE); - treatmentsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.TREATMENT), PluginBase.TREATMENT); + treatmentsDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT), PluginBase.TREATMENT); treatmentsListView.setAdapter(treatmentsDataAdapter); + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TREATMENT).size() == 0) + treatmentsLabel.setVisibility(View.GONE); setListViewHeightBasedOnChildren(treatmentsListView); - tempsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL), PluginBase.TEMPBASAL); - tempsListView.setAdapter(tempsDataAdapter); - setListViewHeightBasedOnChildren(tempsListView); - if (MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL).size() == 0) - tempsLabel.setVisibility(View.GONE); - profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(ProfileInterface.class), PluginBase.PROFILE); + profileDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.BGSOURCE), PluginBase.PROFILE); profileListView.setAdapter(profileDataAdapter); + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0) + profileLabel.setVisibility(View.GONE); setListViewHeightBasedOnChildren(profileListView); - apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.APS), PluginBase.APS); + apsDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.APS), PluginBase.APS); apsListView.setAdapter(apsDataAdapter); setListViewHeightBasedOnChildren(apsListView); - if (MainApp.getSpecificPluginsList(PluginBase.APS).size() == 0) + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.APS).size() == 0) apsLabel.setVisibility(View.GONE); - constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class), PluginBase.CONSTRAINTS); + constraintsDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginBase.BGSOURCE), PluginBase.CONSTRAINTS); constraintsListView.setAdapter(constraintsDataAdapter); setListViewHeightBasedOnChildren(constraintsListView); - if (MainApp.getSpecificPluginsList(PluginBase.CONSTRAINTS).size() == 0) + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.CONSTRAINTS).size() == 0) constraintsLabel.setVisibility(View.GONE); - generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsList(PluginBase.GENERAL), PluginBase.GENERAL); + generalDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.GENERAL), PluginBase.GENERAL); generalListView.setAdapter(generalDataAdapter); setListViewHeightBasedOnChildren(generalListView); @@ -193,18 +213,18 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { } @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View view, ViewGroup parent) { PluginViewHolder holder = null; - if (convertView == null) { - convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null); + if (view == null) { + view = LayoutInflater.from(parent.getContext()).inflate(smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, null); holder = new PluginViewHolder(); - holder.name = (TextView) convertView.findViewById(R.id.configbuilder_simpleitem_name); - holder.checkboxEnabled = (CheckBox) convertView.findViewById(R.id.configbuilder_simpleitem_checkboxenabled); - holder.checkboxVisible = (CheckBox) convertView.findViewById(R.id.configbuilder_simpleitem_checkboxvisible); - convertView.setTag(holder); + 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); + view.setTag(holder); holder.checkboxEnabled.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { @@ -232,7 +252,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { } }); } else { - holder = (PluginViewHolder) convertView.getTag(); + holder = (PluginViewHolder) view.getTag(); } PluginBase plugin = pluginList.get(position); @@ -252,8 +272,12 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { 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 == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.TEMPBASAL || type == PluginBase.PROFILE) + if (type == PluginBase.INSULIN || type == PluginBase.PUMP || type == PluginBase.TREATMENT || type == PluginBase.PROFILE) if (pluginList.size() < 2) { holder.checkboxEnabled.setEnabled(false); plugin.setFragmentEnabled(type, true); @@ -284,7 +308,7 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { } } - return convertView; + return view; } @@ -299,6 +323,9 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { case PluginBase.LOOP: break; // Single selection allowed + case PluginBase.INSULIN: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class); + break; case PluginBase.APS: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class); break; @@ -308,7 +335,6 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { case PluginBase.BGSOURCE: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class); break; - case PluginBase.TEMPBASAL: case PluginBase.TREATMENT: case PluginBase.PUMP: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class); @@ -328,6 +354,8 @@ public class ConfigBuilderFragment extends Fragment implements FragmentBase { } else { // enable first plugin in list if (type == PluginBase.PUMP) MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true); + else if (type == PluginBase.INSULIN) + MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true); else if (type == PluginBase.PROFILE) MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(type, true); else 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 2c42ffaa41..b476577d06 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -1,16 +1,12 @@ package info.nightscout.androidaps.plugins.ConfigBuilder; import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; -import android.os.Bundle; import android.os.PowerManager; import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; -import com.squareup.otto.Subscribe; - import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; @@ -18,71 +14,65 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Date; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; +import java.util.List; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.OverlappingIntervals; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventBolusRequested; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgError; import info.nightscout.androidaps.plugins.Loop.APSResult; -import info.nightscout.androidaps.plugins.Loop.DeviceStatus; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; -import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA; import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog; -import info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressHelperActivity; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.BatteryLevel; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.SP; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.utils.NSUpload; /** * Created by mike on 05.08.2016. */ -public class ConfigBuilderPlugin implements PluginBase, PumpInterface, ConstraintsInterface { +public class ConfigBuilderPlugin implements PluginBase, PumpInterface, ConstraintsInterface, TreatmentsInterface { private static Logger log = LoggerFactory.getLogger(ConfigBuilderPlugin.class); - static BgSourceInterface activeBgSource; - static PumpInterface activePump; - static ProfileInterface activeProfile; - static TreatmentsInterface activeTreatments; - static TempBasalsInterface activeTempBasals; - static APSInterface activeAPS; - static LoopPlugin activeLoop; + private static BgSourceInterface activeBgSource; + private static PumpInterface activePump; + private static ProfileInterface activeProfile; + private static TreatmentsInterface activeTreatments; + private static APSInterface activeAPS; + private static LoopPlugin activeLoop; + private static InsulinInterface activeInsulin; static public String nightscoutVersionName = ""; static public Integer nightscoutVersionCode = 0; static public String nsClientVersionName = ""; static public Integer nsClientVersionCode = 0; - static ArrayList pluginList; + private static ArrayList pluginList; - PowerManager.WakeLock mWakeLock; + private PowerManager.WakeLock mWakeLock; public ConfigBuilderPlugin() { MainApp.bus().register(this); @@ -119,12 +109,12 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain @Override public boolean isEnabled(int type) { - return type == GENERAL && true; + return type == GENERAL; } @Override public boolean isVisibleInTabs(int type) { - return type == GENERAL && true; + return type == GENERAL; } @Override @@ -132,6 +122,16 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return false; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return false; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { // Always enabled @@ -179,7 +179,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain if (SP.contains(settingEnabled)) p.setFragmentEnabled(type, SP.getBoolean(settingEnabled, true)); if (SP.contains(settingVisible)) - p.setFragmentVisible(type, SP.getBoolean(settingVisible, true)); + p.setFragmentVisible(type, SP.getBoolean(settingVisible, true) && SP.getBoolean(settingEnabled, true)); } catch (Exception e) { e.printStackTrace(); } @@ -192,17 +192,12 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return activeBgSource; } - @Nullable - public static ProfileInterface getActiveProfile() { + public static ProfileInterface getActiveProfileInterface() { return activeProfile; } - public static TreatmentsInterface getActiveTreatments() { - return activeTreatments; - } - - public static TempBasalsInterface getActiveTempBasals() { - return activeTempBasals; + public static InsulinInterface getActiveInsulin() { + return activeInsulin; } public static APSInterface getActiveAPS() { @@ -213,18 +208,18 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return activeLoop; } - public void logPluginStatus() { + void logPluginStatus() { for (PluginBase p : pluginList) { log.debug(p.getName() + ":" + (p.isEnabled(1) ? " GENERAL" : "") + (p.isEnabled(2) ? " TREATMENT" : "") + - (p.isEnabled(3) ? " TEMPBASAL" : "") + (p.isEnabled(4) ? " PROFILE" : "") + (p.isEnabled(5) ? " APS" : "") + (p.isEnabled(6) ? " PUMP" : "") + (p.isEnabled(7) ? " CONSTRAINTS" : "") + (p.isEnabled(8) ? " LOOP" : "") + - (p.isEnabled(9) ? " BGSOURCE" : "") + (p.isEnabled(9) ? " BGSOURCE" : "") + + (p.isEnabled(10) ? " INSULIN" : "") ); } } @@ -245,6 +240,17 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } } + // PluginBase.INSULIN + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class); + activeInsulin = (InsulinInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.INSULIN); + if (Config.logConfigBuilder) + log.debug("Selected insulin interface: " + ((PluginBase) activeInsulin).getName()); + for (PluginBase p : pluginsInCategory) { + if (!p.getName().equals(((PluginBase) activeInsulin).getName())) { + p.setFragmentVisible(PluginBase.INSULIN, false); + } + } + // PluginBase.PROFILE pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class); activeProfile = (ProfileInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PROFILE); @@ -270,7 +276,9 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain // PluginBase.PUMP pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.PUMP); activePump = (PumpInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PUMP); - if (Config.logConfigBuilder && activePump != null) + if (activePump == null) + activePump = VirtualPumpPlugin.getInstance(); // for NSClient build + if (Config.logConfigBuilder) log.debug("Selected pump interface: " + ((PluginBase) activePump).getName()); for (PluginBase p : pluginsInCategory) { if (!p.getName().equals(((PluginBase) activePump).getName())) { @@ -291,17 +299,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } } - // PluginBase.TEMPBASAL - pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TEMPBASAL); - activeTempBasals = (TempBasalsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TEMPBASAL); - if (Config.logConfigBuilder && activeTempBasals != null) - log.debug("Selected tempbasal interface: " + ((PluginBase) activeTempBasals).getName()); - for (PluginBase p : pluginsInCategory) { - if (!p.getName().equals(((PluginBase) activeTempBasals).getName())) { - p.setFragmentVisible(PluginBase.TEMPBASAL, false); - } - } - // PluginBase.TREATMENT pluginsInCategory = MainApp.getSpecificPluginsList(PluginBase.TREATMENT); activeTreatments = (TreatmentsInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.TREATMENT); @@ -358,23 +355,9 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } @Override - public boolean isTempBasalInProgress() { - if (activePump != null) - return activePump.isTempBasalInProgress(); - else return false; - } - - @Override - public boolean isExtendedBoluslInProgress() { - if (activePump != null) - return activePump.isExtendedBoluslInProgress(); - else return false; - } - - @Override - public int setNewBasalProfile(NSProfile profile) { + public int setNewBasalProfile(Profile profile) { // Compare with pump limits - NSProfile.BasalValue[] basalValues = profile.getBasalValues(); + Profile.BasalValue[] basalValues = profile.getBasalValues(); for (int index = 0; index < basalValues.length; index++) { if (basalValues[index].value < getPumpDescription().basalMinimumRate) { @@ -396,7 +379,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } @Override - public boolean isThisProfileSet(NSProfile profile) { + public boolean isThisProfileSet(Profile profile) { if (activePump != null) return activePump.isThisProfileSet(profile); else return true; @@ -423,50 +406,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return 0d; } - @Override - public double getTempBasalAbsoluteRate() { - if (activePump != null) - return activePump.getTempBasalAbsoluteRate(); - else - return 0d; - } - - @Override - public double getTempBasalRemainingMinutes() { - if (activePump != null) - return activePump.getTempBasalRemainingMinutes(); - else - return 0d; - } - - @Override - public TempBasal getTempBasal(Date time) { - if (activePump != null) - return activePump.getTempBasal(time); - else - return null; - } - - @Override - public TempBasal getTempBasal() { - if (activePump != null) - return activePump.getTempBasal(); - else - return null; - } - - @Override - public TempBasal getExtendedBolus() { - if (activePump != null) - return activePump.getExtendedBolus(); - else - return null; - } - - public PumpEnactResult deliverTreatmentFromBolusWizard(Context context, Double insulin, Integer carbs, Double glucose, String glucoseType, int carbTime, JSONObject boluscalc) { - mWakeLock.acquire(); - PumpEnactResult result; - if (activePump != null) { + /* + public PumpEnactResult deliverTreatmentFromBolusWizard(InsulinInterface insulinType, Context context, Double insulin, Integer carbs, Double glucose, String glucoseType, int carbTime, JSONObject boluscalc) { + mWakeLock.acquire(); + PumpEnactResult result; insulin = applyBolusConstraints(insulin); carbs = applyCarbsConstraints(carbs); @@ -479,53 +422,61 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain MainApp.bus().post(new EventBolusRequested(insulin)); - result = activePump.deliverTreatment(insulin, carbs, context); + result = activePump.deliverTreatment(insulinType, insulin, carbs, context); BolusProgressDialog.bolusEnded = true; MainApp.bus().post(new EventDismissBolusprogressIfRunning(result)); if (result.success) { - Treatment t = new Treatment(); + Treatment t = new Treatment(insulinType); t.insulin = result.bolusDelivered; if (carbTime == 0) t.carbs = (double) result.carbsDelivered; // with different carbTime record will come back from nightscout - t.created_at = new Date(); + t.date = new Date().getTime(); t.mealBolus = result.carbsDelivered > 0; - MainApp.getDbHelper().create(t); - t.setTimeIndex(t.getTimeIndex()); + addToHistoryTreatment(t); t.carbs = (double) result.carbsDelivered; - uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc); + NSUpload.uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc); } - } else { - if (Config.logCongigBuilderActions) - log.debug("Creating treatment: " + insulin + " carbs: " + carbs); - Treatment t = new Treatment(); - t.insulin = insulin; - t.carbs = (double) carbs; - t.created_at = new Date(); - t.mealBolus = t.carbs > 0; - MainApp.getDbHelper().create(t); - t.setTimeIndex(t.getTimeIndex()); - t.sendToNSClient(); - result = new PumpEnactResult(); - result.success = true; - result.bolusDelivered = insulin; - result.carbsDelivered = carbs; + mWakeLock.release(); + return result; } + */ + @Override + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { + mWakeLock.acquire(); + PumpEnactResult result; + detailedBolusInfo.insulin = applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.carbs = applyCarbsConstraints((int) detailedBolusInfo.carbs); + + BolusProgressDialog bolusProgressDialog = null; + if (detailedBolusInfo.context != null) { + bolusProgressDialog = new BolusProgressDialog(); + bolusProgressDialog.setInsulin(detailedBolusInfo.insulin); + bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress"); + } + + MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); + + result = activePump.deliverTreatment(detailedBolusInfo); + + BolusProgressDialog.bolusEnded = true; + MainApp.bus().post(new EventDismissBolusprogressIfRunning(result)); + mWakeLock.release(); return result; } - @Override - public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) { - return deliverTreatment(insulin, carbs, context, true); - } + /* + @Override + public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context) { + return deliverTreatment(insulinType, insulin, carbs, context, true); + } - public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context, boolean createTreatment) { - mWakeLock.acquire(); - PumpEnactResult result; - if (activePump != null) { + public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context, boolean createTreatment) { + mWakeLock.acquire(); + PumpEnactResult result; insulin = applyBolusConstraints(insulin); carbs = applyCarbsConstraints(carbs); @@ -544,7 +495,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain MainApp.bus().post(new EventBolusRequested(insulin)); - result = activePump.deliverTreatment(insulin, carbs, context); + result = activePump.deliverTreatment(insulinType, insulin, carbs, context); BolusProgressDialog.bolusEnded = true; @@ -554,36 +505,19 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain log.debug("deliverTreatment insulin: " + insulin + " carbs: " + carbs + " success: " + result.success + " enacted: " + result.enacted + " bolusDelivered: " + result.bolusDelivered); if (result.success && createTreatment) { - Treatment t = new Treatment(); + Treatment t = new Treatment(insulinType); t.insulin = result.bolusDelivered; t.carbs = (double) result.carbsDelivered; - t.created_at = new Date(); + t.date = new Date().getTime(); t.mealBolus = t.carbs > 0; - MainApp.getDbHelper().create(t); - t.setTimeIndex(t.getTimeIndex()); - t.sendToNSClient(); + addToHistoryTreatment(t); + NSUpload.uploadTreatment(t); } - } else { - if (Config.logCongigBuilderActions) - log.debug("Creating treatment: " + insulin + " carbs: " + carbs); - Treatment t = new Treatment(); - t.insulin = insulin; - t.carbs = (double) carbs; - t.created_at = new Date(); - t.mealBolus = t.carbs > 0; - MainApp.getDbHelper().create(t); - t.setTimeIndex(t.getTimeIndex()); - t.sendToNSClient(); - result = new PumpEnactResult(); - result.success = true; - result.bolusDelivered = insulin; - result.carbsDelivered = carbs; + mWakeLock.release(); + return result; } - mWakeLock.release(); - return result; - } - + */ @Override public void stopBolusDelivering() { activePump.stopBolusDelivering(); @@ -602,14 +536,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain PumpEnactResult result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes); if (Config.logCongigBuilderActions) log.debug("setTempBasalAbsolute rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted); - if (result.enacted && result.success) { - if (result.isPercent) { - uploadTempBasalStartPercent(result.percent, result.duration); - } else { - uploadTempBasalStartAbsolute(result.absolute, result.duration); - } - MainApp.bus().post(new EventTempBasalChange()); - } return result; } @@ -626,10 +552,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain PumpEnactResult result = activePump.setTempBasalPercent(percentAfterConstraints, durationInMinutes); if (Config.logCongigBuilderActions) log.debug("setTempBasalPercent percent: " + percentAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted); - if (result.enacted && result.success) { - uploadTempBasalStartPercent(result.percent, result.duration); - MainApp.bus().post(new EventTempBasalChange()); - } return result; } @@ -639,10 +561,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain PumpEnactResult result = activePump.setExtendedBolus(rateAfterConstraints, durationInMinutes); if (Config.logCongigBuilderActions) log.debug("setExtendedBolus rate: " + rateAfterConstraints + " durationInMinutes: " + durationInMinutes + " success: " + result.success + " enacted: " + result.enacted); - if (result.enacted && result.success) { - uploadExtendedBolus(result.bolusDelivered, result.duration); - MainApp.bus().post(new EventTreatmentChange()); - } return result; } @@ -651,10 +569,6 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain PumpEnactResult result = activePump.cancelTempBasal(); if (Config.logCongigBuilderActions) log.debug("cancelTempBasal success: " + result.success + " enacted: " + result.enacted); - if (result.enacted && result.success) { - uploadTempBasalEnd(); - MainApp.bus().post(new EventTempBasalChange()); - } return result; } @@ -672,6 +586,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain * @param request * @return */ + public PumpEnactResult applyAPSRequest(APSResult request) { request.rate = applyBasalConstraints(request.rate); PumpEnactResult result; @@ -711,10 +626,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: Basal set correctly"); } - } else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRate()) < 0.05) { + } else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < 0.05) { result = new PumpEnactResult(); - result.absolute = getTempBasalAbsoluteRate(); - result.duration = activePump.getTempBasal().getPlannedRemainingMinutes(); + result.absolute = getTempBasalAbsoluteRateHistory(); + result.duration = getTempBasalFromHistory(new Date().getTime()).getPlannedRemainingMinutes(); result.enacted = false; result.comment = "Temp basal set correctly"; result.success = true; @@ -767,6 +682,13 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } } + @Override + public boolean isFakingTempsByExtendedBoluses() { + if (Config.NSCLIENT) + return false; + return activePump.isFakingTempsByExtendedBoluses(); + } + /** * Constraints interface **/ @@ -883,272 +805,243 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return maxIobAfterConstrain; } - public void uploadTempBasalStartAbsolute(Double absolute, double durationInMinutes) { - try { - Context context = MainApp.instance().getApplicationContext(); - JSONObject data = new JSONObject(); - data.put("eventType", "Temp Basal"); - data.put("duration", durationInMinutes); - data.put("absolute", absolute); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); - data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + absolute + "u/h " + durationInMinutes + " min"); // ECOR - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); - } catch (JSONException e) { - e.printStackTrace(); - } + // ****** Treatments interface ***** + @Override + public void updateTotalIOBTreatments() { + activeTreatments.updateTotalIOBTreatments(); } - public void uploadTempBasalStartPercent(Integer percent, double durationInMinutes) { - try { - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - boolean useAbsolute = SP.getBoolean("ns_sync_use_absolute", false); - if (useAbsolute) { - double absolute = getBaseBasalRate() * percent / 100d; - uploadTempBasalStartAbsolute(absolute, durationInMinutes); + @Override + public void updateTotalIOBTempBasals() { + activeTreatments.updateTotalIOBTempBasals(); + } + + @Override + public IobTotal getLastCalculationTreatments() { + return activeTreatments.getLastCalculationTreatments(); + } + + @Override + public IobTotal getCalculationToTimeTreatments(long time) { + return activeTreatments.getCalculationToTimeTreatments(time); + } + + @Override + public IobTotal getLastCalculationTempBasals() { + return activeTreatments.getLastCalculationTempBasals(); + } + + @Override + public IobTotal getCalculationToTimeTempBasals(long time) { + return activeTreatments.getCalculationToTimeTempBasals(time); + } + + @Override + public MealData getMealData() { + return activeTreatments.getMealData(); + } + + @Override + public List getTreatmentsFromHistory() { + return activeTreatments.getTreatmentsFromHistory(); + } + + @Override + public List getTreatments5MinBackFromHistory(long time) { + return activeTreatments.getTreatments5MinBackFromHistory(time); + } + + @Override + public boolean isInHistoryRealTempBasalInProgress() { + return activeTreatments.isInHistoryRealTempBasalInProgress(); + } + + @Override + @Nullable + public TemporaryBasal getRealTempBasalFromHistory(long time) { + return activeTreatments.getRealTempBasalFromHistory(time); + } + + @Override + public boolean isTempBasalInProgress() { + return activeTreatments.isTempBasalInProgress(); + } + + @Override + @Nullable + public TemporaryBasal getTempBasalFromHistory(long time) { + return activeTreatments.getTempBasalFromHistory(time); + } + + @Override + public double getTempBasalAbsoluteRateHistory() { + return activeTreatments.getTempBasalAbsoluteRateHistory(); + } + + @Override + public double getTempBasalRemainingMinutesFromHistory() { + return activeTreatments.getTempBasalRemainingMinutesFromHistory(); + } + + @Override + public OverlappingIntervals getTemporaryBasalsFromHistory() { + return activeTreatments.getTemporaryBasalsFromHistory(); + } + + @Override + public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { + boolean newRecordCreated = activeTreatments.addToHistoryTempBasal(tempBasal); + if (newRecordCreated) { + if (tempBasal.durationInMinutes == 0) + NSUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); + else if (tempBasal.isAbsolute) + NSUpload.uploadTempBasalStartAbsolute(tempBasal, null); + else + NSUpload.uploadTempBasalStartPercent(tempBasal); + } + return newRecordCreated; + } + + @Override + public boolean isInHistoryExtendedBoluslInProgress() { + return activeTreatments.isInHistoryExtendedBoluslInProgress(); + } + + @Override + @Nullable + public ExtendedBolus getExtendedBolusFromHistory(long time) { + return activeTreatments.getExtendedBolusFromHistory(time); + } + + @Override + public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) { + boolean newRecordCreated = activeTreatments.addToHistoryExtendedBolus(extendedBolus); + if (newRecordCreated) { + if (extendedBolus.durationInMinutes == 0) { + if (activePump.isFakingTempsByExtendedBoluses()) + NSUpload.uploadTempBasalEnd(extendedBolus.date, true, extendedBolus.pumpId); + else + NSUpload.uploadExtendedBolusEnd(extendedBolus.date, extendedBolus.pumpId); + } else if (activePump.isFakingTempsByExtendedBoluses()) + NSUpload.uploadTempBasalStartAbsolute(new TemporaryBasal(extendedBolus), extendedBolus.insulin); + else + NSUpload.uploadExtendedBolus(extendedBolus); + } + return newRecordCreated; + } + + @Override + public OverlappingIntervals getExtendedBolusesFromHistory() { + return activeTreatments.getExtendedBolusesFromHistory(); + } + + @Override + // return true if new record is created + public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo) { + if (!detailedBolusInfo.addToTreatments) + return false; + boolean newRecordCreated = activeTreatments.addToHistoryTreatment(detailedBolusInfo); + if (newRecordCreated) + NSUpload.uploadBolusWizardRecord(detailedBolusInfo); + return newRecordCreated; + } + + @Override + @Nullable + public TempTarget getTempTargetFromHistory(long time) { + return activeTreatments.getTempTargetFromHistory(time); + } + + @Override + public OverlappingIntervals getTempTargetsFromHistory() { + return activeTreatments.getTempTargetsFromHistory(); + } + + @Override + @Nullable + public ProfileSwitch getProfileSwitchFromHistory(long time) { + return activeTreatments.getProfileSwitchFromHistory(time); + } + + @Override + public ProfileIntervals getProfileSwitchesFromHistory() { + return activeTreatments.getProfileSwitchesFromHistory(); + } + + @Override + public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) { + activeTreatments.addToHistoryProfileSwitch(profileSwitch); + NSUpload.uploadProfileSwitch(profileSwitch); + } + + @Override + public long oldestDataAvailable() { + return activeTreatments.oldestDataAvailable(); + } + + public String getProfileName() { + return getProfileName(new Date().getTime()); + } + + public String getProfileName(long time) { + ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time); + if (profileSwitch != null) { + if (profileSwitch.profileJson != null) { + return profileSwitch.profileName; } else { - Context context = MainApp.instance().getApplicationContext(); - JSONObject data = new JSONObject(); - data.put("eventType", "Temp Basal"); - data.put("duration", durationInMinutes); - data.put("percent", percent - 100); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); - data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + percent + "% " + durationInMinutes + " min"); // ECOR - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); + Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName); + if (profile != null) + return profileSwitch.profileName; } - } catch (JSONException e) { - e.printStackTrace(); } + // Unable to determine profile, failover to default + String defaultProfile = activeProfile.getProfile().getDefaultProfileName(); + if (defaultProfile != null) + return defaultProfile; + // If default from plugin fails .... create empty + return "Default"; } - public void uploadTempBasalEnd() { - try { - Context context = MainApp.instance().getApplicationContext(); - JSONObject data = new JSONObject(); - data.put("eventType", "Temp Basal"); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); - data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalendnote)); // ECOR - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); - } catch (JSONException e) { - e.printStackTrace(); - } + public Profile getProfile() { + return getProfile(new Date().getTime()); } - public void uploadExtendedBolus(Double insulin, double durationInMinutes) { - try { - Context context = MainApp.instance().getApplicationContext(); - JSONObject data = new JSONObject(); - data.put("eventType", "Combo Bolus"); - data.put("duration", durationInMinutes); - data.put("splitNow", 0); - data.put("splitExt", 100); - data.put("enteredinsulin", insulin); - data.put("relative", insulin); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - public void uploadDeviceStatus() { - DeviceStatus deviceStatus = new DeviceStatus(); - try { - LoopPlugin.LastRun lastRun = LoopPlugin.lastRun; - if (lastRun != null && lastRun.lastAPSRun.getTime() > new Date().getTime() - 300 * 1000L) { - // do not send if result is older than 1 min - APSResult apsResult = lastRun.request; - apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun)); - deviceStatus.suggested = apsResult.json(); - - if (lastRun.request instanceof DetermineBasalResultMA) { - DetermineBasalResultMA result = (DetermineBasalResultMA) lastRun.request; - deviceStatus.iob = result.iob.json(); - deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun)); - } - - if (lastRun.request instanceof DetermineBasalResultAMA) { - DetermineBasalResultAMA result = (DetermineBasalResultAMA) lastRun.request; - deviceStatus.iob = result.iob.json(); - deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun)); - } - - if (lastRun.setByPump != null && lastRun.setByPump.enacted) { // enacted - deviceStatus.enacted = lastRun.request.json(); - deviceStatus.enacted.put("rate", lastRun.setByPump.json().get("rate")); - deviceStatus.enacted.put("duration", lastRun.setByPump.json().get("duration")); - deviceStatus.enacted.put("recieved", true); - JSONObject requested = new JSONObject(); - requested.put("duration", lastRun.request.duration); - requested.put("rate", lastRun.request.rate); - requested.put("temp", "absolute"); - deviceStatus.enacted.put("requested", requested); + public Profile getProfile(long time) { + //log.debug("Profile for: " + new Date(time).toLocaleString() + " : " + getProfileName(time)); + ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time); + if (profileSwitch != null) { + if (profileSwitch.profileJson != null) { + try { + return new Profile(new JSONObject(profileSwitch.profileJson)); + } catch (JSONException e) { + e.printStackTrace(); } } else { - log.debug("OpenAPS data too old to upload"); + Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName); + if (profile != null) + return profile; } - if (activePump != null) { - deviceStatus.device = "openaps://" + deviceID(); - JSONObject pumpstatus = getJSONStatus(); - if (pumpstatus != null) { - deviceStatus.pump = pumpstatus; - } - } - - int batteryLevel = BatteryLevel.getBatteryLevel(); - deviceStatus.uploaderBattery = batteryLevel; - - deviceStatus.created_at = DateUtil.toISOString(new Date()); - deviceStatus.sendToNSClient(); + } + // Unable to determine profile, failover to default + if (activeProfile.getProfile() == null) + return null; //app not initialized + Profile defaultProfile = activeProfile.getProfile().getDefaultProfile(); + if (defaultProfile != null) + return defaultProfile; + // If default from plugin fails .... create empty + try { + Notification noisf = new Notification(Notification.ISF_MISSING, MainApp.sResources.getString(R.string.isfmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(noisf)); + Notification noic = new Notification(Notification.IC_MISSING, MainApp.sResources.getString(R.string.icmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(noic)); + Notification nobasal = new Notification(Notification.BASAL_MISSING, MainApp.sResources.getString(R.string.basalmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(nobasal)); + Notification notarget = new Notification(Notification.TARGET_MISSING, MainApp.sResources.getString(R.string.targetmissing), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notarget)); + return new Profile(new JSONObject("{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"20\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"20\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"6\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"8\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}}")); } catch (JSONException e) { e.printStackTrace(); } + return null; } - - public void uploadBolusWizardRecord(Treatment t, double glucose, String glucoseType, int carbTime, JSONObject boluscalc) { - JSONObject data = new JSONObject(); - try { - data.put("eventType", "Bolus Wizard"); - if (t.insulin != 0d) data.put("insulin", t.insulin); - if (t.carbs != 0d) data.put("carbs", t.carbs.intValue()); - data.put("created_at", DateUtil.toISOString(t.created_at)); - data.put("timeIndex", t.timeIndex); - if (glucose != 0d) data.put("glucose", glucose); - data.put("glucoseType", glucoseType); - data.put("boluscalc", boluscalc); - if (carbTime != 0) data.put("preBolus", carbTime); - } catch (JSONException e) { - e.printStackTrace(); - } - uploadCareportalEntryToNS(data); - } - - public static void uploadCareportalEntryToNS(JSONObject data) { - try { - if (data.has("preBolus") && data.has("carbs")) { - JSONObject prebolus = new JSONObject(); - prebolus.put("carbs", data.get("carbs")); - data.remove("carbs"); - prebolus.put("eventType", data.get("eventType")); - if (data.has("enteredBy")) prebolus.put("enteredBy", data.get("enteredBy")); - if (data.has("notes")) prebolus.put("notes", data.get("notes")); - long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime(); - Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L); - prebolus.put("created_at", DateUtil.toISOString(preBolusDate)); - uploadCareportalEntryToNS(prebolus); - } - Context context = MainApp.instance().getApplicationContext(); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - public static void removeCareportalEntryFromNS(String _id) { - try { - Context context = MainApp.instance().getApplicationContext(); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbRemove"); - bundle.putString("collection", "treatments"); - bundle.putString("_id", _id); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbRemove(intent, _id, ConfigBuilderPlugin.class); - } catch (Exception e) { - e.printStackTrace(); - } - - } - - public void uploadError(String error) { - Context context = MainApp.instance().getApplicationContext(); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - JSONObject data = new JSONObject(); - try { - data.put("eventType", "Announcement"); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("notes", error); - data.put("isAnnouncement", true); - } catch (JSONException e) { - e.printStackTrace(); - } - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), MsgError.class); - } - - public void uploadAppStart() { - if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) { - Context context = MainApp.instance().getApplicationContext(); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "treatments"); - JSONObject data = new JSONObject(); - try { - data.put("eventType", "Note"); - data.put("created_at", DateUtil.toISOString(new Date())); - data.put("notes", MainApp.sResources.getString(R.string.androidaps_start)); - } catch (JSONException e) { - e.printStackTrace(); - } - bundle.putString("data", data.toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, data.toString(), ConfigBuilderPlugin.class); - } - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java index 2321d8a955..3334267057 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Objectives; +package info.nightscout.androidaps.plugins.ConstraintsObjectives; import android.app.Activity; import android.content.Context; @@ -7,7 +7,6 @@ import android.support.v4.app.Fragment; import android.support.v7.widget.CardView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.text.Layout; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -24,9 +23,8 @@ import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; -public class ObjectivesFragment extends Fragment implements View.OnClickListener, FragmentBase { +public class ObjectivesFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(ObjectivesFragment.class); private static ObjectivesPlugin objectivesPlugin; @@ -44,15 +42,6 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener LinearLayout fake_layout; TextView reset; - @Override - public void onClick(View v) { - int id = v.getId(); - switch (id) { - default: - break; - } - } - public class RecyclerViewAdapter extends RecyclerView.Adapter { List objectives; @@ -237,16 +226,4 @@ public class ObjectivesFragment extends Fragment implements View.OnClickListener }); } - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java index 86cea210b4..b6f4e57acd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Objectives/ObjectivesPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.Objectives; +package info.nightscout.androidaps.plugins.ConstraintsObjectives; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -17,7 +17,6 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; /** * Created by mike on 05.08.2016. @@ -77,6 +76,16 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyFragment.java similarity index 63% rename from app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyFragment.java index 5742249206..07583e7622 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.SafetyFragment; +package info.nightscout.androidaps.plugins.ConstraintsSafety; import android.support.v4.app.Fragment; @@ -6,9 +6,7 @@ import android.support.v4.app.Fragment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import info.nightscout.androidaps.interfaces.FragmentBase; - -public class SafetyFragment extends Fragment implements FragmentBase{ +public class SafetyFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(SafetyFragment.class); private static SafetyPlugin safetyPlugin = new SafetyPlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java index 83ace20c71..213bba47fa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SafetyFragment/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.SafetyFragment; +package info.nightscout.androidaps.plugins.ConstraintsSafety; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,7 +10,7 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.HardLimits; import info.nightscout.utils.Round; import info.nightscout.utils.SP; @@ -57,6 +57,16 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return false; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { @@ -95,7 +105,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { Double origAbsoluteRate = absoluteRate; Double maxBasal = SP.getDouble("openapsma_max_basal", 1d); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return absoluteRate; if (absoluteRate < 0) absoluteRate = 0d; @@ -108,8 +118,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); } - if (absoluteRate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { - absoluteRate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; + if (absoluteRate > maxBasalMult * profile.getBasal()) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100; if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); } @@ -126,9 +136,9 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { Integer origPercentRate = percentRate; Double maxBasal = SP.getDouble("openapsma_max_basal", 1d); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return percentRate; - Double currentBasal = profile.getBasal(profile.secondsFromMidnight()); + Double currentBasal = profile.getBasal(); Double absoluteRate = currentBasal * ((double) percentRate / 100); @@ -146,8 +156,8 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { if (Config.logConstraintsChanges && origPercentRate != Constants.basalPercentOnlyForCheckLimit) log.debug("Limiting rate " + origRate + " by maxBasal preference to " + absoluteRate + "U/h"); } - if (absoluteRate > maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight())) { - absoluteRate = Math.floor(maxBasalMult * profile.getBasal(NSProfile.secondsFromMidnight()) * 100) / 100; + if (absoluteRate > maxBasalMult * profile.getBasal()) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100; if (Config.logConstraintsChanges && origPercentRate != Constants.basalPercentOnlyForCheckLimit) log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingGlucose.java deleted file mode 100644 index 1327445b19..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingGlucose.java +++ /dev/null @@ -1,29 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingGlucose extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingGlucose.class); - - public MsgSettingGlucose() { - SetCommand(0x3209); - } - - public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().units = intFromBuff(bytes, 0, 1); - DanaRPlugin.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1); - - if (Config.logDanaMessageDetail) { - log.debug("Pump units: " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Easy basal mode: " + DanaRPlugin.getDanaRPump().easyBasalMode); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingMaxValues.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingMaxValues.java deleted file mode 100644 index b5ced45f67..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingMaxValues.java +++ /dev/null @@ -1,32 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; - - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingMaxValues extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingMaxValues.class); - - public MsgSettingMaxValues() { - SetCommand(0x3205); - } - - public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().maxBolus = intFromBuff(bytes, 0, 2) / 100d; - DanaRPlugin.getDanaRPump().maxBasal = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100; - - if (Config.logDanaMessageDetail) { - log.debug("Max bolus: " + DanaRPlugin.getDanaRPump().maxBolus); - log.debug("Max basal: " + DanaRPlugin.getDanaRPump().maxBasal); - log.debug("Total daily max units: " + DanaRPlugin.getDanaRPump().maxDailyTotalUnits); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingMeal.java deleted file mode 100644 index a588479869..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingMeal.java +++ /dev/null @@ -1,40 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -/** - * Created by mike on 13.12.2016. - */ - -public class MsgSettingMeal extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingMeal.class); - - public MsgSettingMeal() { - SetCommand(0x3203); - } - - public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); - pump.basalStep = intFromBuff(bytes, 0, 1) / 100d; - pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d; - boolean bolusEnabled = intFromBuff(bytes, 2, 1) == 1; - int melodyTime = intFromBuff(bytes, 3, 1); - int blockTime = intFromBuff(bytes, 4, 1); - pump.isConfigUD = intFromBuff(bytes, 5, 1) == 1; - - if (Config.logDanaMessageDetail) { - log.debug("Basal step: " + pump.basalStep); - log.debug("Bolus step: " + pump.bolusStep); - log.debug("Bolus enabled: " + bolusEnabled); - log.debug("Melody time: " + melodyTime); - log.debug("Block time: " + blockTime); - log.debug("Is Config U/d: " + pump.isConfigUD); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingProfileRatios.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingProfileRatios.java deleted file mode 100644 index 56e7d6c6cb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingProfileRatios.java +++ /dev/null @@ -1,44 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingProfileRatios extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatios.class); - - public MsgSettingProfileRatios() { - SetCommand(0x3204); - } - - public void handleMessage(byte[] bytes) { - if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2); - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2); - DanaRPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1); - } else { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d; - DanaRPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1); - } - - if (Config.logDanaMessageDetail) { - log.debug("Pump units (saved): " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump CIR: " + DanaRPlugin.getDanaRPump().currentCIR); - log.debug("Current pump CF: " + DanaRPlugin.getDanaRPump().currentCF); - log.debug("Current pump AI: " + DanaRPlugin.getDanaRPump().currentAI); - log.debug("Current pump target: " + DanaRPlugin.getDanaRPump().currentTarget); - log.debug("Current pump AIDR: " + DanaRPlugin.getDanaRPump().currentAIDR); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingProfileRatiosAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingProfileRatiosAll.java deleted file mode 100644 index 09b386ab11..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingProfileRatiosAll.java +++ /dev/null @@ -1,55 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingProfileRatiosAll extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatiosAll.class); - - public MsgSettingProfileRatiosAll() { - SetCommand(0x320D); - } - - public void handleMessage(byte[] bytes) { - if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) { - DanaRPlugin.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2); - DanaRPlugin.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2); - DanaRPlugin.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2); - DanaRPlugin.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2); - DanaRPlugin.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2); - DanaRPlugin.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2); - DanaRPlugin.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2); - } else { - DanaRPlugin.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2); - DanaRPlugin.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2) / 100d; - DanaRPlugin.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2); - DanaRPlugin.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2) / 100d; - DanaRPlugin.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2); - DanaRPlugin.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2) / 100d; - } - - if (Config.logDanaMessageDetail) { - log.debug("Pump units: " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump morning CIR: " + DanaRPlugin.getDanaRPump().morningCIR); - log.debug("Current pump morning CF: " + DanaRPlugin.getDanaRPump().morningCF); - log.debug("Current pump afternoon CIR: " + DanaRPlugin.getDanaRPump().afternoonCIR); - log.debug("Current pump afternoon CF: " + DanaRPlugin.getDanaRPump().afternoonCF); - log.debug("Current pump evening CIR: " + DanaRPlugin.getDanaRPump().eveningCIR); - log.debug("Current pump evening CF: " + DanaRPlugin.getDanaRPump().eveningCF); - log.debug("Current pump night CIR: " + DanaRPlugin.getDanaRPump().nightCIR); - log.debug("Current pump night CF: " + DanaRPlugin.getDanaRPump().nightCF); - } - - DanaRPlugin.getDanaRPump().createConvertedProfile(); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatus.java deleted file mode 100644 index e7f5472feb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatus.java +++ /dev/null @@ -1,38 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; - -public class MsgStatus extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatus.class); - - public MsgStatus() { - SetCommand(0x020B); - } - - public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d; - DanaRPlugin.getDanaRPump().isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1; - DanaRPlugin.getDanaRPump().extendedBolusMinutes = intFromBuff(bytes, 4, 2); - DanaRPlugin.getDanaRPump().extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d; - Double lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d; - if (lastBolusAmount != 0d) { - DanaRPlugin.getDanaRPump().lastBolusTime = dateTimeFromBuff(bytes, 8); - DanaRPlugin.getDanaRPump().lastBolusAmount = lastBolusAmount; - } - DanaRPlugin.getDanaRPump().iob = intFromBuff(bytes, 15, 2) / 100d; - - if (Config.logDanaMessageDetail) { - log.debug("Daily total: " + DanaRPlugin.getDanaRPump().dailyTotalUnits); - log.debug("Is extended bolus running: " + DanaRPlugin.getDanaRPump().isExtendedInProgress); - log.debug("Extended bolus min: " + DanaRPlugin.getDanaRPump().extendedBolusMinutes); - log.debug("Extended bolus amount: " + DanaRPlugin.getDanaRPump().extendedBolusAmount); - log.debug("Last bolus time: " + DanaRPlugin.getDanaRPump().lastBolusTime); - log.debug("Last bolus amount: " + DanaRPlugin.getDanaRPump().lastBolusAmount); - log.debug("IOB: " + DanaRPlugin.getDanaRPump().iob); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusBolusExtended.java deleted file mode 100644 index 3ffef7862f..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusBolusExtended.java +++ /dev/null @@ -1,111 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import android.support.annotation.NonNull; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -public class MsgStatusBolusExtended extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended.class); - - public MsgStatusBolusExtended() { - SetCommand(0x0207); - } - - public void handleMessage(byte[] bytes) { - boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1; - int extendedBolusHalfHours = intFromBuff(bytes, 1, 1); - int extendedBolusMinutes = extendedBolusHalfHours * 30; - - double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d; - int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3); - - int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60; - double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d; - Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0); - int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes; - - DanaRPlugin.getDanaRPump().isExtendedInProgress = isExtendedInProgress; - DanaRPlugin.getDanaRPump().extendedBolusMinutes = extendedBolusMinutes; - DanaRPlugin.getDanaRPump().extendedBolusAmount = extendedBolusAmount; - DanaRPlugin.getDanaRPump().extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; - DanaRPlugin.getDanaRPump().extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; - DanaRPlugin.getDanaRPump().extendedBolusStart = extendedBolusStart; - DanaRPlugin.getDanaRPump().extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; - - updateExtendedBolusInDB(); - - if (Config.logDanaMessageDetail) { - log.debug("Is extended bolus running: " + isExtendedInProgress); - log.debug("Extended bolus min: " + extendedBolusMinutes); - log.debug("Extended bolus amount: " + extendedBolusAmount); - log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes); - log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate); - log.debug("Extended bolus start: " + extendedBolusStart); - log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes); - } - } - - @NonNull - private Date getDateFromSecAgo(int tempBasalAgoSecs) { - return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); - } - - public static void updateExtendedBolusInDB() { - DanaRPlugin DanaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRPump danaRPump = DanaRPlugin.getDanaRPump(); - Date now = new Date(); - - try { - - if (DanaRPlugin.isExtendedBoluslInProgress()) { - TempBasal extendedBolus = DanaRPlugin.getExtendedBolus(); - if (danaRPump.isExtendedInProgress) { - if (extendedBolus.absolute != danaRPump.extendedBolusAbsoluteRate) { - // Close current extended - extendedBolus.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); - // Create new - TempBasal newExtended = new TempBasal(); - newExtended.timeStart = now; - newExtended.absolute = danaRPump.extendedBolusAbsoluteRate; - newExtended.isAbsolute = true; - newExtended.duration = danaRPump.extendedBolusMinutes; - newExtended.isExtended = true; - MainApp.getDbHelper().getDaoTempBasals().create(newExtended); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - // Close curent temp basal - extendedBolus.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - if (danaRPump.isExtendedInProgress) { - // Create new - TempBasal newExtended = new TempBasal(); - newExtended.timeStart = now; - newExtended.absolute = danaRPump.extendedBolusAbsoluteRate; - newExtended.isAbsolute = true; - newExtended.duration = danaRPump.extendedBolusMinutes; - newExtended.isExtended = true; - MainApp.getDbHelper().getDaoTempBasals().create(newExtended); - MainApp.bus().post(new EventTempBasalChange()); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusProfile.java deleted file mode 100644 index 5006a7b1ea..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusProfile.java +++ /dev/null @@ -1,42 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgStatusProfile extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusProfile.class); - - public MsgStatusProfile() { - SetCommand(0x0204); - } - - public void handleMessage(byte[] bytes) { - if (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL) { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2); - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2); - } else { - DanaRPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d; - } - - if (Config.logDanaMessageDetail) { - log.debug("Pump units (saved): " + (DanaRPlugin.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump CIR: " + DanaRPlugin.getDanaRPump().currentCIR); - log.debug("Current pump CF: " + DanaRPlugin.getDanaRPump().currentCF); - log.debug("Current pump AI: " + DanaRPlugin.getDanaRPump().currentAI); - log.debug("Current pump target: " + DanaRPlugin.getDanaRPump().currentTarget); - log.debug("Current pump AIDR: " + DanaRPlugin.getDanaRPump().currentAIDR); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusTempBasal.java deleted file mode 100644 index cdcac0c365..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusTempBasal.java +++ /dev/null @@ -1,102 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import android.support.annotation.NonNull; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; - -public class MsgStatusTempBasal extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal.class); - - public MsgStatusTempBasal() { - SetCommand(0x0205); - } - - public void handleMessage(byte[] bytes) { - boolean isTempBasalInProgress = intFromBuff(bytes, 0, 1) == 1; - int tempBasalPercent = intFromBuff(bytes, 1, 1); - int tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60; - int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3); - int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60; - Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0); - - DanaRPlugin.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress; - DanaRPlugin.getDanaRPump().tempBasalPercent = tempBasalPercent; - DanaRPlugin.getDanaRPump().tempBasalRemainingMin = tempBasalRemainingMin; - DanaRPlugin.getDanaRPump().tempBasalTotalSec = tempBasalTotalSec; - DanaRPlugin.getDanaRPump().tempBasalStart = tempBasalStart; - - updateTempBasalInDB(); - - if (Config.logDanaMessageDetail) { - log.debug("Is temp basal running: " + isTempBasalInProgress); - log.debug("Current temp basal percent: " + tempBasalPercent); - log.debug("Current temp basal remaining min: " + tempBasalRemainingMin); - log.debug("Current temp basal total sec: " + tempBasalTotalSec); - log.debug("Current temp basal start: " + tempBasalStart); - } - } - - @NonNull - private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) { - return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); - } - - public static void updateTempBasalInDB() { - DanaRPlugin DanaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRPump danaRPump = DanaRPlugin.getDanaRPump(); - Date now = new Date(); - - try { - - if (DanaRPlugin.isRealTempBasalInProgress()) { - TempBasal tempBasal = DanaRPlugin.getRealTempBasal(); - if (danaRPump.isTempBasalInProgress) { - if (tempBasal.percent != danaRPump.tempBasalPercent) { - // Close current temp basal - tempBasal.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); - // Create new - TempBasal newTempBasal = new TempBasal(); - newTempBasal.timeStart = now; - newTempBasal.percent = danaRPump.tempBasalPercent; - newTempBasal.isAbsolute = false; - newTempBasal.duration = danaRPump.tempBasalTotalSec / 60; - newTempBasal.isExtended = false; - MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - // Close current temp basal - tempBasal.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - if (danaRPump.isTempBasalInProgress) { - // Create new - TempBasal newTempBasal = new TempBasal(); - newTempBasal.timeStart = now; - newTempBasal.percent = danaRPump.tempBasalPercent; - newTempBasal.isAbsolute = false; - newTempBasal.duration = danaRPump.tempBasalTotalSec / 60; - newTempBasal.isExtended = false; - MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal); - MainApp.bus().post(new EventTempBasalChange()); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanPump.java deleted file mode 100644 index 6786cc4c2e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanPump.java +++ /dev/null @@ -1,167 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.text.DecimalFormat; -import java.util.Date; - -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.SP; - -/** - * Created by mike on 04.07.2016. - */ -public class DanaRKoreanPump { - public static final int UNITS_MGDL = 0; - public static final int UNITS_MMOL = 1; - - public static final int DELIVERY_PRIME = 0x01; - public static final int DELIVERY_STEP_BOLUS = 0x02; - public static final int DELIVERY_BASAL = 0x04; - public static final int DELIVERY_EXT_BOLUS = 0x08; - - public static final String PROFILE_PREFIX = "DanaR-"; - - public Date lastConnection = new Date(0); - public Date lastSettingsRead = new Date(0); - - // Info - public String serialNumber = ""; - public Date shippingDate = new Date(0); - public String shippingCountry = ""; - public boolean isNewPump = true; - public int password = -1; - public Date pumpTime = new Date(0); - - public static final int DOMESTIC_MODEL = 0x01; - public static final int EXPORT_MODEL = 0x03; - public int model; - public int protocol; - public int productCode; - - public boolean pumpSuspended; - - public boolean isConfigUD; - public boolean isExtendedBolusEnabled; - public boolean isEasyModeEnabled; - - // Status - public double dailyTotalUnits; - public int maxDailyTotalUnits; - - public double bolusStep; - public double basalStep; - - public double iob; - - public double reservoirRemainingUnits; - public int batteryRemaining; - - public double currentBasal; - - public boolean isTempBasalInProgress; - public int tempBasalPercent; - public int tempBasalRemainingMin; - public int tempBasalTotalSec; - public Date tempBasalStart; - - public boolean isExtendedInProgress; - public int extendedBolusMinutes; - public double extendedBolusAmount; - public double extendedBolusAbsoluteRate; - public int extendedBolusSoFarInMinutes; - public Date extendedBolusStart; - public int extendedBolusRemainingMinutes; - - // Profile - public int units; - public int easyBasalMode; - public boolean basal48Enable = false; - public int currentCIR; - public double currentCF; - public double currentAI; - public double currentTarget; - public int currentAIDR; - - public int morningCIR; - public double morningCF; - public int afternoonCIR; - public double afternoonCF; - public int eveningCIR; - public double eveningCF; - public int nightCIR; - public double nightCF; - - - public int activeProfile = 0; - public double[][] pumpProfiles = null; - - //Limits - public double maxBolus; - public double maxBasal; - - public NSProfile createConvertedProfile() { - JSONObject json = new JSONObject(); - JSONObject store = new JSONObject(); - JSONObject profile = new JSONObject(); - -// Morning / 6:00–10:59 -// Afternoon / 11:00–16:59 -// Evening / 17:00–21:59 -// Night / 22:00–5:59 - - double dia = SP.getDouble(R.string.key_danarprofile_dia, 3d); - - try { - json.put("defaultProfile", PROFILE_PREFIX + (activeProfile + 1)); - json.put("store", store); - profile.put("dia", dia); - - JSONArray carbratios = new JSONArray(); - carbratios.put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", nightCIR)); - carbratios.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCIR)); - carbratios.put(new JSONObject().put("time", "11:00").put("timeAsSeconds", 11 * 3600).put("value", afternoonCIR)); - carbratios.put(new JSONObject().put("time", "14:00").put("timeAsSeconds", 17 * 3600).put("value", eveningCIR)); - carbratios.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCIR)); - profile.put("carbratio", carbratios); - - JSONArray sens = new JSONArray(); - sens.put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", nightCF)); - sens.put(new JSONObject().put("time", "06:00").put("timeAsSeconds", 6 * 3600).put("value", morningCF)); - sens.put(new JSONObject().put("time", "11:00").put("timeAsSeconds", 11 * 3600).put("value", afternoonCF)); - sens.put(new JSONObject().put("time", "17:00").put("timeAsSeconds", 17 * 3600).put("value", eveningCF)); - sens.put(new JSONObject().put("time", "22:00").put("timeAsSeconds", 22 * 3600).put("value", nightCF)); - profile.put("sens", sens); - - JSONArray basals = new JSONArray(); - int basalValues = basal48Enable ? 48 : 24; - int basalIncrement = basal48Enable ? 30 * 60 : 60 * 60; - for (int h = 0; h < basalValues; h++) { - String time; - DecimalFormat df = new DecimalFormat("00"); - if (basal48Enable) { - time = df.format((long) h / 2) + ":" + df.format(30 * (h % 2)); - } else { - time = df.format(h) + ":00"; - } - basals.put(new JSONObject().put("time", time).put("timeAsSeconds", h * basalIncrement).put("value", pumpProfiles[activeProfile][h])); - } - profile.put("basal", basals); - - profile.put("target_low", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", currentTarget))); - profile.put("target_high", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", currentTarget))); - profile.put("units", units == UNITS_MGDL ? Constants.MGDL : Constants.MMOL); - store.put(PROFILE_PREFIX + (activeProfile + 1), profile); - } catch (JSONException e) { - e.printStackTrace(); - } catch (Exception e) { - return null; - } - return new NSProfile(json, PROFILE_PREFIX + (activeProfile + 1)); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingGlucose.java deleted file mode 100644 index 8ebc972495..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingGlucose.java +++ /dev/null @@ -1,30 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingGlucose extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingGlucose.class); - - public MsgSettingGlucose() { - SetCommand(0x3209); - } - - public void handleMessage(byte[] bytes) { - DanaRKoreanPlugin.getDanaRPump().units = intFromBuff(bytes, 0, 1); - DanaRKoreanPlugin.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1); - - if (Config.logDanaMessageDetail) { - log.debug("Pump units: " + (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Easy basal mode: " + DanaRKoreanPlugin.getDanaRPump().easyBasalMode); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingMaxValues.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingMaxValues.java deleted file mode 100644 index 428881e715..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingMaxValues.java +++ /dev/null @@ -1,33 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; - - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingMaxValues extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingMaxValues.class); - - public MsgSettingMaxValues() { - SetCommand(0x3205); - } - - public void handleMessage(byte[] bytes) { - DanaRKoreanPlugin.getDanaRPump().maxBolus = intFromBuff(bytes, 0, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().maxBasal = intFromBuff(bytes, 2, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100; - - if (Config.logDanaMessageDetail) { - log.debug("Max bolus: " + DanaRKoreanPlugin.getDanaRPump().maxBolus); - log.debug("Max basal: " + DanaRKoreanPlugin.getDanaRPump().maxBasal); - log.debug("Total daily max units: " + DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingProfileRatios.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingProfileRatios.java deleted file mode 100644 index e023c1bb5b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingProfileRatios.java +++ /dev/null @@ -1,45 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingProfileRatios extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatios.class); - - public MsgSettingProfileRatios() { - SetCommand(0x3204); - } - - public void handleMessage(byte[] bytes) { - if (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL) { - DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2); - DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2); - DanaRKoreanPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1); - } else { - DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentAIDR = intFromBuff(bytes, 8, 1); - } - - if (Config.logDanaMessageDetail) { - log.debug("Pump units (saved): " + (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump CIR: " + DanaRKoreanPlugin.getDanaRPump().currentCIR); - log.debug("Current pump CF: " + DanaRKoreanPlugin.getDanaRPump().currentCF); - log.debug("Current pump AI: " + DanaRKoreanPlugin.getDanaRPump().currentAI); - log.debug("Current pump target: " + DanaRKoreanPlugin.getDanaRPump().currentTarget); - log.debug("Current pump AIDR: " + DanaRKoreanPlugin.getDanaRPump().currentAIDR); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingPumpTime.java deleted file mode 100644 index 359ffb924e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingPumpTime.java +++ /dev/null @@ -1,35 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; - -public class MsgSettingPumpTime extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class); - - public MsgSettingPumpTime() { - SetCommand(0x320A); - } - - public void handleMessage(byte[] bytes) { - Date time = - new Date( - 100 + intFromBuff(bytes, 5, 1), - intFromBuff(bytes, 4, 1) - 1, - intFromBuff(bytes, 3, 1), - intFromBuff(bytes, 2, 1), - intFromBuff(bytes, 1, 1), - intFromBuff(bytes, 0, 1) - ); - - if (Config.logDanaMessageDetail) - log.debug("Pump time: " + time); - - DanaRKoreanPlugin.getDanaRPump().pumpTime = time; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingShippingInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingShippingInfo.java deleted file mode 100644 index f222d86cbf..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingShippingInfo.java +++ /dev/null @@ -1,35 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgSettingShippingInfo extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingShippingInfo.class); - - public MsgSettingShippingInfo() { - SetCommand(0x3207); - } - - public void handleMessage(byte[] bytes) { - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); - pump.serialNumber = stringFromBuff(bytes, 0, 10); - pump.shippingDate = dateFromBuff(bytes, 10); - pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3); - if (Config.logDanaMessageDetail) { - log.debug("Serial number: " + pump.serialNumber); - log.debug("Shipping date: " + pump.shippingDate); - log.debug("Shipping country: " + pump.shippingCountry); - } - } -} - diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatus.java deleted file mode 100644 index bb4adaa58e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatus.java +++ /dev/null @@ -1,39 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; - -public class MsgStatus extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatus.class); - - public MsgStatus() { - SetCommand(0x020B); - } - - public void handleMessage(byte[] bytes) { - DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d; - DanaRKoreanPlugin.getDanaRPump().isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1; - DanaRKoreanPlugin.getDanaRPump().extendedBolusMinutes = intFromBuff(bytes, 4, 2); - DanaRKoreanPlugin.getDanaRPump().extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d; - Double lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d; -// if (lastBolusAmount != 0d) { -// DanaRKoreanPlugin.getDanaRPump().lastBolusTime = dateTimeFromBuff(bytes, 8); -// DanaRKoreanPlugin.getDanaRPump().lastBolusAmount = lastBolusAmount; -// } - DanaRKoreanPlugin.getDanaRPump().iob = intFromBuff(bytes, 15, 2) / 100d; - - if (Config.logDanaMessageDetail) { - log.debug("Daily total: " + DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits); - log.debug("Is extended bolus running: " + DanaRKoreanPlugin.getDanaRPump().isExtendedInProgress); - log.debug("Extended bolus min: " + DanaRKoreanPlugin.getDanaRPump().extendedBolusMinutes); - log.debug("Extended bolus amount: " + DanaRKoreanPlugin.getDanaRPump().extendedBolusAmount); -// log.debug("Last bolus time: " + DanaRKoreanPlugin.getDanaRPump().lastBolusTime); -// log.debug("Last bolus amount: " + DanaRKoreanPlugin.getDanaRPump().lastBolusAmount); - log.debug("IOB: " + DanaRKoreanPlugin.getDanaRPump().iob); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusBolusExtended.java deleted file mode 100644 index 1c740fd960..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusBolusExtended.java +++ /dev/null @@ -1,114 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import android.support.annotation.NonNull; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; - -public class MsgStatusBolusExtended extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended.class); - - public MsgStatusBolusExtended() { - SetCommand(0x0207); - } - - public void handleMessage(byte[] bytes) { - boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1; - int extendedBolusHalfHours = intFromBuff(bytes, 1, 1); - int extendedBolusMinutes = extendedBolusHalfHours * 30; - - double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d; - int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3); - int extendedBolusDeliveryPulse = intFromBuff(bytes, 7, 2); - int isEasyUIUserSleep = intFromBuff(bytes, 9, 1); - - int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60; - double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d; - Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0); - int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes; - - DanaRKoreanPlugin.getDanaRPump().isExtendedInProgress = isExtendedInProgress; - DanaRKoreanPlugin.getDanaRPump().extendedBolusMinutes = extendedBolusMinutes; - DanaRKoreanPlugin.getDanaRPump().extendedBolusAmount = extendedBolusAmount; - DanaRKoreanPlugin.getDanaRPump().extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; - DanaRKoreanPlugin.getDanaRPump().extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; - DanaRKoreanPlugin.getDanaRPump().extendedBolusStart = extendedBolusStart; - DanaRKoreanPlugin.getDanaRPump().extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; - - updateExtendedBolusInDB(); - - if (Config.logDanaMessageDetail) { - log.debug("Is extended bolus running: " + isExtendedInProgress); - log.debug("Extended bolus min: " + extendedBolusMinutes); - log.debug("Extended bolus amount: " + extendedBolusAmount); - log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes); - log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate); - log.debug("Extended bolus start: " + extendedBolusStart); - log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes); - } - } - - @NonNull - private Date getDateFromSecAgo(int tempBasalAgoSecs) { - return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); - } - - public static void updateExtendedBolusInDB() { - DanaRKoreanPlugin DanaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); - DanaRKoreanPump danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump(); - Date now = new Date(); - - try { - - if (DanaRKoreanPlugin.isExtendedBoluslInProgress()) { - TempBasal extendedBolus = DanaRKoreanPlugin.getExtendedBolus(); - if (danaRKoreanPump.isExtendedInProgress) { - if (extendedBolus.absolute != danaRKoreanPump.extendedBolusAbsoluteRate) { - // Close current extended - extendedBolus.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); - // Create new - TempBasal newExtended = new TempBasal(); - newExtended.timeStart = now; - newExtended.absolute = danaRKoreanPump.extendedBolusAbsoluteRate; - newExtended.isAbsolute = true; - newExtended.duration = danaRKoreanPump.extendedBolusMinutes; - newExtended.isExtended = true; - MainApp.getDbHelper().getDaoTempBasals().create(newExtended); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - // Close curent temp basal - extendedBolus.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(extendedBolus); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - if (danaRKoreanPump.isExtendedInProgress) { - // Create new - TempBasal newExtended = new TempBasal(); - newExtended.timeStart = now; - newExtended.absolute = danaRKoreanPump.extendedBolusAbsoluteRate; - newExtended.isAbsolute = true; - newExtended.duration = danaRKoreanPump.extendedBolusMinutes; - newExtended.isExtended = true; - MainApp.getDbHelper().getDaoTempBasals().create(newExtended); - MainApp.bus().post(new EventTempBasalChange()); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusProfile.java deleted file mode 100644 index 7af3260b3a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusProfile.java +++ /dev/null @@ -1,43 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; - -/** - * Created by mike on 05.07.2016. - */ -public class MsgStatusProfile extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusProfile.class); - - public MsgStatusProfile() { - SetCommand(0x0204); - } - - public void handleMessage(byte[] bytes) { - if (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL) { - DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2); - DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2); - } else { - DanaRKoreanPlugin.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2); - DanaRKoreanPlugin.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100d; - DanaRKoreanPlugin.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100d; - } - - if (Config.logDanaMessageDetail) { - log.debug("Pump units (saved): " + (DanaRKoreanPlugin.getDanaRPump().units == DanaRKoreanPump.UNITS_MGDL ? "MGDL" : "MMOL")); - log.debug("Current pump CIR: " + DanaRKoreanPlugin.getDanaRPump().currentCIR); - log.debug("Current pump CF: " + DanaRKoreanPlugin.getDanaRPump().currentCF); - log.debug("Current pump AI: " + DanaRKoreanPlugin.getDanaRPump().currentAI); - log.debug("Current pump target: " + DanaRKoreanPlugin.getDanaRPump().currentTarget); - log.debug("Current pump AIDR: " + DanaRKoreanPlugin.getDanaRPump().currentAIDR); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusTempBasal.java deleted file mode 100644 index 4506bb944a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusTempBasal.java +++ /dev/null @@ -1,103 +0,0 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; - -import android.support.annotation.NonNull; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; - -public class MsgStatusTempBasal extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal.class); - - public MsgStatusTempBasal() { - SetCommand(0x0205); - } - - public void handleMessage(byte[] bytes) { - boolean isTempBasalInProgress = intFromBuff(bytes, 0, 1) == 1; - int tempBasalPercent = intFromBuff(bytes, 1, 1); - int tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60; - int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3); - int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60; - Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0); - - DanaRKoreanPlugin.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress; - DanaRKoreanPlugin.getDanaRPump().tempBasalPercent = tempBasalPercent; - DanaRKoreanPlugin.getDanaRPump().tempBasalRemainingMin = tempBasalRemainingMin; - DanaRKoreanPlugin.getDanaRPump().tempBasalTotalSec = tempBasalTotalSec; - DanaRKoreanPlugin.getDanaRPump().tempBasalStart = tempBasalStart; - - updateTempBasalInDB(); - - if (Config.logDanaMessageDetail) { - log.debug("Is temp basal running: " + isTempBasalInProgress); - log.debug("Current temp basal percent: " + tempBasalPercent); - log.debug("Current temp basal remaining min: " + tempBasalRemainingMin); - log.debug("Current temp basal total sec: " + tempBasalTotalSec); - log.debug("Current temp basal start: " + tempBasalStart); - } - } - - @NonNull - private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) { - return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); - } - - public static void updateTempBasalInDB() { - DanaRKoreanPlugin DanaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); - DanaRKoreanPump danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump(); - Date now = new Date(); - - try { - - if (DanaRKoreanPlugin.isRealTempBasalInProgress()) { - TempBasal tempBasal = DanaRKoreanPlugin.getRealTempBasal(); - if (danaRKoreanPump.isTempBasalInProgress) { - if (tempBasal.percent != danaRKoreanPump.tempBasalPercent) { - // Close current temp basal - tempBasal.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); - // Create new - TempBasal newTempBasal = new TempBasal(); - newTempBasal.timeStart = now; - newTempBasal.percent = danaRKoreanPump.tempBasalPercent; - newTempBasal.isAbsolute = false; - newTempBasal.duration = danaRKoreanPump.tempBasalTotalSec / 60; - newTempBasal.isExtended = false; - MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - // Close current temp basal - tempBasal.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); - MainApp.bus().post(new EventTempBasalChange()); - } - } else { - if (danaRKoreanPump.isTempBasalInProgress) { - // Create new - TempBasal newTempBasal = new TempBasal(); - newTempBasal.timeStart = now; - newTempBasal.percent = danaRKoreanPump.tempBasalPercent; - newTempBasal.isAbsolute = false; - newTempBasal.duration = danaRKoreanPump.tempBasalTotalSec / 60; - newTempBasal.isExtended = false; - MainApp.getDbHelper().getDaoTempBasals().create(newTempBasal); - MainApp.bus().post(new EventTempBasalChange()); - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/ActivityGraph.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/ActivityGraph.java new file mode 100644 index 0000000000..2f98e45272 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/ActivityGraph.java @@ -0,0 +1,76 @@ +package info.nightscout.androidaps.plugins.InsulinFastacting; + +import android.content.Context; +import android.graphics.Color; +import android.util.AttributeSet; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.series.DataPoint; +import com.jjoe64.graphview.series.LineGraphSeries; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.InsulinInterface; + +/** + * Created by mike on 21.04.2017. + */ + +public class ActivityGraph extends GraphView { + + Context context; + + public ActivityGraph(Context context) { + super(context); + this.context = context; + } + + public ActivityGraph(Context context, AttributeSet attrs) { + super(context, attrs); + this.context = context; + } + + public void show(InsulinInterface insulin) { + double dia = insulin.getDia(); + int hours = (int) Math.floor(dia + 1); + + Treatment t = new Treatment(insulin); + t.date = 0; + t.insulin = 1d; + + LineGraphSeries activitySeries = null; + LineGraphSeries iobSeries = null; + List activityArray = new ArrayList(); + List iobArray = new ArrayList(); + + for (long time = 0; time <= hours * 60 * 60 * 1000; time += 5 * 60 * 1000L) { + Iob iob = t.iobCalc(time, dia); + activityArray.add(new DataPoint(time / 60 / 1000, iob.activityContrib)); + iobArray.add(new DataPoint(time / 60 / 1000, iob.iobContrib)); + } + + DataPoint[] activityDataPoints = new DataPoint[activityArray.size()]; + activityDataPoints = activityArray.toArray(activityDataPoints); + addSeries(activitySeries = new LineGraphSeries(activityDataPoints)); + activitySeries.setThickness(8); + + getViewport().setXAxisBoundsManual(true); + getViewport().setMinX(0); + getViewport().setMaxX(hours * 60); + getGridLabelRenderer().setNumHorizontalLabels(hours + 1); + getGridLabelRenderer().setHorizontalAxisTitle("[min]"); + + DataPoint[] iobDataPoints = new DataPoint[iobArray.size()]; + iobDataPoints = iobArray.toArray(iobDataPoints); + getSecondScale().addSeries(iobSeries = new LineGraphSeries(iobDataPoints)); + iobSeries.setDrawBackground(true); + iobSeries.setColor(Color.MAGENTA); + iobSeries.setBackgroundColor(Color.argb(70, 255, 0, 255)); + getSecondScale().setMinY(0); + getSecondScale().setMaxY(1); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingFragment.java new file mode 100644 index 0000000000..a99e016621 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingFragment.java @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.plugins.InsulinFastacting; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +/** + * Created by mike on 17.04.2017. + */ + +public class InsulinFastactingFragment extends Fragment { + static InsulinFastactingPlugin insulinFastactingPlugin = new InsulinFastactingPlugin(); + + static public InsulinFastactingPlugin getPlugin() { + return insulinFastactingPlugin; + } + + TextView insulinName; + TextView insulinComment; + TextView insulinDia; + ActivityGraph insulinGraph; + + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.insulin_fragment, container, false); + + insulinName = (TextView) view.findViewById(R.id.insulin_name); + insulinComment = (TextView) view.findViewById(R.id.insulin_comment); + insulinDia = (TextView) view.findViewById(R.id.insulin_dia); + insulinGraph = (ActivityGraph) view.findViewById(R.id.insuling_graph); + + insulinName.setText(insulinFastactingPlugin.getFriendlyName()); + insulinComment.setText(insulinFastactingPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + new Double(insulinFastactingPlugin.getDia()).toString() + "h"); + insulinGraph.show(insulinFastactingPlugin); + + return view; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingPlugin.java new file mode 100644 index 0000000000..c98295ad35 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingPlugin.java @@ -0,0 +1,122 @@ +package info.nightscout.androidaps.plugins.InsulinFastacting; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.PluginBase; + +/** + * Created by mike on 17.04.2017. + */ + +public class InsulinFastactingPlugin implements PluginBase, InsulinInterface { + + private static boolean fragmentEnabled = true; + private static boolean fragmentVisible = false; + + @Override + public int getType() { + return INSULIN; + } + + @Override + public String getFragmentClass() { + return InsulinFastactingFragment.class.getName(); + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.fastactinginsulin); + } + + @Override + public String getNameShort() { + return MainApp.sResources.getString(R.string.insulin_shortname); + } + + @Override + public boolean isEnabled(int type) { + return type == INSULIN && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == INSULIN && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == INSULIN) this.fragmentVisible = fragmentVisible; + } + + // Insulin interface + @Override + public int getId() { + return FASTACTINGINSULIN; + } + + @Override + public String getFriendlyName() { + return MainApp.sResources.getString(R.string.fastactinginsulin); + } + + @Override + public String getComment() { + return MainApp.sResources.getString(R.string.fastactinginsulincomment); + } + + @Override + public double getDia() { + return MainApp.getConfigBuilder().getProfile().getDia(); + } + + @Override + public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { + Iob result = new Iob(); + + double scaleFactor = 3.0 / dia; + double peak = 75d; + double end = 180d; + + if (treatment.insulin != 0d) { + long bolusTime = treatment.date; + double minAgo = scaleFactor * (time - bolusTime) / 1000d / 60d; + + if (minAgo < peak) { + double x1 = minAgo / 5d + 1; + result.iobContrib = treatment.insulin * (1 - 0.001852 * x1 * x1 + 0.001852 * x1); + // units: BG (mg/dL) = (BG/U) * U insulin * scalar + result.activityContrib = treatment.insulin * (2 / dia / 60 / peak) * minAgo; + + } else if (minAgo < end) { + double x2 = (minAgo - 75) / 5; + result.iobContrib = treatment.insulin * (0.001323 * x2 * x2 - 0.054233 * x2 + 0.55556); + result.activityContrib = treatment.insulin * (2 / dia / 60 - (minAgo - peak) * 2 / dia / 60 / (60 * 3 - peak)); + } + } + return result; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedFragment.java new file mode 100644 index 0000000000..acc915b001 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedFragment.java @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.InsulinFastactingProlonged; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.InsulinFastacting.ActivityGraph; + +/** + * Created by mike on 17.04.2017. + */ + +public class InsulinFastactingProlongedFragment extends Fragment { + static InsulinFastactingProlongedPlugin insulinFastactingProlongedPlugin = new InsulinFastactingProlongedPlugin(); + + static public InsulinFastactingProlongedPlugin getPlugin() { + return insulinFastactingProlongedPlugin; + } + + TextView insulinName; + TextView insulinComment; + TextView insulinDia; + ActivityGraph insulinGraph; + + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.insulin_fragment, container, false); + + insulinName = (TextView) view.findViewById(R.id.insulin_name); + insulinComment = (TextView) view.findViewById(R.id.insulin_comment); + insulinDia = (TextView) view.findViewById(R.id.insulin_dia); + insulinGraph = (ActivityGraph) view.findViewById(R.id.insuling_graph); + + insulinName.setText(insulinFastactingProlongedPlugin.getFriendlyName()); + insulinComment.setText(insulinFastactingProlongedPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + new Double(insulinFastactingProlongedPlugin.getDia()).toString() + "h"); + insulinGraph.show(insulinFastactingProlongedPlugin); + + return view; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedPlugin.java new file mode 100644 index 0000000000..ed5fc0485c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedPlugin.java @@ -0,0 +1,127 @@ +package info.nightscout.androidaps.plugins.InsulinFastactingProlonged; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.PluginBase; + +/** + * Created by mike on 17.04.2017. + */ + +public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInterface { + + private static boolean fragmentEnabled = false; + private static boolean fragmentVisible = false; + + @Override + public int getType() { + return INSULIN; + } + + @Override + public String getFragmentClass() { + return InsulinFastactingProlongedFragment.class.getName(); + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.fastactinginsulinprolonged); + } + + @Override + public String getNameShort() { + return MainApp.sResources.getString(R.string.insulin_shortname); + } + + @Override + public boolean isEnabled(int type) { + return type == INSULIN && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == INSULIN && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == INSULIN) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == INSULIN) this.fragmentVisible = fragmentVisible; + } + + // Insulin interface + @Override + public int getId() { + return FASTACTINGINSULINPROLONGED; + } + + @Override + public String getFriendlyName() { + return MainApp.sResources.getString(R.string.fastactinginsulinprolonged); + } + + @Override + public String getComment() { + return MainApp.sResources.getString(R.string.fastactinginsulincomment); + } + + @Override + public double getDia() { + return MainApp.getConfigBuilder().getProfile().getDia(); + } + + @Override + public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { + Iob result = new Iob(); + + //Double scaleFactor = 3.0 / dia; + double peak = 75d * dia / 6.0; + double tail = 180d * dia / 6.0; + double end = 360d * dia / 6.0; + double Total = 2 * peak + (tail - peak) * 5 / 2 + (end - tail) / 2; + + if (treatment.insulin != 0d) { + long bolusTime = treatment.date; + double minAgo = (time - bolusTime) / 1000d / 60d; + + if (minAgo < peak) { + double x1 = 6 / dia * minAgo / 5d + 1; + result.iobContrib = treatment.insulin * (1 - 0.0012595 * x1 * x1 + 0.0012595 * x1); + // units: BG (mg/dL) = (BG/U) * U insulin * scalar + result.activityContrib = treatment.insulin * ((2 * peak / Total) * 2 / peak / peak * minAgo); + } else if (minAgo < tail) { + double x2 = (6 / dia * (minAgo - peak)) / 5; + result.iobContrib = treatment.insulin * (0.00074 * x2 * x2 - 0.0403 * x2 + 0.69772); + result.activityContrib = treatment.insulin * (-((2 * peak / Total) * 2 / peak * 3 / 4) / (tail - peak) * (minAgo - peak) + (2 * peak / Total) * 2 / peak); + } else if (minAgo < end) { + double x3 = (6 / dia * (minAgo - tail)) / 5; + result.iobContrib = treatment.insulin * (0.0001323 * x3 * x3 - 0.0097 * x3 + 0.17776); + result.activityContrib = treatment.insulin * (-((2 * peak / Total) * 2 / peak * 1 / 4) / (end - tail) * (minAgo - tail) + (2 * peak / Total) * 2 / peak / 4); + } + + } + return result; + } +} 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 new file mode 100644 index 0000000000..427ca5d531 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator; + +import java.util.Date; + +/** + * Created by mike on 25.04.2017. + */ + +public class AutosensData { + long time = 0L; + public String pastSensitivity = ""; + public double deviation = 0d; + boolean calculateWithDeviation = false; + double absorbed = 0d; + public double carbsFromBolus = 0d; + public double cob = 0; + public double bgi = 0d; + public double delta = 0d; + + public String log(long time) { + return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " Bgi=" + bgi + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob; + } + + public int minOld() { + return (int) ((new Date().getTime() - time) / 1000 / 60); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/AutosensResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/AutosensResult.java rename to app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java index 811fee0f39..1e40005b36 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/AutosensResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensResult.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.OpenAPSAMA; +package info.nightscout.androidaps.plugins.IobCobCalculator; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorFragment.java new file mode 100644 index 0000000000..db1db95998 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorFragment.java @@ -0,0 +1,16 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator; + +import android.support.v4.app.Fragment; + +/** + * Created by adrian on 17/11/16. + */ + +public class IobCobCalculatorFragment extends Fragment { + + private static IobCobCalculatorPlugin iobCobCalculatorPlugin = new IobCobCalculatorPlugin(); + + public static IobCobCalculatorPlugin getPlugin() { + return iobCobCalculatorPlugin; + } +} 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 new file mode 100644 index 0000000000..417322a6b4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -0,0 +1,629 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator; + +import android.os.Handler; +import android.os.HandlerThread; +import android.support.annotation.Nullable; +import android.support.v4.util.LongSparseArray; + +import com.squareup.otto.Subscribe; + +import org.json.JSONArray; +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.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.events.EventNewBasalProfile; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; +import info.nightscout.utils.Round; +import info.nightscout.utils.SP; +import info.nightscout.utils.SafeParse; + +/** + * Created by mike on 24.04.2017. + */ + +public class IobCobCalculatorPlugin implements PluginBase { + private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class); + + private static LongSparseArray iobTable = new LongSparseArray<>(); // oldest at index 0 + private static LongSparseArray autosensDataTable = new LongSparseArray<>(); // oldest at index 0 + private static LongSparseArray basalDataTable = new LongSparseArray<>(); // oldest at index 0 + + private static volatile List bgReadings = null; // newest at index 0 + private static volatile List bucketed_data = null; + + private static double dia = Constants.defaultDIA; + + private static Handler sHandler = null; + private static HandlerThread sHandlerThread = null; + + private static Object dataLock = new Object(); + + @Override + public int getType() { + return GENERAL; + } + + @Override + public String getFragmentClass() { + return IobCobCalculatorFragment.class.getName(); + } + + @Override + public String getName() { + return "IOB COB Calculator"; + } + + @Override + public String getNameShort() { + return "IOC"; + } + + @Override + public boolean isEnabled(int type) { + return type == GENERAL; + } + + @Override + public boolean isVisibleInTabs(int type) { + return false; + } + + @Override + public boolean canBeHidden(int type) { + return false; + } + + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return false; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + + } + + public IobCobCalculatorPlugin() { + MainApp.bus().register(this); + if (sHandlerThread == null) { + sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName()); + sHandlerThread.start(); + sHandler = new Handler(sHandlerThread.getLooper()); + } + onNewBg(new EventNewBG()); + } + + @Nullable + public static List getBucketedData(long fromTime) { + //log.debug("Locking getBucketedData"); + synchronized (dataLock) { + if (bucketed_data == null) { + log.debug("No bucketed data available"); + return null; + } + int index = indexNewerThan(fromTime); + if (index > -1) { + List part = bucketed_data.subList(0, index); + log.debug("Bucketed data striped off: " + part.size() + "/" + bucketed_data.size()); + return part; + } + } + //log.debug("Releasing getBucketedData"); + return null; + } + + private static int indexNewerThan(long time) { + for (int index = 0; index < bucketed_data.size(); index++) { + if (bucketed_data.get(index).date < time) + return index - 1; + } + return -1; + } + + public static long roundUpTime(long time) { + if (time % 60000 == 0) + return time; + long rouded = (time / 60000 + 1) * 60000; + return rouded; + } + + private void loadBgData() { + //log.debug("Locking loadBgData"); + synchronized (dataLock) { + onNewProfile(null); + bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)), false); + log.debug("BG data loaded. Size: " + bgReadings.size()); + } + //log.debug("Releasing loadBgData"); + } + + public void createBucketedData() { + //log.debug("Locking createBucketedData"); + synchronized (dataLock) { + if (bgReadings == null || bgReadings.size() < 3) { + bucketed_data = null; + return; + } + + bucketed_data = new ArrayList<>(); + bucketed_data.add(bgReadings.get(0)); + int j = 0; + for (int i = 1; i < bgReadings.size(); ++i) { + long bgTime = bgReadings.get(i).date; + long lastbgTime = bgReadings.get(i - 1).date; + //log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + bgReadings.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + bgReadings.get(i - 1).value); + if (bgReadings.get(i).value < 39 || bgReadings.get(i - 1).value < 39) { + continue; + } + + long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000); + if (Math.abs(elapsed_minutes) > 8) { + // interpolate missing data points + double lastbg = bgReadings.get(i - 1).value; + elapsed_minutes = Math.abs(elapsed_minutes); + //console.error(elapsed_minutes); + long nextbgTime; + while (elapsed_minutes > 5) { + nextbgTime = lastbgTime - 5 * 60 * 1000; + j++; + BgReading newBgreading = new BgReading(); + newBgreading.date = nextbgTime; + double gapDelta = bgReadings.get(i).value - lastbg; + //console.error(gapDelta, lastbg, elapsed_minutes); + double nextbg = lastbg + (5d / elapsed_minutes * gapDelta); + newBgreading.value = Math.round(nextbg); + //console.error("Interpolated", bucketed_data[j]); + bucketed_data.add(newBgreading); + //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); + + elapsed_minutes = elapsed_minutes - 5; + lastbg = nextbg; + lastbgTime = nextbgTime; + } + j++; + BgReading newBgreading = new BgReading(); + newBgreading.value = bgReadings.get(i).value; + newBgreading.date = bgTime; + bucketed_data.add(newBgreading); + //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); + } else if (Math.abs(elapsed_minutes) > 2) { + j++; + BgReading newBgreading = new BgReading(); + newBgreading.value = bgReadings.get(i).value; + newBgreading.date = bgTime; + bucketed_data.add(newBgreading); + //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); + } else { + bucketed_data.get(j).value = (bucketed_data.get(j).value + bgReadings.get(i).value) / 2; + //log.error("***** Average"); + } + } + log.debug("Bucketed data created. Size: " + bucketed_data.size()); + } + //log.debug("Releasing createBucketedData"); + } + + public void calculateSensitivityData() { + if (MainApp.getConfigBuilder() == null) + return; // app still initializing + //log.debug("Locking calculateSensitivityData"); + synchronized (dataLock) { + + if (bucketed_data == null || bucketed_data.size() < 3) { + log.debug("calculateSensitivityData: No bucketed data available"); + return; + } + + long prevDataTime = 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--) { + // check if data already exists + long bgTime = bucketed_data.get(i).date; + bgTime = roundUpTime(bgTime); + Profile profile = MainApp.getConfigBuilder().getProfile(bgTime); + + AutosensData existing; + if ((existing = autosensDataTable.get(bgTime)) != null) { + previous = existing; + continue; + } + + double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits()); + + AutosensData autosensData = new AutosensData(); + autosensData.time = bgTime; + + //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; + } + delta = (bg - bucketed_data.get(i + 1).value); + + IobTotal iob = calulateFromTreatmentsAndTemps(bgTime); + + double bgi = -iob.activity * sens * 5; + double deviation = delta - bgi; + + List recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime); + for (int ir = 0; ir < recentTreatments.size(); ir++) { + autosensData.carbsFromBolus += recentTreatments.get(ir).carbs; + } + + // if we are absorbing carbs + if (previous != null && previous.cob > 0) { + // figure out how many carbs that represents + // but always assume at least 3mg/dL/5m (default) absorption + double ci = Math.max(deviation, SP.getDouble("openapsama_min_5m_carbimpact", 3.0)); + 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.cob += autosensData.carbsFromBolus; + autosensData.deviation = deviation; + autosensData.bgi = bgi; + autosensData.delta = delta; + + // calculate autosens only without COB + if (autosensData.cob <= 0) { + if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) { + autosensData.pastSensitivity += "="; + } else if (deviation > 0) { + autosensData.pastSensitivity += "+"; + } else { + autosensData.pastSensitivity += "-"; + } + autosensData.calculateWithDeviation = true; + } else { + 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 (Config.logAutosensData) + log.debug(autosensData.log(bgTime)); + } + } + MainApp.bus().post(new EventAutosensCalculationFinished()); + //log.debug("Releasing calculateSensitivityData"); + } + + public static IobTotal calulateFromTreatmentsAndTemps(long time) { + long now = new Date().getTime(); + time = roundUpTime(time); + if (time < now && iobTable.get(time) != null) { + //log.debug(">>> Cache hit"); + return iobTable.get(time); + } else { + //log.debug(">>> Cache miss " + new Date(time).toLocaleString()); + } + IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round(); + IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round(); +/* + if (basalIob.basaliob > 0) { + log.debug(new Date(time).toLocaleString() + " basaliob: " + basalIob.basaliob ); + } +*/ + IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); + if (time < new Date().getTime()) { + iobTable.put(time, iobTotal); + } + return iobTotal; + } + + private static Long findPreviousTimeFromBucketedData(long time) { + if (bucketed_data == null) + return null; + for (int index = 0; index < bucketed_data.size(); index++) { + if (bucketed_data.get(index).date < time) + return bucketed_data.get(index).date; + } + return null; + } + + public static BasalData getBasalData(long time) { + long now = new Date().getTime(); + time = roundUpTime(time); + BasalData retval = basalDataTable.get(time); + if (retval == null) { + retval = new BasalData(); + TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(time); + retval.basal = MainApp.getConfigBuilder().getProfile(time).getBasal(time); + if (tb != null) { + retval.isTempBasalRunning = true; + retval.tempBasalAbsolute = tb.tempBasalConvertedToAbsolute(time); + } else { + retval.isTempBasalRunning = false; + retval.tempBasalAbsolute = retval.basal; + } + if (time < now) { + basalDataTable.append(time, retval); + } + //log.debug(">>> Cache miss " + new Date(time).toLocaleString()); + } else { + //log.debug(">>> Cache hit " + new Date(time).toLocaleString()); + } + return retval; + } + + public static AutosensData getAutosensData(long time) { + long now = new Date().getTime(); + if (time > now) + return null; + Long previous = findPreviousTimeFromBucketedData(time); + if (previous == null) + return null; + time = roundUpTime(previous); + AutosensData data = autosensDataTable.get(time); + if (data != null) { + //log.debug(">>> Cache hit " + data.log(time)); + return data; + } else { + //log.debug(">>> Cache miss " + new Date(time).toLocaleString()); + return null; + } + } + + public static AutosensData getLastAutosensData() { + if (autosensDataTable.size() < 1) + return null; + AutosensData data = autosensDataTable.valueAt(autosensDataTable.size() - 1); + if (data.time < new Date().getTime() - 5 * 60 * 1000) { + return null; + } else { + return data; + } + } + + public static IobTotal[] calculateIobArrayInDia() { + Profile profile = MainApp.getConfigBuilder().getProfile(); + // predict IOB out to DIA plus 30m + long time = new Date().getTime(); + int len = (int) ((profile.getDia() * 60 + 30) / 5); + IobTotal[] array = new IobTotal[len]; + int pos = 0; + for (int i = 0; i < len; i++) { + long t = time + i * 5 * 60000; + IobTotal iob = calulateFromTreatmentsAndTemps(t); + array[pos] = iob; + pos++; + } + return array; + } + + public static AutosensResult detectSensitivity(long fromTime) { + //log.debug("Locking detectSensitivity"); + synchronized (dataLock) { + if (autosensDataTable == null || autosensDataTable.size() < 4) { + log.debug("No autosens data available"); + return new AutosensResult(); + } + + AutosensData current = getLastAutosensData(); + if (current == null) { + log.debug("No current autosens data available"); + return new AutosensResult(); + } + + + 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.calculateWithDeviation) + deviationsArray.add(autosensData.deviation); + + 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++; + } + + Double[] deviations = new Double[deviationsArray.size()]; + deviations = deviationsArray.toArray(deviations); + + Profile profile = MainApp.getConfigBuilder().getProfile(); + + double sens = profile.getIsf(); + + double ratio = 1; + String ratioLimit = ""; + String sensResult = ""; + + log.debug("Records: " + index + " " + pastSensitivity); + Arrays.sort(deviations); + + for (double i = 0.9; i > 0.1; i = i - 0.02) { + if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) { + log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)"); + } + } + double pSensitive = percentile(deviations, 0.50); + double pResistant = percentile(deviations, 0.45); + + 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"; + } + log.debug(sensResult); + ratio = 1 + (basalOff / profile.getMaxDailyBasal()); + + double rawRatio = ratio; + ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7"))); + ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2"))); + + if (ratio != rawRatio) { + ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio; + log.debug(ratioLimit); + } + + double newisf = Math.round(Profile.toMgdl(sens, profile.getUnits()) / ratio); + if (ratio != 1) { + log.debug("ISF adjusted from " + Profile.toMgdl(sens, profile.getUnits()) + " to " + newisf); + } + + 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; + } + //log.debug("Releasing detectSensitivity"); + } + + + public static JSONArray convertToJSONArray(IobTotal[] iobArray) { + JSONArray array = new JSONArray(); + for (int i = 0; i < iobArray.length; i++) { + array.put(iobArray[i].determineBasalJson()); + } + return array; + } + + @Subscribe + public void onNewBg(EventNewBG ev) { + sHandler.post(new Runnable() { + @Override + public void run() { + loadBgData(); + createBucketedData(); + calculateSensitivityData(); + } + }); + } + + @Subscribe + public void onNewProfile(EventNewBasalProfile ev) { + if (MainApp.getConfigBuilder() == null) + return; // app still initializing + Profile profile = MainApp.getConfigBuilder().getProfile(); + dia = profile.getDia(); + if (ev == null) { // on init no need of reset + return; + } + synchronized (dataLock) { + log.debug("Invalidating cached data because of new profile. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); + iobTable = new LongSparseArray<>(); + autosensDataTable = new LongSparseArray<>(); + } + sHandler.post(new Runnable() { + @Override + public void run() { + calculateSensitivityData(); + } + }); + } + + // When historical data is changed (comming from NS etc) finished calculations after this date must be invalidated + @Subscribe + public void onNewHistoryData(EventNewHistoryData ev) { + //log.debug("Locking onNewHistoryData"); + synchronized (dataLock) { + long time = ev.time; + log.debug("Invalidating cached data to: " + new Date(time).toLocaleString()); + for (int index = iobTable.size() - 1; index >= 0; index--) { + if (iobTable.keyAt(index) > time) { + if (Config.logAutosensData) + log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString()); + iobTable.removeAt(index); + } else { + break; + } + } + for (int index = autosensDataTable.size() - 1; index >= 0; index--) { + if (autosensDataTable.keyAt(index) > time) { + if (Config.logAutosensData) + log.debug("Removing from autosensDataTable: " + new Date(autosensDataTable.keyAt(index)).toLocaleString()); + autosensDataTable.removeAt(index); + } else { + break; + } + } + for (int index = basalDataTable.size() - 1; index >= 0; index--) { + if (basalDataTable.keyAt(index) > time) { + if (Config.logAutosensData) + log.debug("Removing from basalDataTable: " + new Date(basalDataTable.keyAt(index)).toLocaleString()); + basalDataTable.removeAt(index); + } else { + break; + } + } + } + sHandler.post(new Runnable() { + @Override + public void run() { + calculateSensitivityData(); + } + }); + //log.debug("Releasing onNewHistoryData"); + } + + // From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2 + // Returns the value at a given percentile in a sorted numeric array. + // "Linear interpolation between closest ranks" method + public static double percentile(Double[] arr, double p) { + if (arr.length == 0) return 0; + if (p <= 0) return arr[0]; + if (p >= 1) return arr[arr.length - 1]; + + double index = arr.length * p, + lower = Math.floor(index), + upper = lower + 1, + weight = index % 1; + + if (upper >= arr.length) return arr[(int) lower]; + return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/BasalData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/BasalData.java new file mode 100644 index 0000000000..4e1dcc1bf6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/BasalData.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator.events; + +/** + * Created by mike on 10.06.2017. + */ + +public class BasalData { + public double basal; + public double tempBasalAbsolute; + public boolean isTempBasalRunning; +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java new file mode 100644 index 0000000000..f2977c90c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventAutosensCalculationFinished.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator.events; + +/** + * Created by mike on 30.04.2017. + */ + +public class EventAutosensCalculationFinished { +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java new file mode 100644 index 0000000000..7499fad383 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/events/EventNewHistoryData.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.IobCobCalculator.events; + +/** + * Created by mike on 26.04.2017. + */ + +public class EventNewHistoryData { + public long time = 0; + + public EventNewHistoryData(long time) { + this.time = time; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java index 0d72464b73..3080717773 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/DeviceStatus.java @@ -402,16 +402,4 @@ public class DeviceStatus { return record; } - public void sendToNSClient() { - Context context = MainApp.instance().getApplicationContext(); - Bundle bundle = new Bundle(); - bundle.putString("action", "dbAdd"); - bundle.putString("collection", "devicestatus"); - bundle.putString("data", mongoRecord().toString()); - Intent intent = new Intent(Intents.ACTION_DATABASE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - DbLogger.dbAdd(intent, mongoRecord().toString(), DeviceStatus.class); - } } 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 43a8fa3c83..de295d8a6e 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 @@ -19,11 +19,10 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; -public class LoopFragment extends Fragment implements View.OnClickListener, FragmentBase { +public class LoopFragment extends Fragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(LoopFragment.class); private static LoopPlugin loopPlugin; 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 6a3869589b..6fa9e6d677 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 @@ -12,6 +12,7 @@ import android.support.v7.app.NotificationCompat; import com.squareup.otto.Subscribe; +import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,7 +33,10 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; +import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; +import info.nightscout.utils.SafeParse; /** * Created by mike on 05.08.2016. @@ -44,7 +48,7 @@ public class LoopPlugin implements PluginBase { private static HandlerThread sHandlerThread; private boolean fragmentEnabled = false; - private boolean fragmentVisible = true; + private boolean fragmentVisible = false; private long loopSuspendedTill = 0L; // end of manual loop suspend private boolean isSuperBolus = false; @@ -113,6 +117,16 @@ public class LoopPlugin implements PluginBase { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == LOOP) this.fragmentEnabled = fragmentEnabled; @@ -246,7 +260,7 @@ public class LoopPlugin implements PluginBase { lastRun.source = ((PluginBase) usedAPS).getName(); lastRun.setByPump = null; - if (constraintsInterface.isClosedModeEnabled()) { + if (constraintsInterface.isClosedModeEnabled()) { if (result.changeRequested) { final PumpEnactResult waiting = new PumpEnactResult(); final PumpEnactResult previousResult = lastRun.setByPump; @@ -306,7 +320,7 @@ public class LoopPlugin implements PluginBase { } MainApp.bus().post(new EventLoopUpdateGui()); - MainApp.getConfigBuilder().uploadDeviceStatus(); + NSUpload.uploadDeviceStatus(); } finally { if (Config.logFunctionCalls) log.debug("invoke end"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIFragment.java deleted file mode 100644 index a67f68dfb3..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIFragment.java +++ /dev/null @@ -1,33 +0,0 @@ -package info.nightscout.androidaps.plugins.MDI; - - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -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.R; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.VirtualPump.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui; - -public class MDIFragment extends Fragment implements FragmentBase { - private static Logger log = LoggerFactory.getLogger(MDIFragment.class); - - private static MDIPlugin mdiPlugin = new MDIPlugin(); - - public static MDIPlugin getPlugin() { - return mdiPlugin; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalFragment.java index 3514285473..c3e8c777c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalFragment.java @@ -28,13 +28,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI; import info.nightscout.utils.SP; -public class NSClientInternalFragment extends Fragment implements FragmentBase, View.OnClickListener, CompoundButton.OnCheckedChangeListener { +public class NSClientInternalFragment extends Fragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(NSClientInternalFragment.class); static NSClientInternalPlugin nsClientInternalPlugin; @@ -189,5 +188,4 @@ public class NSClientInternalFragment extends Fragment implements FragmentBase, }); } - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java index 46c19b2eaa..a37d5442ca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalPlugin.java @@ -4,11 +4,9 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.preference.PreferenceManager; import android.text.Html; import android.text.Spanned; import android.text.TextUtils; @@ -20,20 +18,15 @@ import org.slf4j.LoggerFactory; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; 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.events.EventAppExit; -import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpDescription; -import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; -import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientUpdateGUI; import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; @@ -116,6 +109,16 @@ public class NSClientInternalPlugin implements PluginBase { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return !Config.NSCLIENT; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; @@ -147,11 +150,6 @@ public class NSClientInternalPlugin implements PluginBase { MainApp.instance().getApplicationContext().unbindService(mConnection); } - @Subscribe - public void onStatusEvent(final EventPreferenceChange s) { - //TODO - } - @Subscribe public void onStatusEvent(final EventNSClientNewLog ev) { addToLog(ev); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java index b318d8026f..24231de63f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java @@ -5,22 +5,17 @@ import android.content.Intent; import com.j256.ormlite.dao.CloseableIterator; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; -import info.nightscout.utils.SP; /** * Created by mike on 21.02.2016. @@ -118,7 +113,7 @@ public class UploadQueue { String result = ""; CloseableIterator iterator = null; try { - iterator = MainApp.getDbHelper().getDaoDbRequest().closeableIterator(); + iterator = MainApp.getDbHelper().getDbRequestInterator(); try { while (iterator.hasNext()) { DbRequest dbr = iterator.next(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastProfile.java index a1d44d0340..641a4e6a77 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastProfile.java @@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory; import java.util.List; import info.nightscout.androidaps.Services.Intents; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; /** @@ -20,10 +20,9 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; public class BroadcastProfile { private static Logger log = LoggerFactory.getLogger(BroadcastProfile.class); - public void handleNewTreatment(NSProfile profile, Context context, boolean isDelta) { + public void handleNewTreatment(ProfileStore profile, Context context, boolean isDelta) { Bundle bundle = new Bundle(); bundle.putString("profile", profile.getData().toString()); - bundle.putString("activeprofile", profile.getActiveProfile()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_PROFILE); intent.putExtras(bundle); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/DbLogger.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/DbLogger.java index 70d8e9e336..79a66186fb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/DbLogger.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/DbLogger.java @@ -17,8 +17,9 @@ import info.nightscout.utils.ToastUtils; * Created by mike on 02.07.2016. */ public class DbLogger { - public static void dbAdd(Intent intent, String data, Class sender) { - Logger log = LoggerFactory.getLogger(sender); + private static Logger log = LoggerFactory.getLogger(DbLogger.class); + + public static void dbAdd(Intent intent, String data) { List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0); if (q.size() < 1) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.nsclientnotinstalled)); @@ -27,8 +28,7 @@ public class DbLogger { log.debug("DBADD dbAdd " + q.size() + " receivers " + data); } - public static void dbRemove(Intent intent, String data, Class sender) { - Logger log = LoggerFactory.getLogger(sender); + public static void dbRemove(Intent intent, String data) { List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0); if (q.size() < 1) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.nsclientnotinstalled)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java new file mode 100644 index 0000000000..79fa60c3bb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSMbg.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.data; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NSMbg { + private static Logger log = LoggerFactory.getLogger(NSMbg.class); + public long date; + public double mbg; + public String json; + + public NSMbg(JSONObject json) { + try { + date = json.getLong("mills"); + mbg = json.getDouble("mgdl"); + this.json = json.toString(); + } catch (JSONException e) { + e.printStackTrace(); + log.debug("Data: " + json.toString()); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java deleted file mode 100644 index 5ff95ddf39..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java +++ /dev/null @@ -1,483 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.data; - -import android.support.annotation.Nullable; - -import com.crashlytics.android.Crashlytics; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.Iterator; -import java.util.TimeZone; - -import info.nightscout.androidaps.Constants; -import info.nightscout.utils.DecimalFormatter; - -public class NSProfile { - private static Logger log = LoggerFactory.getLogger(NSProfile.class); - - private JSONObject json = null; - private String activeProfile = null; - - public NSProfile(JSONObject json, String activeProfile) { - this.json = json; - this.activeProfile = null; - JSONObject store; - try { - store = json.getJSONObject("store"); - if (activeProfile != null && store.has(activeProfile)) { - this.activeProfile = activeProfile; - } else { - log.error("Active profile not found in store"); - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - - public JSONObject getDefaultProfile() { - String defaultProfileName = null; - JSONObject store; - JSONObject profile = null; - try { - defaultProfileName = (String) json.get("defaultProfile"); - store = json.getJSONObject("store"); - if (activeProfile != null && store.has(activeProfile)) { - defaultProfileName = activeProfile; - } - profile = store.getJSONObject(defaultProfileName); - } catch (JSONException e) { - e.printStackTrace(); - } - return profile; - } - - public JSONObject getSpecificProfile(String profileName) { - JSONObject profile = null; - try { - JSONObject store = json.getJSONObject("store"); - if (store.has(profileName)) { - profile = store.getJSONObject(profileName); - } - } catch (JSONException e) { - e.printStackTrace(); - } - return profile; - } - - public ArrayList getProfileList() { - ArrayList ret = new ArrayList(); - - JSONObject store; - JSONObject profile = null; - try { - store = json.getJSONObject("store"); - Iterator keys = store.keys(); - - while (keys.hasNext()) { - String profileName = (String) keys.next(); - ret.add(profileName); - } - } catch (JSONException e) { - e.printStackTrace(); - } - - return ret; - } - - public String log() { - String ret = "\n"; - for (Integer hour = 0; hour < 24; hour++) { - double value = getBasal(hour * 60 * 60); - ret += "NS basal value for " + hour + ":00 is " + value + "\n"; - } - ret += "NS units: " + getUnits(); - return ret; - } - - public JSONObject getData() { - return json; - } - - public Double getDia() { - return getDia(getDefaultProfile()); - } - - public Double getDia(JSONObject profile) { - Double dia; - if (profile != null) { - try { - dia = profile.getDouble("dia"); - return dia; - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 3D; - } -/* - public Double getCarbAbsorbtionRate() { - return getCarbAbsorbtionRate(getDefaultProfile()); - } - - public Double getCarbAbsorbtionRate(JSONObject profile) { - Double carbAbsorptionRate; - if (profile != null) { - try { - carbAbsorptionRate = profile.getDouble("carbs_hr"); - return carbAbsorptionRate; - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 0D; - } -*/ - // mmol or mg/dl - public String getUnits() { - return getUnits(getDefaultProfile()); - } - - public String getUnits(JSONObject profile) { - String units; - if (profile != null) { - try { - units = profile.getString("units"); - return units.toLowerCase(); - } catch (JSONException e) { - log.error("Profile not found. Failing over to main JSON"); - try { - return json.getString("units").toLowerCase(); - } catch (JSONException e1) { - e1.printStackTrace(); - Crashlytics.log("Profile failover failed too"); - } - } - } - return Constants.MGDL; - } - - public TimeZone getTimeZone() { - return getTimeZone(getDefaultProfile()); - } - - public TimeZone getTimeZone(JSONObject profile) { - TimeZone timeZone; - if (profile != null) { - try { - return TimeZone.getTimeZone(profile.getString("timezone")); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return TimeZone.getDefault(); - } - - @Nullable - public Double getValueToTime(JSONArray array, Integer timeAsSeconds) { - Double lastValue = null; - - for (Integer index = 0; index < array.length(); index++) { - try { - JSONObject o = array.getJSONObject(index); - Integer tas = o.getInt("timeAsSeconds"); - Double value = o.getDouble("value"); - if (lastValue == null) lastValue = value; - if (timeAsSeconds < tas) { - break; - } - lastValue = value; - } catch (JSONException e) { - e.printStackTrace(); - } - } - return lastValue; - } - - public String getValuesList(JSONArray array, JSONArray array2, DecimalFormat format, String units) { - String retValue = ""; - - for (Integer index = 0; index < array.length(); index++) { - try { - JSONObject o = array.getJSONObject(index); - retValue += o.getString("time"); - retValue += " "; - retValue += format.format(o.getDouble("value")); - if (array2 != null) { - JSONObject o2 = array2.getJSONObject(index); - retValue += " - "; - retValue += format.format(o2.getDouble("value")); - } - retValue += " " + units; - retValue += "\n"; - } catch (JSONException e) { - e.printStackTrace(); - } - } - return retValue; - } - - @Nullable - public Double getIsf(Integer timeAsSeconds) { - return getIsf(getDefaultProfile(), timeAsSeconds); - } - - @Nullable - public Double getIsf(JSONObject profile, Integer timeAsSeconds) { - if (profile != null) { - try { - return getValueToTime(profile.getJSONArray("sens"), timeAsSeconds); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 0D; - } - - public String getIsfList() { - return getIsfList(getDefaultProfile()); - } - - public String getIsfList(JSONObject profile) { - if (profile != null) { - try { - return getValuesList(profile.getJSONArray("sens"), null, new DecimalFormat("0.0"), getUnits() + "/U"); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ""; - } - - @Nullable - public Double getIc(Integer timeAsSeconds) { - return getIc(getDefaultProfile(), timeAsSeconds); - } - - @Nullable - public Double getIc(JSONObject profile, Integer timeAsSeconds) { - if (profile != null) { - try { - return getValueToTime(profile.getJSONArray("carbratio"), timeAsSeconds); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 0D; - } - - public String getIcList() { - return getIcList(getDefaultProfile()); - } - - public String getIcList(JSONObject profile) { - if (profile != null) { - try { - return getValuesList(profile.getJSONArray("carbratio"), null, new DecimalFormat("0.0"), "g"); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ""; - } - - @Nullable - public Double getBasal(Integer timeAsSeconds) { - return getBasal(getDefaultProfile(), timeAsSeconds); - } - - @Nullable - public Double getBasal(JSONObject profile, Integer timeAsSeconds) { - if (profile != null) { - try { - return getValueToTime(profile.getJSONArray("basal"), timeAsSeconds); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 0D; - } - - public String getBasalList() { - return getBasalList(getDefaultProfile()); - } - - public class BasalValue { - public BasalValue(Integer timeAsSeconds, Double value) { - this.timeAsSeconds = timeAsSeconds; - this.value = value; - } - - public Integer timeAsSeconds; - public Double value; - } - - public BasalValue[] getBasalValues() { - try { - JSONArray array = getDefaultProfile().getJSONArray("basal"); - BasalValue[] ret = new BasalValue[array.length()]; - - for (Integer index = 0; index < array.length(); index++) { - JSONObject o = array.getJSONObject(index); - Integer tas = o.getInt("timeAsSeconds"); - Double value = o.getDouble("value"); - ret[index] = new BasalValue(tas, value); - } - return ret; - } catch (JSONException e) { - e.printStackTrace(); - } - return new BasalValue[0]; - } - - public String getBasalList(JSONObject profile) { - if (profile != null) { - try { - return getValuesList(profile.getJSONArray("basal"), null, new DecimalFormat("0.00"), "U"); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ""; - } - - @Nullable - public Double getTargetLow(Integer timeAsSeconds) { - return getTargetLow(getDefaultProfile(), timeAsSeconds); - } - - @Nullable - public Double getTargetLow(JSONObject profile, Integer timeAsSeconds) { - if (profile != null) { - try { - return getValueToTime(profile.getJSONArray("target_low"), timeAsSeconds); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 0D; - } - - @Nullable - public Double getTargetHigh(Integer timeAsSeconds) { - return getTargetHigh(getDefaultProfile(), timeAsSeconds); - } - - @Nullable - public Double getTargetHigh(JSONObject profile, Integer timeAsSeconds) { - if (profile != null) { - try { - return getValueToTime(profile.getJSONArray("target_high"), timeAsSeconds); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return 0D; - } - - public String getTargetList() { - return getTargetList(getDefaultProfile()); - } - - public String getTargetList(JSONObject profile) { - if (profile != null) { - try { - return getValuesList(profile.getJSONArray("target_low"), profile.getJSONArray("target_high"), new DecimalFormat("0.0"), getUnits()); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ""; - } - - public String getActiveProfile() { - if (activeProfile != null) - return activeProfile; - else { - try { - JSONObject store = json.getJSONObject("store"); - String defaultProfileName = (String) json.get("defaultProfile"); - if (store.has(defaultProfileName)) { - return defaultProfileName; - } - log.error("Default profile not found"); - return null; - } catch (JSONException e) { - e.printStackTrace(); - } - } - return null; - } - - public void setActiveProfile(String newProfile) { - try { - JSONObject store = json.getJSONObject("store"); - if (newProfile != null && store.has(newProfile)) { - activeProfile = newProfile; - } else { - log.error("Attempt to set wrong active profile"); - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - - public Double getMaxDailyBasal() { - Double max = 0d; - for (Integer hour = 0; hour < 24; hour++) { - double value = getBasal(hour * 60 * 60); - if (value > max) max = value; - } - return max; - } - - public static int secondsFromMidnight() { - Calendar c = Calendar.getInstance(); - long now = c.getTimeInMillis(); - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - long passed = now - c.getTimeInMillis(); - return (int) (passed / 1000); - } - - public static int secondsFromMidnight(Date date) { - Calendar c = Calendar.getInstance(); - long now = date.getTime(); - c.setTime(date); - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MILLISECOND, 0); - long passed = now - c.getTimeInMillis(); - return (int) (passed / 1000); - } - - public static Double toMgdl(Double value, String units) { - if (units.equals(Constants.MGDL)) return value; - else return value * Constants.MMOLL_TO_MGDL; - } - - public static Double fromMgdlToUnits(Double value, String units) { - if (units.equals(Constants.MGDL)) return value; - else return value * Constants.MGDL_TO_MMOLL; - } - - public static Double toUnits(Double valueInMgdl, Double valueInMmol, String units) { - if (units.equals(Constants.MGDL)) return valueInMgdl; - else return valueInMmol; - } - - public static String toUnitsString(Double valueInMgdl, Double valueInMmol, String units) { - if (units.equals(Constants.MGDL)) return DecimalFormatter.to0Decimal(valueInMgdl); - else return DecimalFormatter.to1Decimal(valueInMmol); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java index 44c6587fb1..91fca44d12 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java @@ -14,10 +14,12 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.db.DbRequest; +import info.nightscout.utils.SP; public class DBAccessReceiver extends BroadcastReceiver { private static Logger log = LoggerFactory.getLogger(DBAccessReceiver.class); @@ -32,6 +34,10 @@ public class DBAccessReceiver extends BroadcastReceiver { if (!nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) { return; } + if (SP.getBoolean(R.string.key_ns_noupload, false)) { + log.debug("Upload disabled. Message dropped"); + return; + } wakeLock.acquire(); try { Bundle bundles = intent.getExtras(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java index c109873faa..901b29ad16 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java @@ -3,13 +3,11 @@ package info.nightscout.androidaps.plugins.NSClientInternal.services; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.PowerManager; -import android.preference.PreferenceManager; import com.google.common.base.Charsets; import com.google.common.hash.Hashing; @@ -25,22 +23,20 @@ import org.slf4j.LoggerFactory; import java.net.URISyntaxException; import java.sql.SQLException; import java.util.Date; -import java.util.Iterator; -import java.util.Map; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAddAck; import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSAuthAck; -import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSPingAck; import info.nightscout.androidaps.plugins.NSClientInternal.acks.NSUpdateAck; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastCals; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastDeviceStatus; @@ -49,9 +45,7 @@ import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastP import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastSgvs; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastStatus; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment; -import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSCal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; @@ -68,15 +62,14 @@ import io.socket.client.Socket; import io.socket.emitter.Emitter; public class NSClientService extends Service { - private static Logger log = LoggerFactory.getLogger(ExecutionService.class); + private static Logger log = LoggerFactory.getLogger(NSClientService.class); static public PowerManager.WakeLock mWakeLock; private IBinder mBinder = new NSClientService.LocalBinder(); - static NSProfile nsProfile; + static ProfileStore profileStore; static public Handler handler; - static private HandlerThread handlerThread; public static Socket mSocket; public static boolean isConnected = false; @@ -92,11 +85,9 @@ public class NSClientService extends Service { static public String nsURL = ""; private String nsAPISecret = ""; private String nsDevice = ""; - private Integer nsHours = 24; + private Integer nsHours = 48; - private final Integer timeToWaitForResponseInMs = 30000; - private boolean uploading = false; - public Date lastReception = new Date(); + public long lastResendTime = 0; public long latestDateInReceivedData = 0; @@ -107,7 +98,7 @@ public class NSClientService extends Service { public NSClientService() { registerBus(); if (handler == null) { - handlerThread = new HandlerThread(NSClientService.class.getSimpleName() + "Handler"); + HandlerThread handlerThread = new HandlerThread(NSClientService.class.getSimpleName() + "Handler"); handlerThread.start(); handler = new Handler(handlerThread.getLooper()); } @@ -180,14 +171,6 @@ public class NSClientService extends Service { restart(); } - public static void setNsProfile(NSProfile profile) { - nsProfile = profile; - } - - public static NSProfile getNsProfile() { - return nsProfile; - } - public void initialize() { dataCounter = 0; @@ -295,7 +278,6 @@ public class NSClientService extends Service { } else { MainApp.bus().post(new EventDismissNotification(Notification.NSCLIENT_NO_WRITE_PERMISSION)); } - lastReception = new Date(); } public void readPreferences() { @@ -318,7 +300,6 @@ public class NSClientService extends Service { private Emitter.Listener onDataUpdate = new Emitter.Listener() { @Override public void call(final Object... args) { - lastReception = new Date(); NSClientService.handler.post(new Runnable() { @Override public void run() { @@ -327,10 +308,8 @@ public class NSClientService extends Service { "onDataUpdate"); wakeLock.acquire(); try { - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); JSONObject data = (JSONObject) args[0]; - NSCal actualCal = new NSCal(); boolean broadcastProfile = false; try { // delta means only increment/changes are comming @@ -342,9 +321,7 @@ public class NSClientService extends Service { JSONArray profiles = (JSONArray) data.getJSONArray("profiles"); if (profiles.length() > 0) { JSONObject profile = (JSONObject) profiles.get(profiles.length() - 1); - String activeProfile = NSClientService.getNsProfile() == null ? null : NSClientService.getNsProfile().getActiveProfile(); - NSProfile nsProfile = new NSProfile(profile, activeProfile); - NSClientService.setNsProfile(nsProfile); + profileStore = new ProfileStore(profile); broadcastProfile = true; MainApp.bus().post(new EventNSClientNewLog("PROFILE", "profile received")); } @@ -366,20 +343,6 @@ public class NSClientService extends Service { BroadcastStatus bs = new BroadcastStatus(); bs.handleNewStatus(nsStatus, MainApp.instance().getApplicationContext(), isDelta); - if (NSClientService.getNsProfile() != null) { - String oldActiveProfile = NSClientService.getNsProfile().getActiveProfile(); - String receivedActiveProfile = nsStatus.getActiveProfile(); - NSClientService.getNsProfile().setActiveProfile(receivedActiveProfile); - if (receivedActiveProfile != null) { - MainApp.bus().post(new EventNSClientNewLog("PROFILE", "status activeProfile received: " + receivedActiveProfile)); - } - // Change possible nulls to "" - String oldP = oldActiveProfile == null ? "" : oldActiveProfile; - String newP = receivedActiveProfile == null ? "" : receivedActiveProfile; - if (!newP.equals(oldP)) { - broadcastProfile = true; - } - } /* Other received data to 2016/02/10 { status: 'ok' @@ -401,9 +364,9 @@ public class NSClientService extends Service { } // If new profile received or change detected broadcast it - if (broadcastProfile && nsProfile != null) { + if (broadcastProfile && profileStore != null) { BroadcastProfile bp = new BroadcastProfile(); - bp.handleNewTreatment(nsProfile, MainApp.instance().getApplicationContext(), isDelta); + bp.handleNewTreatment(profileStore, MainApp.instance().getApplicationContext(), isDelta); MainApp.bus().post(new EventNSClientNewLog("PROFILE", "broadcasting")); } @@ -427,12 +390,11 @@ public class NSClientService extends Service { latestDateInReceivedData = treatment.getMills(); if (treatment.getAction() == null) { - if (!isCurrent(treatment)) continue; addedTreatments.put(jsonTreatment); } else if (treatment.getAction().equals("update")) { - if (!isCurrent(treatment)) continue; updatedTreatments.put(jsonTreatment); } else if (treatment.getAction().equals("remove")) { + if (treatment.getMills() != null && treatment.getMills() > new Date().getTime() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only removedTreatments.put(jsonTreatment); } } @@ -479,9 +441,6 @@ public class NSClientService extends Service { MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals")); // Retreive actual calibration for (Integer index = 0; index < cals.length(); index++) { - if (index == 0) { - actualCal.set(cals.optJSONObject(index)); - } // remove from upload queue if Ack is failing UploadQueue.removeID(cals.optJSONObject(index)); } @@ -489,7 +448,6 @@ public class NSClientService extends Service { } if (data.has("sgvs")) { BroadcastSgvs bs = new BroadcastSgvs(); - String units = nsProfile != null ? nsProfile.getUnits() : "mg/dl"; JSONArray sgvs = (JSONArray) data.getJSONArray("sgvs"); if (sgvs.length() > 0) MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs")); @@ -595,40 +553,6 @@ public class NSClientService extends Service { } } - public void doPing() { - if (!isConnected || !hasWriteAuth) return; - MainApp.bus().post(new EventNSClientNewLog("PING", "Sending")); - uploading = true; - JSONObject message = new JSONObject(); - try { - message.put("mills", new Date().getTime()); - } catch (JSONException e) { - e.printStackTrace(); - } - NSPingAck ack = new NSPingAck(); - mSocket.emit("nsping", message, ack); - synchronized (ack) { - try { - ack.wait(timeToWaitForResponseInMs); - } catch (InterruptedException e) { - } - } - if (ack.received) { - String connectionStatus = "Pong received"; - if (ack.auth_received) { - connectionStatus += ": "; - if (ack.read) connectionStatus += "R"; - if (ack.write) connectionStatus += "W"; - if (ack.write_treatment) connectionStatus += "T"; - } - if (!ack.read) sendAuthMessage(new NSAuthAck()); - MainApp.bus().post(new EventNSClientNewLog("AUTH ", connectionStatus)); - } else { - MainApp.bus().post(new EventNSClientNewLog("PING", "Ping lost")); - } - uploading = false; - } - private boolean isCurrent(NSTreatment treatment) { long now = (new Date()).getTime(); long minPast = now - nsHours * 60L * 60 * 1000; @@ -646,17 +570,22 @@ public class NSClientService extends Service { if (!isConnected || !hasWriteAuth) return; - MainApp.bus().post(new EventNSClientNewLog("QUEUE", "Resend started: " + reason)); - handler.post(new Runnable() { @Override public void run() { - Logger log = LoggerFactory.getLogger(UploadQueue.class); if (mSocket == null || !mSocket.connected()) return; + if (lastResendTime > new Date().getTime() - 10 * 1000L) { + log.debug("Skipping resend by lastResendTime: " + ((new Date().getTime() - lastResendTime) / 1000L) + " sec"); + return; + } + lastResendTime = new Date().getTime(); + + MainApp.bus().post(new EventNSClientNewLog("QUEUE", "Resend started: " + reason)); + CloseableIterator iterator = null; try { - iterator = MainApp.getDbHelper().getDaoDbRequest().closeableIterator(); + iterator = MainApp.getDbHelper().getDbRequestInterator(); try { while (iterator.hasNext()) { DbRequest dbr = iterator.next(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/Autosens.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/Autosens.java deleted file mode 100644 index b504dde984..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/Autosens.java +++ /dev/null @@ -1,255 +0,0 @@ -package info.nightscout.androidaps.plugins.OpenAPSAMA; - -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.MainApp; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; - - -public class Autosens { - private static Logger log = LoggerFactory.getLogger(Autosens.class); - - public static AutosensResult detectSensitivityandCarbAbsorption(List glucose_data, Long mealTime) { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - - //console.error(mealTime); - - double deviationSum = 0; - double carbsAbsorbed = 0; - - List bucketed_data = new ArrayList<>(); - bucketed_data.add(glucose_data.get(0)); - int j = 0; - for (int i = 1; i < glucose_data.size(); ++i) { - long bgTime = glucose_data.get(i).getTimeIndex(); - long lastbgTime = glucose_data.get(i - 1).getTimeIndex(); - //log.error("Processing " + i + ": " + new Date(bgTime).toString() + " " + glucose_data.get(i).value + " Previous: " + new Date(lastbgTime).toString() + " " + glucose_data.get(i - 1).value); - if (glucose_data.get(i).value < 39 || glucose_data.get(i - 1).value < 39) { - continue; - } - - long elapsed_minutes = (bgTime - lastbgTime) / (60 * 1000); - if (Math.abs(elapsed_minutes) > 8) { - // interpolate missing data points - double lastbg = glucose_data.get(i - 1).value; - elapsed_minutes = Math.abs(elapsed_minutes); - //console.error(elapsed_minutes); - long nextbgTime; - while (elapsed_minutes > 5) { - nextbgTime = lastbgTime - 5 * 60 * 1000; - j++; - BgReading newBgreading = new BgReading(); - newBgreading.timeIndex = nextbgTime; - double gapDelta = glucose_data.get(i).value - lastbg; - //console.error(gapDelta, lastbg, elapsed_minutes); - double nextbg = lastbg + (5d / elapsed_minutes * gapDelta); - newBgreading.value = Math.round(nextbg); - //console.error("Interpolated", bucketed_data[j]); - bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value); - - elapsed_minutes = elapsed_minutes - 5; - lastbg = nextbg; - lastbgTime = nextbgTime; - } - j++; - BgReading newBgreading = new BgReading(); - newBgreading.value = glucose_data.get(i).value; - newBgreading.timeIndex = bgTime; - bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value); - } else if (Math.abs(elapsed_minutes) > 2) { - j++; - BgReading newBgreading = new BgReading(); - newBgreading.value = glucose_data.get(i).value; - newBgreading.timeIndex = bgTime; - bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value); - } else { - bucketed_data.get(j).value = (bucketed_data.get(j).value + glucose_data.get(i).value) / 2; - //log.error("***** Average"); - } - } - //console.error(bucketed_data); - double[] avgDeltas = new double[bucketed_data.size() - 2]; - double[] bgis = new double[bucketed_data.size() - 2]; - double[] deviations = new double[bucketed_data.size() - 2]; - - String pastSensitivity = ""; - for (int i = 0; i < bucketed_data.size() - 3; ++i) { - long bgTime = bucketed_data.get(i).timeIndex; - int secondsFromMidnight = NSProfile.secondsFromMidnight(new Date(bgTime)); - - String hour = ""; - //log.debug(new Date(bgTime).toString()); - if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) { - hour += "(" + Math.round(secondsFromMidnight / 3600d) + ")"; - } - - double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits()); - - //console.error(bgTime , bucketed_data[i].glucose); - double bg; - double avgDelta; - double delta; - bg = bucketed_data.get(i).value; - if (bg < 40 || bucketed_data.get(i + 3).value < 40) { - log.error("! value < 40"); - continue; - } - avgDelta = (bg - bucketed_data.get(i + 3).value) / 3; - delta = (bg - bucketed_data.get(i + 1).value); - -// avgDelta = avgDelta.toFixed(2); - IobTotal iob = IobTotal.calulateFromTreatmentsAndTemps(bgTime); - - double bgi = Math.round((-iob.activity * sens * 5) * 100) / 100d; -// bgi = bgi.toFixed(2); - //console.error(delta); - double deviation = delta - bgi; -// deviation = deviation.toFixed(2); - //if (deviation < 0 && deviation > -2) { console.error("BG: "+bg+", avgDelta: "+avgDelta+", BGI: "+bgi+", deviation: "+deviation); } - - // Exclude large positive deviations (carb absorption) from autosens - if (avgDelta - bgi < 6) { - if (deviation > 0) { - pastSensitivity += "+"; - } else if (deviation == 0) { - pastSensitivity += "="; - } else { - pastSensitivity += "-"; - } - avgDeltas[i] = avgDelta; - bgis[i] = bgi; - deviations[i] = deviation; - deviationSum += deviation; - } else { - pastSensitivity += ">"; - //console.error(bgTime); - } - pastSensitivity += hour; - //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); - - // if bgTime is more recent than mealTime - if (mealTime != null && bgTime > mealTime) { - // figure out how many carbs that represents - // but always assume at least 3mg/dL/5m (default) absorption - double ci = Math.max(deviation, SP.getDouble("openapsama_min_5m_carbimpact", 3.0)); - double absorbed = ci * profile.getIc(secondsFromMidnight) / sens; - // and add that to the running total carbsAbsorbed - carbsAbsorbed += absorbed; - } - } - - double ratio = 1; - String ratioLimit = ""; - String sensResult = ""; - - if (mealTime == null) { - //console.error(""); - log.debug(pastSensitivity); - //console.log(JSON.stringify(avgDeltas)); - //console.log(JSON.stringify(bgis)); - Arrays.sort(avgDeltas); - Arrays.sort(bgis); - Arrays.sort(deviations); - - for (double i = 0.9; i > 0.1; i = i - 0.02) { - //console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2)); - if (percentile(deviations, (i + 0.02)) >= 0 && percentile(deviations, i) < 0) { - //console.error("p="+i.toFixed(2)+": "+percentile(avgDeltas, i).toFixed(2)+", "+percentile(bgis, i).toFixed(2)+", "+percentile(deviations, i).toFixed(2)); - log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)"); - } - } - double pSensitive = percentile(deviations, 0.50); - double pResistant = percentile(deviations, 0.45); - //p30 = percentile(deviations, 0.3); - -// average = deviationSum / deviations.length; - - //console.error("Mean deviation: "+average.toFixed(2)); - double basalOff = 0; - - if (pSensitive < 0) { // sensitive - basalOff = pSensitive * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()); - sensResult = "Excess insulin sensitivity detected"; - } else if (pResistant > 0) { // resistant - basalOff = pResistant * (60 / 5) / NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()); - sensResult = "Excess insulin resistance detected"; - } else { - sensResult = "Sensitivity normal"; - } - log.debug(sensResult); - ratio = 1 + (basalOff / profile.getMaxDailyBasal()); - - // don't adjust more than 1.5x - double rawRatio = ratio; - ratio = Math.max(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_min", "0.7"))); - ratio = Math.min(ratio, SafeParse.stringToDouble(SP.getString("openapsama_autosens_max", "1.2"))); - - if (ratio != rawRatio) { - ratioLimit = "Ratio limited from " + rawRatio + " to " + ratio; - log.debug(ratioLimit); - } - - double newisf = Math.round(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) / ratio); - if (ratio != 1) { - log.debug("ISF adjusted from " + NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()), profile.getUnits()) + " to " + newisf); - } - //console.error("Basal adjustment "+basalOff.toFixed(2)+"U/hr"); - //console.error("Ratio: "+ratio*100+"%: new ISF: "+newisf.toFixed(1)+"mg/dL/U"); - } - - 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; - } - - // From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2 - // Returns the value at a given percentile in a sorted numeric array. - // "Linear interpolation between closest ranks" method - public static double percentile(double[] arr, double p) { - if (arr.length == 0) return 0; - if (p <= 0) return arr[0]; - if (p >= 1) return arr[arr.length - 1]; - - double index = arr.length * p, - lower = Math.floor(index), - upper = lower + 1, - weight = index % 1; - - if (upper >= arr.length) return arr[(int) lower]; - return arr[(int) lower] * (1 - weight) + arr[(int) upper] * weight; - } - - // Returns the percentile of the given value in a sorted numeric array. - public static double percentRank(double[] arr, double v) { - for (int i = 0, l = arr.length; i < l; i++) { - if (v <= arr[i]) { - while (i < l && v == arr[i]) i++; - if (i == 0) return 0; - if (v != arr[i - 1]) { - i += (v - arr[i - 1]) / (arr[i] - arr[i - 1]); - } - return i / l; - } - } - return 1; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java index f03a892cae..044374bc86 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java @@ -1,8 +1,5 @@ package info.nightscout.androidaps.plugins.OpenAPSAMA; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - import com.eclipsesource.v8.JavaVoidCallback; import com.eclipsesource.v8.V8; import com.eclipsesource.v8.V8Array; @@ -14,18 +11,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.Date; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.GlucoseStatus; -import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.Loop.ScriptReader; import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.Loop.ScriptReader; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; public class DetermineBasalAdapterAMAJS { private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterAMAJS.class); @@ -192,7 +190,7 @@ public class DetermineBasalAdapterAMAJS { } - public void setData(NSProfile profile, + public void setData(Profile profile, double maxIob, double maxBasal, double minBg, @@ -217,8 +215,8 @@ public class DetermineBasalAdapterAMAJS { mProfile.add("min_bg", minBg); mProfile.add("max_bg", maxBg); mProfile.add("target_bg", targetBg); - mProfile.add("carb_ratio", profile.getIc(profile.secondsFromMidnight())); - mProfile.add("sens", NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units)); + mProfile.add("carb_ratio", profile.getIc()); + mProfile.add("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units)); mProfile.add("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3)); mProfile.add("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4)); mProfile.add("skip_neutral_temps", true); @@ -230,23 +228,28 @@ public class DetermineBasalAdapterAMAJS { mCurrentTemp = new V8Object(mV8rt); mCurrentTemp.add("temp", "absolute"); - mCurrentTemp.add("duration", pump.getTempBasalRemainingMinutes()); - mCurrentTemp.add("rate", pump.getTempBasalAbsoluteRate()); + mCurrentTemp.add("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()); + mCurrentTemp.add("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()); // as we have non default temps longer than 30 mintues - TempBasal tempBasal = pump.getTempBasal(); - if(tempBasal != null){ + TemporaryBasal tempBasal = MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()); + if (tempBasal != null) { mCurrentTemp.add("minutesrunning", tempBasal.getRealDuration()); } mV8rt.add(PARAM_currentTemp, mCurrentTemp); - mIobData = mV8rt.executeArrayScript(IobTotal.convertToJSONArray(iobArray).toString()); + mIobData = mV8rt.executeArrayScript(IobCobCalculatorPlugin.convertToJSONArray(iobArray).toString()); mV8rt.add(PARAM_iobData, mIobData); mGlucoseStatus = new V8Object(mV8rt); mGlucoseStatus.add("glucose", glucoseStatus.glucose); - mGlucoseStatus.add("delta", glucoseStatus.delta); + + if (SP.getBoolean("always_use_shortavg", false)) { + mGlucoseStatus.add("delta", glucoseStatus.short_avgdelta); + } else { + mGlucoseStatus.add("delta", glucoseStatus.delta); + } mGlucoseStatus.add("short_avgdelta", glucoseStatus.short_avgdelta); mGlucoseStatus.add("long_avgdelta", glucoseStatus.long_avgdelta); mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus); 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 652ec856bd..c086ff2cd5 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 @@ -1,8 +1,5 @@ package info.nightscout.androidaps.plugins.OpenAPSAMA; -import android.os.Parcel; -import android.os.Parcelable; - import com.eclipsesource.v8.V8Object; import org.json.JSONArray; @@ -102,7 +99,8 @@ public class DetermineBasalResultAMA extends APSResult { for (int i = 1; i < iob.length(); i ++) { BgReading bg = new BgReading(); bg.value = iob.getInt(i); - bg.timeIndex = startTime + i * 5 * 60 * 1000L; + bg.date = startTime + i * 5 * 60 * 1000L; + bg.isPrediction = true; array.add(bg); } } @@ -111,7 +109,8 @@ public class DetermineBasalResultAMA extends APSResult { for (int i = 1; i < iob.length(); i ++) { BgReading bg = new BgReading(); bg.value = iob.getInt(i); - bg.timeIndex = startTime + i * 5 * 60 * 1000L; + bg.date = startTime + i * 5 * 60 * 1000L; + bg.isPrediction = true; array.add(bg); } } @@ -120,7 +119,8 @@ public class DetermineBasalResultAMA extends APSResult { for (int i = 1; i < iob.length(); i ++) { BgReading bg = new BgReading(); bg.value = iob.getInt(i); - bg.timeIndex = startTime + i * 5 * 60 * 1000L; + bg.date = startTime + i * 5 * 60 * 1000L; + bg.isPrediction = true; array.add(bg); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java index 76753e86a7..c480ebfe3c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/OpenAPSAMAFragment.java @@ -20,12 +20,11 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.utils.JSONFormatter; -public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener, FragmentBase { +public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(OpenAPSAMAFragment.class); private static OpenAPSAMAPlugin openAPSAMAPlugin; 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 2cbffae52a..c39e9a78d3 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,35 +1,32 @@ package info.nightscout.androidaps.plugins.OpenAPSAMA; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Date; -import java.util.List; 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.GlucoseStatus; +import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.Profiler; import info.nightscout.utils.Round; import info.nightscout.utils.SP; @@ -59,7 +56,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.oaps_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -82,6 +79,16 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentVisible(int type, boolean fragmentVisible) { if (type == APS) this.fragmentVisible = fragmentVisible; @@ -125,7 +132,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { } GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); PumpInterface pump = MainApp.getConfigBuilder(); if (!isEnabled(PluginBase.APS)) { @@ -142,20 +149,6 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { return; } - if (profile == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile))); - if (Config.logAPSResult) - log.debug(MainApp.instance().getString(R.string.openapsma_noprofile)); - return; - } - - if (pump == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump))); - if (Config.logAPSResult) - log.debug(MainApp.instance().getString(R.string.openapsma_nopump)); - return; - } - String units = profile.getUnits(); Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL; @@ -171,20 +164,20 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { double maxIob = SP.getDouble("openapsma_max_iob", 1.5d); double maxBasal = SP.getDouble("openapsma_max_basal", 1d); - double minBg = NSProfile.toMgdl(SP.getDouble("openapsma_min_bg", minBgDefault), units); - double maxBg = NSProfile.toMgdl(SP.getDouble("openapsma_max_bg", maxBgDefault), units); - double targetBg = NSProfile.toMgdl(SP.getDouble("openapsma_target_bg", targetBgDefault), units); + double minBg = Profile.toMgdl(SP.getDouble("openapsma_min_bg", minBgDefault), units); + double maxBg = Profile.toMgdl(SP.getDouble("openapsma_max_bg", maxBgDefault), units); + double targetBg = Profile.toMgdl(SP.getDouble("openapsma_target_bg", targetBgDefault), units); minBg = Round.roundTo(minBg, 0.1d); maxBg = Round.roundTo(maxBg, 0.1d); Date start = new Date(); Date startPart = new Date(); - IobTotal[] iobArray = IobTotal.calculateIobArrayInDia(); + IobTotal[] iobArray = IobCobCalculatorPlugin.calculateIobArrayInDia(); Profiler.log(log, "calculateIobArrayInDia()", startPart); startPart = new Date(); - MealData mealData = MainApp.getConfigBuilder().getActiveTreatments().getMealData(); + MealData mealData = MainApp.getConfigBuilder().getMealData(); Profiler.log(log, "getMealData()", startPart); maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); @@ -194,15 +187,12 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]); boolean isTempTarget = false; - TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); - if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) { - TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime()); - if (tempTarget != null) { - isTempTarget = true; - minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); - maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); - targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); - } + TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(new Date().getTime()); + if (tempTarget != null) { + isTempTarget = true; + minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); + maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); + targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); } @@ -210,20 +200,21 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10); if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return; - if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100)) return; - if (!checkOnlyHardLimits(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units), "sens", 2, 900)) return; + if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100)) + return; + if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", 2, 900)) + return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; - startPart = new Date(); - long oldestDataAvailable = MainApp.getConfigBuilder().getActiveTempBasals().oldestDataAvaialable(); - List bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime(Math.max(oldestDataAvailable, (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia()))), false); - log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString() + " (" + bgReadings.size() + " records)"); - Profiler.log(log, "getBgreadingsDataFromTime()", startPart); + long oldestDataAvailable = MainApp.getConfigBuilder().oldestDataAvailable(); + long getBGDataFrom = Math.max(oldestDataAvailable, (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + profile.getDia()))); + log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString()); startPart = new Date(); - if(MainApp.getConfigBuilder().isAMAModeEnabled()){ - lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(bgReadings, null); + if (MainApp.getConfigBuilder().isAMAModeEnabled()) { + //lastAutosensResult = Autosens.detectSensitivityandCarbAbsorption(getBGDataFrom, null); + lastAutosensResult = IobCobCalculatorPlugin.detectSensitivity(getBGDataFrom); } else { lastAutosensResult = new AutosensResult(); } @@ -235,7 +226,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { lastAutosensResult.ratio, //autosensDataRatio isTempTarget, SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact - ); + ); DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke(); @@ -245,7 +236,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { determineBasalResultAMA.changeRequested = false; // limit requests on openloop mode if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { - if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1) + if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) determineBasalResultAMA.changeRequested = false; if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) determineBasalResultAMA.changeRequested = false; @@ -283,7 +274,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { msg += ".\n"; msg += String.format(MainApp.sResources.getString(R.string.openapsma_valuelimitedto), value, newvalue); log.error(msg); - MainApp.getConfigBuilder().uploadError(msg); + NSUpload.uploadError(msg); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error); } return newvalue; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java index 75f87021c5..7df122fc92 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalAdapterMAJS.java @@ -13,12 +13,14 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.utils.SP; public class DetermineBasalAdapterMAJS { private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterMAJS.class); @@ -44,8 +46,8 @@ public class DetermineBasalAdapterMAJS { private String storedProfile = null; private String storedMeal_data = null; - /** - * Main code + /** + * Main code */ public DetermineBasalAdapterMAJS(ScriptReader scriptReader) throws IOException { @@ -105,10 +107,10 @@ public class DetermineBasalAdapterMAJS { mV8rt.executeVoidScript( "console.error(\"determine_basal(\"+\n" + "JSON.stringify(" + PARAM_glucoseStatus + ")+ \", \" +\n" + - "JSON.stringify(" + PARAM_currentTemp + ")+ \", \" +\n" + - "JSON.stringify(" + PARAM_iobData + ")+ \", \" +\n" + - "JSON.stringify(" + PARAM_profile + ")+ \", \" +\n" + - "JSON.stringify(" + PARAM_meal_data + ")+ \") \");" + "JSON.stringify(" + PARAM_currentTemp + ")+ \", \" +\n" + + "JSON.stringify(" + PARAM_iobData + ")+ \", \" +\n" + + "JSON.stringify(" + PARAM_profile + ")+ \", \" +\n" + + "JSON.stringify(" + PARAM_meal_data + ")+ \") \");" ); mV8rt.executeVoidScript( "var rT = determine_basal(" + @@ -215,7 +217,7 @@ public class DetermineBasalAdapterMAJS { } - public void setData(NSProfile profile, + public void setData(Profile profile, double maxIob, double maxBasal, double minBg, @@ -236,12 +238,12 @@ public class DetermineBasalAdapterMAJS { mProfile.add("min_bg", minBg); mProfile.add("max_bg", maxBg); mProfile.add("target_bg", targetBg); - mProfile.add("carb_ratio", profile.getIc(profile.secondsFromMidnight())); - mProfile.add("sens", NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units)); + mProfile.add("carb_ratio", profile.getIc()); + mProfile.add("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units)); mProfile.add("current_basal", pump.getBaseBasalRate()); - mCurrentTemp.add("duration", pump.getTempBasalRemainingMinutes()); - mCurrentTemp.add("rate", pump.getTempBasalAbsoluteRate()); + mCurrentTemp.add("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()); + mCurrentTemp.add("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()); mIobData.add("iob", iobData.iob); //netIob mIobData.add("activity", iobData.activity); //netActivity @@ -251,7 +253,11 @@ public class DetermineBasalAdapterMAJS { mIobData.add("hightempinsulin", iobData.hightempinsulin); mGlucoseStatus.add("glucose", glucoseStatus.glucose); - mGlucoseStatus.add("delta", glucoseStatus.delta); + if (SP.getBoolean("always_use_shortavg", false)) { + mGlucoseStatus.add("delta", glucoseStatus.short_avgdelta); + } else { + mGlucoseStatus.add("delta", glucoseStatus.delta); + } mGlucoseStatus.add("avgdelta", glucoseStatus.avgdelta); mMealData.add("carbs", mealData.carbs); @@ -259,7 +265,7 @@ public class DetermineBasalAdapterMAJS { } - public void release() { + public void release() { mProfile.release(); mCurrentTemp.release(); mIobData.release(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java index bfe4bb5dab..16249dffc3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/OpenAPSMAFragment.java @@ -18,18 +18,17 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; import info.nightscout.utils.JSONFormatter; -public class OpenAPSMAFragment extends Fragment implements View.OnClickListener, FragmentBase { +public class OpenAPSMAFragment extends Fragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(OpenAPSMAFragment.class); private static OpenAPSMAPlugin openAPSMAPlugin; public static OpenAPSMAPlugin getPlugin() { - if(openAPSMAPlugin==null){ + if (openAPSMAPlugin == null) { openAPSMAPlugin = new OpenAPSMAPlugin(); } return openAPSMAPlugin; 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 c4b8f3e34a..11ea2de109 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 @@ -18,14 +18,11 @@ import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.interfaces.TempBasalsInterface; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.ScriptReader; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateResultGui; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; import info.nightscout.utils.DateUtil; import info.nightscout.utils.Profiler; import info.nightscout.utils.Round; @@ -80,6 +77,16 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentVisible(int type, boolean fragmentVisible) { if (type == APS) this.fragmentVisible = fragmentVisible; @@ -123,7 +130,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { } GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); PumpInterface pump = MainApp.getConfigBuilder(); if (!isEnabled(PluginBase.APS)) { @@ -140,20 +147,6 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { return; } - if (profile == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_noprofile))); - if (Config.logAPSResult) - log.debug(MainApp.instance().getString(R.string.openapsma_noprofile)); - return; - } - - if (pump == null) { - MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_nopump))); - if (Config.logAPSResult) - log.debug(MainApp.instance().getString(R.string.openapsma_nopump)); - return; - } - String units = profile.getUnits(); Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL; @@ -169,24 +162,22 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { double maxIob = SP.getDouble("openapsma_max_iob", 1.5d); double maxBasal = SafeParse.stringToDouble(SP.getString("openapsma_max_basal", "1")); - double minBg = NSProfile.toMgdl(SP.getDouble("openapsma_min_bg", minBgDefault), units); - double maxBg = NSProfile.toMgdl(SP.getDouble("openapsma_max_bg", maxBgDefault), units); - double targetBg = NSProfile.toMgdl(SP.getDouble("openapsma_target_bg", targetBgDefault), units); + double minBg = Profile.toMgdl(SP.getDouble("openapsma_min_bg", minBgDefault), units); + double maxBg = Profile.toMgdl(SP.getDouble("openapsma_max_bg", maxBgDefault), units); + double targetBg = Profile.toMgdl(SP.getDouble("openapsma_target_bg", targetBgDefault), units); minBg = Round.roundTo(minBg, 0.1d); maxBg = Round.roundTo(maxBg, 0.1d); Date start = new Date(); - TreatmentsInterface treatments = MainApp.getConfigBuilder().getActiveTreatments(); - TempBasalsInterface tempBasals = MainApp.getConfigBuilder().getActiveTempBasals(); - treatments.updateTotalIOB(); - tempBasals.updateTotalIOB(); - IobTotal bolusIob = treatments.getLastCalculation(); - IobTotal basalIob = tempBasals.getLastCalculation(); + MainApp.getConfigBuilder().updateTotalIOBTreatments(); + MainApp.getConfigBuilder().updateTotalIOBTempBasals(); + IobTotal bolusIob = MainApp.getConfigBuilder().getLastCalculationTreatments(); + IobTotal basalIob = MainApp.getConfigBuilder().getLastCalculationTempBasals(); IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); - MealData mealData = treatments.getMealData(); + MealData mealData = MainApp.getConfigBuilder().getMealData(); maxIob = MainApp.getConfigBuilder().applyMaxIOBConstraints(maxIob); Profiler.log(log, "MA data gathering", start); @@ -194,23 +185,20 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { minBg = verifyHardLimits(minBg, "minBg", Constants.VERY_HARD_LIMIT_MIN_BG[0], Constants.VERY_HARD_LIMIT_MIN_BG[1]); maxBg = verifyHardLimits(maxBg, "maxBg", Constants.VERY_HARD_LIMIT_MAX_BG[0], Constants.VERY_HARD_LIMIT_MAX_BG[1]); targetBg = verifyHardLimits(targetBg, "targetBg", Constants.VERY_HARD_LIMIT_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TARGET_BG[1]); - - TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); - if (tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) { - TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime()); - if (tempTarget != null) { - minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); - maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); - targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); - } + + TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(new Date().getTime()); + if (tempTarget != null) { + minBg = verifyHardLimits(tempTarget.low, "minBg", Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MIN_BG[1]); + maxBg = verifyHardLimits(tempTarget.high, "maxBg", Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[0], Constants.VERY_HARD_LIMIT_TEMP_MAX_BG[1]); + targetBg = verifyHardLimits((tempTarget.low + tempTarget.high) / 2, "targetBg", Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[0], Constants.VERY_HARD_LIMIT_TEMP_TARGET_BG[1]); } maxIob = verifyHardLimits(maxIob, "maxIob", 0, 7); maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, 10); if (!checkOnlyHardLimits(profile.getDia(), "dia", 2, 7)) return; - if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", 2, 100)) return; - if (!checkOnlyHardLimits(NSProfile.toMgdl(profile.getIsf(NSProfile.secondsFromMidnight()).doubleValue(), units), "sens", 2, 900)) return; + if (!checkOnlyHardLimits(profile.getIc(), "carbratio", 2, 100)) return; + if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", 2, 900)) return; if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.1, 10)) return; if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return; @@ -225,7 +213,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface { determineBasalResultMA.changeRequested = false; // limit requests on openloop mode if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { - if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRate()) < 0.1) + if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) determineBasalResultMA.changeRequested = false; if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getBaseBasalRate()) < 0.1) determineBasalResultMA.changeRequested = false; 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 31ffa468d8..f536af5860 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 @@ -22,7 +22,7 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRBolusStart; public class BolusProgressDialog extends DialogFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(BolusProgressDialog.class); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/CalibrationDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/CalibrationDialog.java index 6ff9dceb1f..d1b25fff3a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/CalibrationDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/CalibrationDialog.java @@ -24,8 +24,9 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.PlusMinusEditText; +import info.nightscout.utils.SafeParse; import info.nightscout.utils.XdripCalibrations; public class CalibrationDialog extends DialogFragment implements View.OnClickListener { @@ -34,6 +35,7 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis Button okButton; PlusMinusEditText bgText; TextView unitsView; + TextView bgView; Context context; @@ -58,8 +60,8 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis okButton = (Button) view.findViewById(R.id.overview_calibration_okbutton); okButton.setOnClickListener(this); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - Double bg = profile != null ? NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()) : 0d; + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double bg = profile != null ? Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()) : 0d; String units = Constants.MGDL; if (profile != null) @@ -72,6 +74,7 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis unitsView = (TextView) view.findViewById(R.id.overview_calibration_units); unitsView.setText(units); + bgView = (TextView) view.findViewById(R.id.overview_calibration_bg); return view; } @@ -80,7 +83,8 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis public void onClick(View view) { switch (view.getId()) { case R.id.overview_calibration_okbutton: - final Double bg = bgText.getValue(); + final Double bg = SafeParse.stringToDouble(this.bgView.getText().toString()); + ; XdripCalibrations.confirmAndSendCalibration(bg, context); dismiss(); Answers.getInstance().logCustom(new CustomEvent("Calibration")); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java index a86740cdfd..352c158c1e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/EditQuickWizardDialog.java @@ -71,8 +71,7 @@ public class EditQuickWizardDialog extends DialogFragment implements View.OnClic timeList.add(DateUtil.timeString(DateUtil.toDate(24 * 60 * 60 - 60))); ArrayAdapter adapter = new ArrayAdapter(getContext(), - android.R.layout.simple_spinner_item, timeList); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_centered, timeList); fromSpinner.setAdapter(adapter); toSpinner.setAdapter(adapter); 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 ec25d2a0b0..9b6b7a0f45 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 @@ -24,17 +24,16 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.utils.PlusMinusEditText; import info.nightscout.utils.SafeParse; public class NewTreatmentDialog extends DialogFragment implements OnClickListener { - Button deliverButton; - TextView insulin; - TextView carbs; - PlusMinusEditText editCarbs; PlusMinusEditText editInsulin; @@ -52,13 +51,11 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene Bundle savedInstanceState) { View view = inflater.inflate(R.layout.overview_newtreatment_dialog, null, false); - deliverButton = (Button) view.findViewById(R.id.treatments_newtreatment_deliverbutton); + view.findViewById(R.id.ok).setOnClickListener(this); + view.findViewById(R.id.cancel).setOnClickListener(this); - deliverButton.setOnClickListener(this); getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - insulin = (TextView) view.findViewById(R.id.treatments_newtreatment_insulinamount); - carbs = (TextView) view.findViewById(R.id.treatments_newtreatment_carbsamount); Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); @@ -79,11 +76,11 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene @Override public void onClick(View view) { switch (view.getId()) { - case R.id.treatments_newtreatment_deliverbutton: + case R.id.ok: try { - Double insulin = SafeParse.stringToDouble(this.insulin.getText().toString()); - Integer carbs = SafeParse.stringToInt(this.carbs.getText().toString()); + Double insulin = SafeParse.stringToDouble(editInsulin.getText()); + final Integer carbs = SafeParse.stringToInt(editCarbs.getText()); String confirmMessage = getString(R.string.entertreatmentquestion) + "\n"; @@ -95,8 +92,8 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene if (insulinAfterConstraints - insulin != 0 || carbsAfterConstraints != carbs) confirmMessage += "\n" + getString(R.string.constraintapllied); - final Double finalInsulinAfterConstraints = insulinAfterConstraints; - final Integer finalCarbsAfterConstraints = carbsAfterConstraints; + final double finalInsulinAfterConstraints = insulinAfterConstraints; + final int finalCarbsAfterConstraints = carbsAfterConstraints; final Context context = getContext(); AlertDialog.Builder builder = new AlertDialog.Builder(context); @@ -110,7 +107,14 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene mHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = pump.deliverTreatment(finalInsulinAfterConstraints, finalCarbsAfterConstraints, context); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + if (finalInsulinAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; + if (finalCarbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); if (!result.success) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); @@ -131,6 +135,9 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene e.printStackTrace(); } break; + case R.id.cancel: + dismiss(); + break; } } 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 eaebeec73e..5ba5f3a6f3 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 @@ -34,106 +34,69 @@ import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.Text; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnCheckedChanged; -import butterknife.OnClick; -import butterknife.OnItemSelected; -import butterknife.OnTextChanged; -import butterknife.Unbinder; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventRefreshGui; -import info.nightscout.androidaps.interfaces.TempBasalsInterface; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.OKDialog; import info.nightscout.utils.PlusMinusEditText; +import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; -import static butterknife.OnItemSelected.Callback.NOTHING_SELECTED; - -public class WizardDialog extends DialogFragment { +public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { private static Logger log = LoggerFactory.getLogger(WizardDialog.class); - @BindView(R.id.treatments_wizard_deliverButton) Button wizardDialogDeliverButton; - @BindView(R.id.treatments_wizard_correctioninput) TextView correctionInput; - @BindView(R.id.treatments_wizard_carbsinput) TextView carbsInput; - @BindView(R.id.treatments_wizard_bginput) TextView bgInput; - @BindView(R.id.treatments_wizard_bg) TextView bg; - @BindView(R.id.treatments_wizard_bginsulin) TextView bgInsulin; - @BindView(R.id.treatments_wizard_bgunits) TextView bgUnits; - @BindView(R.id.treatments_wizard_bgcheckbox) CheckBox bgCheckbox; - @BindView(R.id.treatments_wizard_carbs) TextView carbs; - @BindView(R.id.treatments_wizard_carbsinsulin) TextView carbsInsulin; - @BindView(R.id.treatments_wizard_bolusiobinsulin) TextView bolusIobInsulin; - @BindView(R.id.treatments_wizard_basaliobinsulin) TextView basalIobInsulin; - @BindView(R.id.treatments_wizard_bolusiobcheckbox) CheckBox bolusIobCheckbox; - @BindView(R.id.treatments_wizard_basaliobcheckbox) CheckBox basalIobCheckbox; - @BindView(R.id.treatments_wizard_correctioninsulin) TextView correctionInsulin; - @BindView(R.id.treatments_wizard_total) TextView total; - @BindView(R.id.treatments_wizard_totalinsulin) TextView totalInsulin; - @BindView(R.id.treatments_wizard_carbtimeinput) EditText carbTimeEdit; - @BindView(R.id.treatments_wizard_profile) Spinner profileSpinner; - @BindView(R.id.treatments_wizard_sbcheckbox) CheckBox superbolusCheckbox; - @BindView(R.id.treatments_wizard_sb) TextView superbolus; - @BindView(R.id.treatments_wizard_sbinsulin) TextView superbolusInsulin; - @BindView(R.id.treatments_wizard_bgtrendcheckbox) CheckBox bgtrendCheckbox; - @BindView(R.id.treatments_wizard_bgtrend) TextView bgTrend; - @BindView(R.id.treatments_wizard_bgtrendinsulin) TextView bgTrendInsulin; - @BindView(R.id.treatments_wizard_cob_layout) LinearLayout cobLayout; - @BindView(R.id.treatments_wizard_cobcheckbox) CheckBox cobCheckbox; - @BindView(R.id.treatments_wizard_cob) TextView cob; - @BindView(R.id.treatments_wizard_cobinsulin) TextView cobInsulin; PlusMinusEditText editBg; @@ -141,8 +104,6 @@ public class WizardDialog extends DialogFragment { PlusMinusEditText editCorr; PlusMinusEditText editCarbTime; - private Unbinder unbinder; - Integer calculatedCarbs = 0; Double calculatedTotalInsulin = 0d; JSONObject boluscalcJSON; @@ -166,12 +127,6 @@ public class WizardDialog extends DialogFragment { this.context = context; } - @Override - public void onDestroyView() { - super.onDestroyView(); - unbinder.unbind(); - } - @Override public void onResume() { super.onResume(); @@ -240,12 +195,56 @@ public class WizardDialog extends DialogFragment { getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - unbinder = ButterKnife.bind(this, view); + wizardDialogDeliverButton = (Button) view.findViewById(R.id.treatments_wizard_deliverButton); + wizardDialogDeliverButton.setOnClickListener(this); + bg = (TextView) view.findViewById(R.id.treatments_wizard_bg); + bgInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bginsulin); + bgUnits = (TextView) view.findViewById(R.id.treatments_wizard_bgunits); + carbs = (TextView) view.findViewById(R.id.treatments_wizard_carbs); + carbsInsulin = (TextView) view.findViewById(R.id.treatments_wizard_carbsinsulin); + bolusIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bolusiobinsulin); + basalIobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_basaliobinsulin); + correctionInsulin = (TextView) view.findViewById(R.id.treatments_wizard_correctioninsulin); + total = (TextView) view.findViewById(R.id.treatments_wizard_total); + totalInsulin = (TextView) view.findViewById(R.id.treatments_wizard_totalinsulin); + carbTimeEdit = (EditText) view.findViewById(R.id.treatments_wizard_carbtimeinput); + superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb); + superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin); + + bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend); + bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin); + cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout); + cob = (TextView) view.findViewById(R.id.treatments_wizard_cob); + ; + cobInsulin = (TextView) view.findViewById(R.id.treatments_wizard_cobinsulin); + ; + + bgCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgcheckbox); + bolusIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bolusiobcheckbox); + basalIobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_basaliobcheckbox); + superbolusCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_sbcheckbox); + bgtrendCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_bgtrendcheckbox); + cobCheckbox = (CheckBox) view.findViewById(R.id.treatments_wizard_cobcheckbox); + bgCheckbox.setOnCheckedChangeListener(this); + basalIobCheckbox.setOnCheckedChangeListener(this); + bolusIobCheckbox.setOnCheckedChangeListener(this); + superbolusCheckbox.setOnCheckedChangeListener(this); + bgtrendCheckbox.setOnCheckedChangeListener(this); + cobCheckbox.setOnCheckedChangeListener(this); + + profileSpinner = (Spinner) view.findViewById(R.id.treatments_wizard_profile); + profileSpinner.setOnItemSelectedListener(this); + + correctionInput = (TextView) view.findViewById(R.id.treatments_wizard_correctioninput); + carbsInput = (TextView) view.findViewById(R.id.treatments_wizard_carbsinput); + bgInput = (TextView) view.findViewById(R.id.treatments_wizard_bginput); correctionInput.addTextChangedListener(textWatcher); carbsInput.addTextChangedListener(textWatcher); bgInput.addTextChangedListener(textWatcher); + superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE); + Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); Double maxCorrection = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); @@ -258,106 +257,105 @@ public class WizardDialog extends DialogFragment { return view; } - @OnCheckedChanged({R.id.treatments_wizard_bgcheckbox, R.id.treatments_wizard_bolusiobcheckbox, R.id.treatments_wizard_basaliobcheckbox, R.id.treatments_wizard_sbcheckbox, R.id.treatments_wizard_cobcheckbox, R.id.treatments_wizard_bgtrendcheckbox}) - public void checkboxToggled(boolean isChecked) { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { calculateInsulin(); } - @OnItemSelected(R.id.treatments_wizard_profile) - public void profileSelected(int position) { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { calculateInsulin(); wizardDialogDeliverButton.setVisibility(View.VISIBLE); } - @OnItemSelected(value = R.id.treatments_wizard_profile, - callback = NOTHING_SELECTED) - public void profileNotSelected() { + @Override + public void onNothingSelected(AdapterView parent) { ToastUtils.showToastInUiThread(context, MainApp.sResources.getString(R.string.noprofileselected)); wizardDialogDeliverButton.setVisibility(View.GONE); } - @OnClick(R.id.treatments_wizard_deliverButton) + @Override public void onClick(View view) { - if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { - DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); - String confirmMessage = getString(R.string.entertreatmentquestion); + switch (view.getId()) { + case R.id.treatments_wizard_deliverButton: + if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { + DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); + String confirmMessage = getString(R.string.entertreatmentquestion); - Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(calculatedTotalInsulin); - Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(calculatedCarbs); + Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(calculatedTotalInsulin); + Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(calculatedCarbs); - confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; - confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; + confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; + confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - if (insulinAfterConstraints - calculatedTotalInsulin != 0 || !carbsAfterConstraints.equals(calculatedCarbs)) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput)); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - return; - } - - final Double finalInsulinAfterConstraints = insulinAfterConstraints; - final Integer finalCarbsAfterConstraints = carbsAfterConstraints; - final Double bg = SafeParse.stringToDouble(bgInput.getText().toString()); - final int carbTime = SafeParse.stringToInt(carbTimeEdit.getText().toString()); - final boolean useSuperBolus = superbolusCheckbox.isChecked(); - - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); - builder.setMessage(confirmMessage); - builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { - final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); - mHandler.post(new Runnable() { - @Override - public void run() { - PumpEnactResult result = pump.deliverTreatmentFromBolusWizard( - context, - finalInsulinAfterConstraints, - finalCarbsAfterConstraints, - bg, - "Manual", - carbTime, - boluscalcJSON - ); - if (!result.success) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - } - if (useSuperBolus) { - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - result = pump.setTempBasalAbsolute(0d, 120); - if (!result.success) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); - builder.setMessage(result.comment); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); - builder.show(); - } - if (activeloop != null) { - activeloop.superBolusTo(new Date().getTime() + 2 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshGui(false)); - } - } - } - }); - Answers.getInstance().logCustom(new CustomEvent("Wizard")); + if (insulinAfterConstraints - calculatedTotalInsulin != 0 || !carbsAfterConstraints.equals(calculatedCarbs)) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); + builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput)); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); + builder.show(); + return; } + + final Double finalInsulinAfterConstraints = insulinAfterConstraints; + final Integer finalCarbsAfterConstraints = carbsAfterConstraints; + final Double bg = SafeParse.stringToDouble(bgInput.getText().toString()); + final int carbTime = SafeParse.stringToInt(carbTimeEdit.getText().toString()); + final boolean useSuperBolus = superbolusCheckbox.isChecked(); + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(confirmMessage); + builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { + final ConfigBuilderPlugin pump = MainApp.getConfigBuilder(); + mHandler.post(new Runnable() { + @Override + public void run() { + PumpEnactResult result; + if (useSuperBolus) { + final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + if (activeloop != null) { + activeloop.superBolusTo(new Date().getTime() + 2 * 60L * 60 * 1000); + MainApp.bus().post(new EventRefreshGui(false)); + } + result = pump.setTempBasalAbsolute(0d, 120); + if (!result.success) { + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror), result.comment, null); + } + } + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.glucose = bg; + detailedBolusInfo.glucoseType = "Manual"; + detailedBolusInfo.carbTime = carbTime; + detailedBolusInfo.boluscalc = boluscalcJSON; + detailedBolusInfo.source = Source.USER; + result = pump.deliverTreatment(detailedBolusInfo); + if (!result.success) { + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.treatmentdeliveryerror), result.comment, null); + } + } + }); + Answers.getInstance().logCustom(new CustomEvent("Wizard")); + } + } + }); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.show(); + dismiss(); } - }); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.show(); - dismiss(); + break; } } private void initDialog() { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); + ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); if (profile == null) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); @@ -365,14 +363,14 @@ public class WizardDialog extends DialogFragment { } ArrayList profileList; - profileList = profile.getProfileList(); + profileList = profileStore.getProfileList(); ArrayAdapter adapter = new ArrayAdapter(getContext(), - android.R.layout.simple_spinner_item, profileList); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_centered, profileList); + profileSpinner.setAdapter(adapter); // set selected to actual profile for (int p = 0; p < profileList.size(); p++) { - if (profileList.get(p).equals(profile.getActiveProfile())) + if (profileList.get(p).equals(MainApp.getConfigBuilder().getProfileName())) profileSpinner.setSelection(p); } @@ -382,13 +380,13 @@ public class WizardDialog extends DialogFragment { else editBg.setStep(0.1d); // Set BG if not old - BgReading lastBg = GlucoseStatus.actualBg(); + BgReading lastBg = DatabaseHelper.actualBg(); if (lastBg != null) { Double lastBgValue = lastBg.valueToUnits(units); - Double sens = profile.getIsf(NSProfile.secondsFromMidnight()); - Double targetBGLow = profile.getTargetLow(NSProfile.secondsFromMidnight()); - Double targetBGHigh = profile.getTargetHigh(NSProfile.secondsFromMidnight()); + Double sens = profile.getIsf(); + Double targetBGLow = profile.getTargetLow(); + Double targetBGHigh = profile.getTargetHigh(); Double bgDiff; if (lastBgValue <= targetBGLow) { bgDiff = lastBgValue - targetBGLow; @@ -412,15 +410,10 @@ public class WizardDialog extends DialogFragment { } // IOB calculation - TreatmentsInterface treatments = ConfigBuilderPlugin.getActiveTreatments(); - treatments.updateTotalIOB(); - IobTotal bolusIob = treatments.getLastCalculation(); - TempBasalsInterface tempBasals = ConfigBuilderPlugin.getActiveTempBasals(); - IobTotal basalIob = new IobTotal(new Date().getTime()); - if (tempBasals != null) { - tempBasals.updateTotalIOB(); - basalIob = tempBasals.getLastCalculation().round(); - } + MainApp.getConfigBuilder().updateTotalIOBTreatments(); + IobTotal bolusIob = MainApp.getConfigBuilder().getLastCalculationTreatments().round(); + MainApp.getConfigBuilder().updateTotalIOBTempBasals(); + IobTotal basalIob = MainApp.getConfigBuilder().getLastCalculationTempBasals().round(); bolusIobInsulin.setText(DecimalFormatter.to2Decimal(-bolusIob.iob) + "U"); basalIobInsulin.setText(DecimalFormatter.to2Decimal(-basalIob.basaliob) + "U"); @@ -439,11 +432,11 @@ public class WizardDialog extends DialogFragment { } private void calculateInsulin() { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + ProfileStore profile = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); if (profileSpinner == null || profileSpinner.getSelectedItem() == null) return; // not initialized yet String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString(); - JSONObject specificProfile = profile.getSpecificProfile(selectedAlternativeProfile); + Profile specificProfile = profile.getSpecificProfile(selectedAlternativeProfile); // Entered values Double c_bg = SafeParse.stringToDouble(bgInput.getText().toString()); @@ -517,7 +510,7 @@ public class WizardDialog extends DialogFragment { // Trend if (bgtrendCheckbox.isChecked()) { if (wizard.glucoseStatus != null) { - bgTrend.setText((wizard.glucoseStatus.avgdelta > 0 ? "+" : "") + NSProfile.toUnitsString(wizard.glucoseStatus.avgdelta * 3, wizard.glucoseStatus.avgdelta * 3 / 18, profile.getUnits()) + " " + profile.getUnits()); + bgTrend.setText((wizard.glucoseStatus.avgdelta > 0 ? "+" : "") + Profile.toUnitsString(wizard.glucoseStatus.avgdelta * 3, wizard.glucoseStatus.avgdelta * 3 / 18, specificProfile.getUnits()) + " " + specificProfile.getUnits()); } else { bgTrend.setText(""); } @@ -571,4 +564,5 @@ public class WizardDialog extends DialogFragment { e.printStackTrace(); } } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java index 0508917312..c9a80dbaef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java @@ -23,7 +23,13 @@ public class Notification { public static final int OLD_NSCLIENT = 8; public static final int INVALID_PHONE_NUMBER = 9; public static final int APPROACHING_DAILY_LIMIT = 10; - public static final int NSCLIENT_NO_WRITE_PERMISSION = 10; + public static final int NSCLIENT_NO_WRITE_PERMISSION = 11; + public static final int MISSING_SMS_PERMISSION = 12; + public static final int ISF_MISSING = 13; + public static final int IC_MISSING = 14; + public static final int BASAL_MISSING = 15; + public static final int TARGET_MISSING = 16; + public static final int ANNOUNCEMENT = 17; public int id; public Date date; 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 22d5e48b57..7d81f307a2 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 @@ -2,15 +2,15 @@ package info.nightscout.androidaps.plugins.Overview; import android.annotation.SuppressLint; import android.app.Activity; +import android.app.NotificationManager; +import android.content.Context; import android.content.DialogInterface; -import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; -import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; @@ -18,6 +18,8 @@ import android.support.v7.app.AlertDialog; import android.support.v7.widget.CardView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.util.TypedValue; import android.view.ContextMenu; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; @@ -33,11 +35,13 @@ import android.widget.TextView; import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.LabelFormatter; import com.jjoe64.graphview.ValueDependentColor; +import com.jjoe64.graphview.Viewport; import com.jjoe64.graphview.series.BarGraphSeries; import com.jjoe64.graphview.series.DataPoint; import com.jjoe64.graphview.series.LineGraphSeries; -import com.jjoe64.graphview.series.PointsGraphSeries; +import com.jjoe64.graphview.series.Series; import com.squareup.otto.Subscribe; import org.json.JSONException; @@ -51,34 +55,51 @@ import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventCareportalEventChange; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.events.EventNewBG; -import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.BasalData; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; -import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog; @@ -86,21 +107,24 @@ import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.Profiler; import info.nightscout.utils.Round; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; -public class OverviewFragment extends Fragment { +public class OverviewFragment extends Fragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(OverviewFragment.class); private static OverviewPlugin overviewPlugin = new OverviewPlugin(); @@ -109,28 +133,41 @@ public class OverviewFragment extends Fragment { return overviewPlugin; } + TextView timeView; TextView bgView; TextView arrowView; TextView timeAgoView; TextView deltaView; TextView avgdeltaView; - TextView runningTempView; TextView baseBasalView; - LinearLayout basalLayout; + TextView extendedBolusView; TextView activeProfileView; TextView iobView; + TextView cobView; TextView apsModeView; TextView tempTargetView; TextView pumpStatusView; LinearLayout loopStatusLayout; LinearLayout pumpStatusLayout; GraphView bgGraph; + GraphView iobGraph; + + TextView iage; + TextView cage; + TextView sage; + TextView pbage; + + TextView updating; + CheckBox showPredictionView; + CheckBox showBasalsView; + CheckBox showIobView; + CheckBox showCobView; + CheckBox showDeviationsView; RecyclerView notificationsView; LinearLayoutManager llm; - LinearLayout cancelTempLayout; LinearLayout acceptTempLayout; Button cancelTempButton; Button treatmentButton; @@ -139,12 +176,21 @@ public class OverviewFragment extends Fragment { Button acceptTempButton; Button quickWizardButton; + boolean smallWidth; + boolean smallHeight; + + + private int rangeToDisplay = 6; // for graph + Handler sLoopHandler = new Handler(); Runnable sRefreshLoop = null; private static Handler sHandler; private static HandlerThread sHandlerThread; + private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledUpdate = null; + public OverviewFragment() { super(); if (sHandlerThread == null) { @@ -158,167 +204,134 @@ public class OverviewFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.overview_fragment, container, false); + //check screen width + final DisplayMetrics dm = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + int screen_width = dm.widthPixels; + int screen_height = dm.heightPixels; + smallWidth = screen_width < Constants.SMALL_WIDTH; + smallHeight = screen_height < Constants.SMALL_HEIGHT; + + View view; + + if (MainApp.sResources.getBoolean(R.bool.isTablet)) { + view = inflater.inflate(R.layout.overview_fragment_tablet, container, false); + } else if (smallHeight) { + view = inflater.inflate(R.layout.overview_fragment_smallheight, container, false); + } else { + view = inflater.inflate(R.layout.overview_fragment, container, false); + } + + timeView = (TextView) view.findViewById(R.id.overview_time); bgView = (TextView) view.findViewById(R.id.overview_bg); arrowView = (TextView) view.findViewById(R.id.overview_arrow); + if (smallWidth) { + arrowView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 35); + } timeAgoView = (TextView) view.findViewById(R.id.overview_timeago); deltaView = (TextView) view.findViewById(R.id.overview_delta); avgdeltaView = (TextView) view.findViewById(R.id.overview_avgdelta); - runningTempView = (TextView) view.findViewById(R.id.overview_runningtemp); baseBasalView = (TextView) view.findViewById(R.id.overview_basebasal); - basalLayout = (LinearLayout) view.findViewById(R.id.overview_basallayout); + extendedBolusView = (TextView) view.findViewById(R.id.overview_extendedbolus); activeProfileView = (TextView) view.findViewById(R.id.overview_activeprofile); pumpStatusView = (TextView) view.findViewById(R.id.overview_pumpstatus); loopStatusLayout = (LinearLayout) view.findViewById(R.id.overview_looplayout); pumpStatusLayout = (LinearLayout) view.findViewById(R.id.overview_pumpstatuslayout); + pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder)); + iobView = (TextView) view.findViewById(R.id.overview_iob); + cobView = (TextView) view.findViewById(R.id.overview_cob); apsModeView = (TextView) view.findViewById(R.id.overview_apsmode); tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget); + + iage = (TextView) view.findViewById(R.id.careportal_insulinage); + cage = (TextView) view.findViewById(R.id.careportal_canulaage); + sage = (TextView) view.findViewById(R.id.careportal_sensorage); + pbage = (TextView) view.findViewById(R.id.careportal_pbage); + + updating = (TextView) view.findViewById(R.id.overview_updating); + bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph); - cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); - treatmentButton = (Button) view.findViewById(R.id.overview_treatment); - wizardButton = (Button) view.findViewById(R.id.overview_wizard); - cancelTempButton = (Button) view.findViewById(R.id.overview_canceltemp); - cancelTempLayout = (LinearLayout) view.findViewById(R.id.overview_canceltemplayout); + iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph); + + cancelTempButton = (Button) view.findViewById(R.id.overview_canceltempbutton); + cancelTempButton.setOnClickListener(this); + treatmentButton = (Button) view.findViewById(R.id.overview_treatmentbutton); + treatmentButton.setOnClickListener(this); + wizardButton = (Button) view.findViewById(R.id.overview_wizardbutton); + wizardButton.setOnClickListener(this); acceptTempButton = (Button) view.findViewById(R.id.overview_accepttempbutton); + acceptTempButton.setOnClickListener(this); + quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizardbutton); + quickWizardButton.setOnClickListener(this); + calibrationButton = (Button) view.findViewById(R.id.overview_calibrationbutton); + calibrationButton.setOnClickListener(this); + acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); - quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard); - calibrationButton = (Button) view.findViewById(R.id.overview_calibration); + showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction); + showBasalsView = (CheckBox) view.findViewById(R.id.overview_showbasals); + showIobView = (CheckBox) view.findViewById(R.id.overview_showiob); + showCobView = (CheckBox) view.findViewById(R.id.overview_showcob); + showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations); + showPredictionView.setChecked(SP.getBoolean("showprediction", false)); + showBasalsView.setChecked(SP.getBoolean("showbasals", true)); + showIobView.setChecked(SP.getBoolean("showiob", false)); + showCobView.setChecked(SP.getBoolean("showcob", false)); + showDeviationsView.setChecked(SP.getBoolean("showdeviations", false)); + showPredictionView.setOnCheckedChangeListener(this); + showBasalsView.setOnCheckedChangeListener(this); + showIobView.setOnCheckedChangeListener(this); + showCobView.setOnCheckedChangeListener(this); + showDeviationsView.setOnCheckedChangeListener(this); notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications); notificationsView.setHasFixedSize(true); llm = new LinearLayoutManager(view.getContext()); notificationsView.setLayoutManager(llm); - - showPredictionView.setChecked(SP.getBoolean("showprediction", false)); - - showPredictionView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { +/* + final LinearLayout graphs = (LinearLayout)view.findViewById(R.id.overview_graphs_layout); + ViewTreeObserver observer = graphs.getViewTreeObserver(); + observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putBoolean("showprediction", showPredictionView.isChecked()); - editor.apply(); - updateGUI(); + public void onGlobalLayout() { + log.debug("Height: " + graphs.getHeight()); + graphs.getViewTreeObserver().removeGlobalOnLayoutListener( + this); + int heightNeeded = Math.max(320, graphs.getHeight() - 200); + if (heightNeeded != bgGraph.getHeight()) + bgGraph.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heightNeeded)); + } + }); +*/ + bgGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid)); + bgGraph.getGridLabelRenderer().reloadStyles(); + iobGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid)); + iobGraph.getGridLabelRenderer().reloadStyles(); + iobGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false); + bgGraph.getGridLabelRenderer().setLabelVerticalWidth(50); + iobGraph.getGridLabelRenderer().setLabelVerticalWidth(50); + iobGraph.getGridLabelRenderer().setNumVerticalLabels(5); + + bgGraph.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + rangeToDisplay += 6; + rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; + updateGUI("rangeChange"); + return false; } }); - treatmentButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - FragmentManager manager = getFragmentManager(); - NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog(); - treatmentDialogFragment.show(manager, "TreatmentDialog"); - } - }); - - wizardButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - FragmentManager manager = getFragmentManager(); - WizardDialog wizardDialog = new WizardDialog(); - wizardDialog.show(manager, "WizardDialog"); - } - }); - - quickWizardButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - processQuickWizard(); - } - }); - - cancelTempButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - final PumpInterface pump = MainApp.getConfigBuilder(); - if (pump.isTempBasalInProgress()) { - sHandler.post(new Runnable() { - @Override - public void run() { - pump.cancelTempBasal(); - MainApp.bus().post(new EventTempBasalChange()); - Answers.getInstance().logCustom(new CustomEvent("CancelTemp")); - } - }); - } - } - }); - - calibrationButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - FragmentManager manager = getFragmentManager(); - CalibrationDialog calibrationDialog = new CalibrationDialog(); - calibrationDialog.show(manager, "CalibrationDialog"); - } - }); - - acceptTempButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (ConfigBuilderPlugin.getActiveLoop() != null) { - ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false); - final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; - if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setTitle(getContext().getString(R.string.confirmation)); - builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); - builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - sHandler.post(new Runnable() { - @Override - public void run() { - hideTempRecommendation(); - PumpEnactResult applyResult = MainApp.getConfigBuilder().applyAPSRequest(finalLastRun.constraintsProcessed); - if (applyResult.enacted) { - finalLastRun.setByPump = applyResult; - finalLastRun.lastEnact = new Date(); - finalLastRun.lastOpenModeAccept = new Date(); - MainApp.getConfigBuilder().uploadDeviceStatus(); - ObjectivesPlugin objectivesPlugin = (ObjectivesPlugin) MainApp.getSpecificPlugin(ObjectivesPlugin.class); - if (objectivesPlugin != null) { - objectivesPlugin.manualEnacts++; - objectivesPlugin.saveProgress(); - } - } - updateGUIIfVisible(); - } - }); - Answers.getInstance().logCustom(new CustomEvent("AcceptTemp")); - } - }); - builder.setNegativeButton(getContext().getString(R.string.cancel), null); - builder.show(); - } - updateGUI(); - } - } - }); - - pumpStatusView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().isInitialized()) - sHandler.post(new Runnable() { - @Override - public void run() { - MainApp.getConfigBuilder().refreshDataFromPump("RefreshClicked"); - } - }); - } - }); - - updateGUI(); return view; } + @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (activeloop == null) return; menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop)); @@ -341,52 +354,139 @@ public class OverviewFragment extends Fragment { menu.add(MainApp.sResources.getString(R.string.enableloop)); } + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + switch (buttonView.getId()) { + case R.id.overview_showprediction: + SP.putBoolean("showprediction", showPredictionView.isChecked()); + updateGUI("onPredictionCheckedChanged"); + break; + case R.id.overview_showbasals: + SP.putBoolean("showbasals", showBasalsView.isChecked()); + updateGUI("onBasalsCheckedChanged"); + break; + case R.id.overview_showiob: + SP.putBoolean("showiob", showIobView.isChecked()); + updateGUI("onIobCheckedChanged"); + break; + case R.id.overview_showcob: + showDeviationsView.setOnCheckedChangeListener(null); + showDeviationsView.setChecked(false); + showDeviationsView.setOnCheckedChangeListener(this); + SP.putBoolean("showcob", showCobView.isChecked()); + SP.putBoolean("showdeviations", showDeviationsView.isChecked()); + updateGUI("onCobCheckedChanged"); + break; + case R.id.overview_showdeviations: + showCobView.setOnCheckedChangeListener(null); + showCobView.setChecked(false); + showCobView.setOnCheckedChangeListener(this); + SP.putBoolean("showcob", showCobView.isChecked()); + SP.putBoolean("showdeviations", showDeviationsView.isChecked()); + updateGUI("onDeviationsCheckedChanged"); + break; + } + } + @Override public boolean onContextItemSelected(MenuItem item) { - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (item.getTitle().equals(MainApp.sResources.getString(R.string.disableloop))) { activeloop.setFragmentEnabled(PluginBase.LOOP, false); activeloop.setFragmentVisible(PluginBase.LOOP, false); MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshGui(false)); - return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.enableloop))) { - activeloop.setFragmentEnabled(PluginBase.LOOP, true); - activeloop.setFragmentVisible(PluginBase.LOOP, true); - MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshGui(false)); - return true; - } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.resume))) { - activeloop.suspendTo(0L); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - MainApp.bus().post(new EventRefreshGui(false)); PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); + NSUpload.uploadOpenAPSOffline(60); // upload 60 min, we don;t know real duration + return true; + } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.enableloop))) { + activeloop.setFragmentEnabled(PluginBase.LOOP, true); + activeloop.setFragmentVisible(PluginBase.LOOP, true); + MainApp.getConfigBuilder().storeSettings(); + updateGUI("suspendmenu"); + NSUpload.uploadOpenAPSOffline(0); + return true; + } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.resume))) { + activeloop.suspendTo(0L); + updateGUI("suspendmenu"); + sHandler.post(new Runnable() { + @Override + public void run() { + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + } + } + }); + NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor1h))) { activeloop.suspendTo(new Date().getTime() + 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshGui(false)); + updateGUI("suspendmenu"); + sHandler.post(new Runnable() { + @Override + public void run() { + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + } + } + }); + NSUpload.uploadOpenAPSOffline(60); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor2h))) { activeloop.suspendTo(new Date().getTime() + 2 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshGui(false)); + updateGUI("suspendmenu"); + sHandler.post(new Runnable() { + @Override + public void run() { + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + } + } + }); + NSUpload.uploadOpenAPSOffline(120); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor3h))) { activeloop.suspendTo(new Date().getTime() + 3 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshGui(false)); + updateGUI("suspendmenu"); + sHandler.post(new Runnable() { + @Override + public void run() { + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + } + } + }); + NSUpload.uploadOpenAPSOffline(180); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor10h))) { activeloop.suspendTo(new Date().getTime() + 10 * 60L * 60 * 1000); - MainApp.bus().post(new EventRefreshGui(false)); + updateGUI("suspendmenu"); + sHandler.post(new Runnable() { + @Override + public void run() { + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + if (!result.success) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); + } + } + }); + NSUpload.uploadOpenAPSOffline(600); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) { activeloop.suspendTo(new Date().getTime() + 30L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { @@ -394,66 +494,152 @@ public class OverviewFragment extends Fragment { if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } - MainApp.bus().post(new EventRefreshGui(false)); } }); + NSUpload.uploadOpenAPSOffline(30); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor1h))) { activeloop.suspendTo(new Date().getTime() + 1 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - MainApp.bus().post(new EventRefreshGui(false)); PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 60); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); + NSUpload.uploadOpenAPSOffline(60); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor2h))) { activeloop.suspendTo(new Date().getTime() + 2 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - MainApp.bus().post(new EventRefreshGui(false)); PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 2 * 60); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); + NSUpload.uploadOpenAPSOffline(120); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor3h))) { activeloop.suspendTo(new Date().getTime() + 3 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - MainApp.bus().post(new EventRefreshGui(false)); PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 3 * 60); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); + NSUpload.uploadOpenAPSOffline(180); return true; } return super.onContextItemSelected(item); } - void processQuickWizard() { - final BgReading actualBg = GlucoseStatus.actualBg(); - if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet - return; - final NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + @Override + public void onClick(View v) { + FragmentManager manager = getFragmentManager(); + switch (v.getId()) { + case R.id.overview_accepttempbutton: + onClickAcceptTemp(); + break; + case R.id.overview_quickwizardbutton: + onClickQuickwizard(); + break; + case R.id.overview_wizardbutton: + WizardDialog wizardDialog = new WizardDialog(); + wizardDialog.show(manager, "WizardDialog"); + break; + case R.id.overview_calibrationbutton: + CalibrationDialog calibrationDialog = new CalibrationDialog(); + calibrationDialog.show(manager, "CalibrationDialog"); + break; + case R.id.overview_treatmentbutton: + NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog(); + treatmentDialogFragment.show(manager, "TreatmentDialog"); + break; + case R.id.overview_canceltempbutton: + final PumpInterface pump = MainApp.getConfigBuilder(); + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + sHandler.post(new Runnable() { + @Override + public void run() { + pump.cancelTempBasal(); + Answers.getInstance().logCustom(new CustomEvent("CancelTemp")); + } + }); + } + break; + case R.id.overview_pumpstatus: + if (MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().isInitialized()) + sHandler.post(new Runnable() { + @Override + public void run() { + MainApp.getConfigBuilder().refreshDataFromPump("RefreshClicked"); + } + }); + break; + } + + } + + private void onClickAcceptTemp() { + if (ConfigBuilderPlugin.getActiveLoop() != null) { + ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false); + final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; + if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.changeRequested) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getContext().getString(R.string.confirmation)); + builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); + builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + sHandler.post(new Runnable() { + @Override + public void run() { + hideTempRecommendation(); + clearNotification(); + PumpEnactResult applyResult = MainApp.getConfigBuilder().applyAPSRequest(finalLastRun.constraintsProcessed); + if (applyResult.enacted) { + finalLastRun.setByPump = applyResult; + finalLastRun.lastEnact = new Date(); + finalLastRun.lastOpenModeAccept = new Date(); + NSUpload.uploadDeviceStatus(); + ObjectivesPlugin objectivesPlugin = (ObjectivesPlugin) MainApp.getSpecificPlugin(ObjectivesPlugin.class); + if (objectivesPlugin != null) { + ObjectivesPlugin.manualEnacts++; + ObjectivesPlugin.saveProgress(); + } + } + scheduleUpdateGUI("onClickAcceptTemp"); + } + }); + Answers.getInstance().logCustom(new CustomEvent("AcceptTemp")); + } + }); + builder.setNegativeButton(getContext().getString(R.string.cancel), null); + builder.show(); + } + } + } + + void onClickQuickwizard() { + final BgReading actualBg = DatabaseHelper.actualBg(); + final Profile profile = MainApp.getConfigBuilder().getProfile(); QuickWizard.QuickWizardEntry quickWizardEntry = getPlugin().quickWizard.getActive(); if (quickWizardEntry != null && actualBg != null) { quickWizardButton.setVisibility(View.VISIBLE); - String text = MainApp.sResources.getString(R.string.bolus) + ": " + quickWizardEntry.buttonText(); BolusWizard wizard = new BolusWizard(); - wizard.doCalc(profile.getDefaultProfile(), quickWizardEntry.carbs(), 0d, actualBg.valueToUnits(profile.getUnits()), 0d, true, true, false, true); + wizard.doCalc(profile, quickWizardEntry.carbs(), 0d, actualBg.valueToUnits(profile.getUnits()), 0d, true, true, false, false); final JSONObject boluscalcJSON = new JSONObject(); try { @@ -487,7 +673,7 @@ public class OverviewFragment extends Fragment { confirmMessage += "\n" + getString(R.string.bolus) + ": " + formatNumber2decimalplaces.format(insulinAfterConstraints) + "U"; confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - if (insulinAfterConstraints - wizard.calculatedTotalInsulin != 0 || carbsAfterConstraints != quickWizardEntry.carbs()) { + if (!insulinAfterConstraints.equals(wizard.calculatedTotalInsulin) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); builder.setMessage(getString(R.string.constraints_violation) + "\n" + getString(R.string.changeyourinput)); @@ -498,8 +684,8 @@ public class OverviewFragment extends Fragment { final Double finalInsulinAfterConstraints = insulinAfterConstraints; final Integer finalCarbsAfterConstraints = carbsAfterConstraints; - - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + final Context context = getContext(); + AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); builder.setMessage(confirmMessage); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { @@ -509,15 +695,14 @@ public class OverviewFragment extends Fragment { sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = pump.deliverTreatmentFromBolusWizard( - getContext(), - finalInsulinAfterConstraints, - finalCarbsAfterConstraints, - actualBg.valueToUnits(profile.getUnits()), - "Manual", - 0, - boluscalcJSON - ); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD; + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.carbs = finalCarbsAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.boluscalc = boluscalcJSON; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); if (!result.success) { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(MainApp.sResources.getString(R.string.treatmentdeliveryerror)); @@ -553,58 +738,75 @@ public class OverviewFragment extends Fragment { sRefreshLoop = new Runnable() { @Override public void run() { - updateGUIIfVisible(); + scheduleUpdateGUI("refreshLoop"); sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); } }; sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L); registerForContextMenu(apsModeView); - updateGUIIfVisible(); + updateGUI("onResume"); } @Subscribe public void onStatusEvent(final EventInitializationChanged ev) { - updateGUIIfVisible(); + scheduleUpdateGUI("EventInitializationChanged"); } @Subscribe public void onStatusEvent(final EventPreferenceChange ev) { - updateGUIIfVisible(); + scheduleUpdateGUI("EventPreferenceChange"); } @Subscribe public void onStatusEvent(final EventRefreshGui ev) { - updateGUIIfVisible(); + scheduleUpdateGUI("EventRefreshGui"); + } + + @Subscribe + public void onStatusEvent(final EventAutosensCalculationFinished ev) { + scheduleUpdateGUI("EventAutosensCalculationFinished"); } @Subscribe public void onStatusEvent(final EventTreatmentChange ev) { - updateGUIIfVisible(); + scheduleUpdateGUI("EventTreatmentChange"); + } + + @Subscribe + public void onStatusEvent(final EventCareportalEventChange ev) { + scheduleUpdateGUI("EventCareportalEventChange"); } @Subscribe public void onStatusEvent(final EventTempBasalChange ev) { - updateGUIIfVisible(); + scheduleUpdateGUI("EventTempBasalChange"); } @Subscribe - public void onStatusEvent(final EventNewBG ev) { - updateGUIIfVisible(); + public void onStatusEvent(final EventExtendedBolusChange ev) { + scheduleUpdateGUI("EventExtendedBolusChange"); } +// Handled by EventAutosensCalculationFinished +// @Subscribe +// public void onStatusEvent(final EventNewBG ev) { +// scheduleUpdateGUI("EventNewBG"); +// } + @Subscribe public void onStatusEvent(final EventNewOpenLoopNotification ev) { - updateGUIIfVisible(); + scheduleUpdateGUI("EventNewOpenLoopNotification"); } - @Subscribe - public void onStatusEvent(final EventNewBasalProfile ev) { - updateGUIIfVisible(); - } +// Handled by EventAutosensCalculationFinished +// @Subscribe +// public void onStatusEvent(final EventNewBasalProfile ev) { +// scheduleUpdateGUI("EventNewBasalProfile"); +// } @Subscribe - public void onStatusEvent(final EventTempTargetRangeChange ev) { - updateGUIIfVisible(); + public void onStatusEvent(final EventTempTargetChange ev) { + scheduleUpdateGUI("EventTempTargetChange"); } @Subscribe @@ -640,73 +842,97 @@ public class OverviewFragment extends Fragment { }); } - private void updateGUIIfVisible() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - updateGUI(); - } - }); + private void clearNotification() { + NotificationManager notificationManager = + (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(Constants.notificationID); } private void updatePumpStatus(String status) { - PumpInterface pump = MainApp.getConfigBuilder(); if (!status.equals("")) { pumpStatusView.setText(status); pumpStatusLayout.setVisibility(View.VISIBLE); loopStatusLayout.setVisibility(View.GONE); } else { - wizardButton.setVisibility(View.VISIBLE); - treatmentButton.setVisibility(View.VISIBLE); pumpStatusLayout.setVisibility(View.GONE); loopStatusLayout.setVisibility(View.VISIBLE); } } - @SuppressLint("SetTextI18n") - public void updateGUI() { - updateNotifications(); - BgReading actualBG = GlucoseStatus.actualBg(); - BgReading lastBG = GlucoseStatus.lastBg(); - - if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null || MainApp.getConfigBuilder().getActiveProfile().getProfile() == null) {// app not initialized yet - pumpStatusView.setText(R.string.noprofileset); - pumpStatusLayout.setVisibility(View.VISIBLE); - loopStatusLayout.setVisibility(View.GONE); - return; - } else { - pumpStatusLayout.setVisibility(View.GONE); - loopStatusLayout.setVisibility(View.VISIBLE); + public void scheduleUpdateGUI(final String from) { + class UpdateRunnable implements Runnable { + public void run() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + updateGUI(from); + scheduledUpdate = null; + } + }); + } } + // prepare task for execution in 400 msec + // cancel waiting task to prevent multiple updates + if (scheduledUpdate != null) + scheduledUpdate.cancel(false); + Runnable task = new UpdateRunnable(); + final int msec = 2000; + scheduledUpdate = worker.schedule(task, msec, TimeUnit.MILLISECONDS); + } - PumpInterface pump = MainApp.getConfigBuilder(); - - // Skip if not initialized yet - if (bgGraph == null) - return; + @SuppressLint("SetTextI18n") + public void updateGUI(String from) { + log.debug("updateGUI entered from: " + from); + Date updateGUIStart = new Date(); if (getActivity() == null) return; + if (timeView != null) { //must not exists + timeView.setText(DateUtil.timeString(new Date())); + } + if (updating != null) + updating.setVisibility(View.VISIBLE); + + if (MainApp.getConfigBuilder().getProfile() == null) {// app not initialized yet + pumpStatusView.setText(R.string.noprofileset); + pumpStatusLayout.setVisibility(View.VISIBLE); + loopStatusLayout.setVisibility(View.GONE); + if (updating != null) + updating.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(); + + PumpInterface pump = MainApp.getConfigBuilder(); + + Profile profile = MainApp.getConfigBuilder().getProfile(); + // open loop mode final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; if (Config.APS && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable) { apsModeView.setVisibility(View.VISIBLE); - apsModeView.setBackgroundResource(R.drawable.loopmodeborder); + apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopenabled)); apsModeView.setTextColor(Color.BLACK); - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) { - apsModeView.setBackgroundResource(R.drawable.loopmodesuspendedborder); + apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); } else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuspended()) { - apsModeView.setBackgroundResource(R.drawable.loopmodesuspendedborder); + apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), activeloop.minutesToEndOfSuspend())); apsModeView.setTextColor(Color.WHITE); } else if (pump.isSuspended()) { - apsModeView.setBackgroundResource(R.drawable.loopmodesuspendedborder); + apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setText(MainApp.sResources.getString(R.string.pumpsuspended)); apsModeView.setTextColor(Color.WHITE); } else if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { @@ -716,7 +942,7 @@ public class OverviewFragment extends Fragment { apsModeView.setText(MainApp.sResources.getString(R.string.openloop)); } } else { - apsModeView.setBackgroundResource(R.drawable.loopmodedisabledborder); + apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopdisabled)); apsModeView.setText(MainApp.sResources.getString(R.string.disabledloop)); apsModeView.setTextColor(Color.WHITE); } @@ -725,29 +951,28 @@ public class OverviewFragment extends Fragment { } // temp target - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); - if (Config.APS && tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) { - TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime()); - if (tempTarget != null) { - tempTargetView.setTextColor(Color.BLACK); - tempTargetView.setBackgroundResource(R.drawable.temptargetborder); - tempTargetView.setVisibility(View.VISIBLE); - tempTargetView.setText(NSProfile.toUnitsString(tempTarget.low, NSProfile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + NSProfile.toUnitsString(tempTarget.high, NSProfile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits())); - } else { - - Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL; - Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL; - if (!profile.getUnits().equals(Constants.MGDL)) { - maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL; - minBgDefault = Constants.MIN_BG_DEFAULT_MMOL; - } - tempTargetView.setTextColor(Color.WHITE); - tempTargetView.setBackgroundResource(R.drawable.temptargetborderdisabled); - tempTargetView.setText(SP.getDouble("openapsma_min_bg", minBgDefault) + " - " + SP.getDouble("openapsma_max_bg", maxBgDefault)); - tempTargetView.setVisibility(View.VISIBLE); - } + TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(new Date().getTime()); + if (tempTarget != null) { + tempTargetView.setTextColor(Color.BLACK); + tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground)); + tempTargetView.setVisibility(View.VISIBLE); + if (tempTarget.low == tempTarget.high) + tempTargetView.setText(Profile.toUnitsString(tempTarget.low, Profile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits())); + else + tempTargetView.setText(Profile.toUnitsString(tempTarget.low, Profile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + Profile.toUnitsString(tempTarget.high, Profile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits())); } else { + Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL; + Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL; + if (!profile.getUnits().equals(Constants.MGDL)) { + maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL; + minBgDefault = Constants.MIN_BG_DEFAULT_MMOL; + } + tempTargetView.setTextColor(Color.WHITE); + tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetDisabledBackground)); + tempTargetView.setText(SP.getDouble("openapsma_min_bg", minBgDefault) + " - " + SP.getDouble("openapsma_max_bg", maxBgDefault)); + tempTargetView.setVisibility(View.VISIBLE); + } + if (Config.NSCLIENT && tempTarget == null) { tempTargetView.setVisibility(View.GONE); } @@ -765,32 +990,41 @@ public class OverviewFragment extends Fragment { } // **** Calibration button **** - if (MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE) && profile != null && GlucoseStatus.actualBg() != null) { + if (MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE) && profile != null && DatabaseHelper.actualBg() != null) { calibrationButton.setVisibility(View.VISIBLE); } else { calibrationButton.setVisibility(View.GONE); } - TempBasal activeTemp = pump.getTempBasal(); - if (pump.isTempBasalInProgress()) { - cancelTempLayout.setVisibility(View.VISIBLE); - cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + ": " + activeTemp.toString()); - runningTempView.setVisibility(View.VISIBLE); - runningTempView.setText(activeTemp.toString()); + TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()); + if (activeTemp != null) { + cancelTempButton.setVisibility(View.VISIBLE); + cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + "\n" + activeTemp.toStringShort()); } else { - cancelTempLayout.setVisibility(View.GONE); - runningTempView.setVisibility(View.GONE); + cancelTempButton.setVisibility(View.GONE); } - if (pump.getPumpDescription().isTempBasalCapable) { - basalLayout.setVisibility(View.VISIBLE); - baseBasalView.setText(DecimalFormatter.to2Decimal(pump.getBaseBasalRate()) + " U/h"); - } else { - basalLayout.setVisibility(View.GONE); + String basalText = ""; + if (activeTemp != null) { + basalText = activeTemp.toStringFull() + " "; } + if (Config.NSCLIENT) + basalText += "( " + DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getProfile().getBasal()) + " U/h )"; + else if (pump.getPumpDescription().isTempBasalCapable) { + basalText += "( " + DecimalFormatter.to2Decimal(pump.getBaseBasalRate()) + " U/h )"; + } + baseBasalView.setText(basalText); - if (profile != null && profile.getActiveProfile() != null) - activeProfileView.setText(profile.getActiveProfile()); + ExtendedBolus extendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()); + String extendedBolusText = ""; + if (extendedBolus != null) { + extendedBolusText = extendedBolus.toString(); + } + if (extendedBolusView != null) // must not exists in all layouts + extendedBolusView.setText(extendedBolusText); + + activeProfileView.setText(MainApp.getConfigBuilder().getProfileName()); + activeProfileView.setBackgroundColor(Color.GRAY); activeProfileView.setOnLongClickListener(new View.OnLongClickListener() { @Override @@ -825,9 +1059,9 @@ public class OverviewFragment extends Fragment { QuickWizard.QuickWizardEntry quickWizardEntry = getPlugin().quickWizard.getActive(); if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) { quickWizardButton.setVisibility(View.VISIBLE); - String text = MainApp.sResources.getString(R.string.bolus) + ": " + quickWizardEntry.buttonText() + " " + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g"; + String text = quickWizardEntry.buttonText() + "\n" + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g"; BolusWizard wizard = new BolusWizard(); - wizard.doCalc(profile.getDefaultProfile(), quickWizardEntry.carbs(), 0d, lastBG.valueToUnits(profile.getUnits()), 0d, true, true, false, true); + wizard.doCalc(profile, quickWizardEntry.carbs(), 0d, lastBG.valueToUnits(profile.getUnits()), 0d, true, true, false, false); text += " " + DecimalFormatter.to2Decimal(wizard.calculatedTotalInsulin) + "U"; quickWizardButton.setText(text); if (wizard.calculatedTotalInsulin <= 0) @@ -835,26 +1069,51 @@ public class OverviewFragment extends Fragment { } else quickWizardButton.setVisibility(View.GONE); + // Bolus and calc button + if (pump.isInitialized() && !pump.isSuspended()) { + wizardButton.setVisibility(View.VISIBLE); + treatmentButton.setVisibility(View.VISIBLE); + } else { + wizardButton.setVisibility(View.GONE); + treatmentButton.setVisibility(View.GONE); + } + String units = profile.getUnits(); + Double lowLine = SP.getDouble("low_mark", 0d); + Double highLine = SP.getDouble("high_mark", 0d); + if (lowLine < 1) { + lowLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units); + } + if (highLine < 1) { + highLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); + } + // **** BG value **** if (lastBG != null) { + int color = MainApp.sResources.getColor(R.color.inrange); + if (lastBG.valueToUnits(units) < lowLine) + color = MainApp.sResources.getColor(R.color.low); + else if (lastBG.valueToUnits(units) > highLine) + color = MainApp.sResources.getColor(R.color.high); bgView.setText(lastBG.valueToUnitsToString(profile.getUnits())); arrowView.setText(lastBG.directionToSymbol()); + bgView.setTextColor(color); + arrowView.setTextColor(color); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); if (glucoseStatus != null) { - deltaView.setText("Δ " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units); - avgdeltaView.setText("øΔ15m: " + NSProfile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) + - " øΔ40m: " + NSProfile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units)); + deltaView.setText("Δ " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units); + 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.sResources.getString(R.string.notavailable)); avgdeltaView.setText(""); } - - BgReading.units = profile.getUnits(); - } else + } else { + if (updating != null) + updating.setVisibility(View.GONE); return; - + } Integer flag = bgView.getPaintFlags(); if (actualBG == null) { flag |= Paint.STRIKE_THRU_TEXT_FLAG; @@ -862,32 +1121,41 @@ public class OverviewFragment extends Fragment { flag &= ~Paint.STRIKE_THRU_TEXT_FLAG; bgView.setPaintFlags(flag); - Long agoMsec = new Date().getTime() - lastBG.timeIndex; + Long agoMsec = new Date().getTime() - lastBG.date; int agoMin = (int) (agoMsec / 60d / 1000d); timeAgoView.setText(String.format(MainApp.sResources.getString(R.string.minago), agoMin)); // iob - ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB(); - IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round(); - IobTotal basalIob = new IobTotal(new Date().getTime()); - if (ConfigBuilderPlugin.getActiveTempBasals() != null) { - ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB(); - basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round(); - } + MainApp.getConfigBuilder().updateTotalIOBTreatments(); + MainApp.getConfigBuilder().updateTotalIOBTempBasals(); + IobTotal bolusIob = MainApp.getConfigBuilder().getLastCalculationTreatments().round(); + IobTotal basalIob = MainApp.getConfigBuilder().getLastCalculationTempBasals().round(); String iobtext = getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; iobView.setText(iobtext); + // cob + if (cobView != null) { // view must not exists + String cobText = ""; + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(new Date().getTime()); + if (autosensData != null) + cobText = (int) autosensData.cob + " g " + String.format(MainApp.sResources.getString(R.string.minago), autosensData.minOld()); + cobView.setText(cobText); + } + boolean showPrediction = showPredictionView.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class); if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) { showPredictionView.setVisibility(View.VISIBLE); + getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.VISIBLE); } else { showPredictionView.setVisibility(View.GONE); + getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE); } // ****** GRAPH ******* + //log.debug("updateGUI checkpoint 1"); // allign to hours Calendar calendar = Calendar.getInstance(); @@ -905,205 +1173,357 @@ public class OverviewFragment extends Fragment { int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - new Date().getTime()) / (60 * 60 * 1000)); predHours = Math.min(2, predHours); predHours = Math.max(0, predHours); - hoursToFetch = (int) (6 - predHours); - toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding + hoursToFetch = rangeToDisplay - predHours; + toTime = calendar.getTimeInMillis() + 60000; // little bit more to avoid wrong rounding fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; endTime = toTime + predHours * 60 * 60 * 1000L; } else { - hoursToFetch = 6; - toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding + hoursToFetch = rangeToDisplay; + toTime = calendar.getTimeInMillis() + 600000; // little bit more to avoid wrong rounding fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; endTime = toTime; } - Double lowLine = SP.getDouble("low_mark", 0d); - Double highLine = SP.getDouble("high_mark", 0d); - - if (lowLine < 1) { - lowLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units); - } - - if (highLine < 1) { - highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); - } - LineGraphSeries basalsLineSeries = null; - BarGraphSeries basalsSeries = null; - LineGraphSeries seriesLow = null; - LineGraphSeries seriesHigh = null; - LineGraphSeries seriesNow = null; - PointsGraphSeries seriesInRage = null; - PointsGraphSeries seriesOutOfRange = null; - PointsGraphSeries predSeries = null; - PointsWithLabelGraphSeries seriesTreatments = null; - - // remove old data from graph - bgGraph.removeAllSeries(); - - // **** HIGH and LOW targets graph **** - DataPoint[] lowDataPoints = new DataPoint[]{ - new DataPoint(fromTime, lowLine), - new DataPoint(endTime, lowLine) - }; - DataPoint[] highDataPoints = new DataPoint[]{ - new DataPoint(fromTime, highLine), - new DataPoint(endTime, highLine) - }; - bgGraph.addSeries(seriesLow = new LineGraphSeries(lowDataPoints)); - seriesLow.setColor(Color.RED); - bgGraph.addSeries(seriesHigh = new LineGraphSeries(highDataPoints)); - seriesHigh.setColor(Color.RED); + LineGraphSeries absoluteBasalsLineSeries = null; + LineGraphSeries baseBasalsSeries = null; + LineGraphSeries tempBasalsSeries = null; + AreaGraphSeries areaSeries; + LineGraphSeries seriesNow, seriesNow2; // **** TEMP BASALS graph **** - class BarDataPoint extends DataPoint { - public BarDataPoint(double x, double y, boolean isTempBasal) { - super(x, y); - this.isTempBasal = isTempBasal; - } - - public boolean isTempBasal = false; - } - Double maxBasalValueFound = 0d; long now = new Date().getTime(); - if (pump.getPumpDescription().isTempBasalCapable) { - List basalArray = new ArrayList(); - List basalLineArray = new ArrayList(); + if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { + List baseBasalArray = new ArrayList<>(); + List tempBasalArray = new ArrayList<>(); + List basalLineArray = new ArrayList<>(); + List absoluteBasalLineArray = new ArrayList<>(); + double lastLineBasal = 0; + double lastAbsoluteLineBasal = 0; double lastBaseBasal = 0; - for (long time = fromTime; time < now; time += 5 * 60 * 1000L) { - TempBasal tb = MainApp.getConfigBuilder().getTempBasal(new Date(time)); - double basebasal = profile.getBasal(NSProfile.secondsFromMidnight(new Date(time))); - Double basal = 0d; - if (tb != null) - basalArray.add(new BarDataPoint(time, basal = tb.tempBasalConvertedToAbsolute(new Date(time)), true)); - else { - basalArray.add(new BarDataPoint(time, basal = basebasal, false)); + double lastTempBasal = 0; + for (long time = fromTime; time < now; time += 60 * 1000L) { + BasalData basalData = IobCobCalculatorPlugin.getBasalData(time); + double baseBasalValue = basalData.basal; + double absoluteLineValue = baseBasalValue; + double tempBasalValue = 0; + double basal = 0d; + if (basalData.isTempBasalRunning) { + absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; + if (tempBasalValue != lastTempBasal) { + tempBasalArray.add(new DataPoint(time, lastTempBasal)); + tempBasalArray.add(new DataPoint(time, basal = tempBasalValue)); + } + if (lastBaseBasal != 0d) { + baseBasalArray.add(new DataPoint(time, lastBaseBasal)); + baseBasalArray.add(new DataPoint(time, 0d)); + lastBaseBasal = 0d; + } + } else { + if (baseBasalValue != lastBaseBasal) { + baseBasalArray.add(new DataPoint(time, lastBaseBasal)); + baseBasalArray.add(new DataPoint(time, basal = baseBasalValue)); + lastBaseBasal = baseBasalValue; + } + if (lastTempBasal != 0) { + tempBasalArray.add(new DataPoint(time, lastTempBasal)); + tempBasalArray.add(new DataPoint(time, 0d)); + } } - if (basebasal != lastBaseBasal) - basalLineArray.add(new DataPoint(time, lastBaseBasal)); - basalLineArray.add(new DataPoint(time, basebasal)); - lastBaseBasal = basebasal; + + if (baseBasalValue != lastLineBasal) { + basalLineArray.add(new DataPoint(time, lastLineBasal)); + basalLineArray.add(new DataPoint(time, baseBasalValue)); + } + if (absoluteLineValue != lastAbsoluteLineBasal) { + absoluteBasalLineArray.add(new DataPoint(time, lastAbsoluteLineBasal)); + absoluteBasalLineArray.add(new DataPoint(time, basal)); + } + + lastAbsoluteLineBasal = absoluteLineValue; + lastLineBasal = baseBasalValue; + lastTempBasal = tempBasalValue; maxBasalValueFound = Math.max(maxBasalValueFound, basal); } - BarDataPoint[] basal = new BarDataPoint[basalArray.size()]; - basal = basalArray.toArray(basal); - bgGraph.addSeries(basalsSeries = new BarGraphSeries(basal)); - basalsSeries.setValueDependentColor(new ValueDependentColor() { - @Override - public int get(DataPoint data) { - BarDataPoint point = (BarDataPoint) data; - if (point.isTempBasal) return Color.BLUE; - else return Color.CYAN; - } - }); + basalLineArray.add(new DataPoint(now, lastLineBasal)); + baseBasalArray.add(new DataPoint(now, lastBaseBasal)); + tempBasalArray.add(new DataPoint(now, lastTempBasal)); + absoluteBasalLineArray.add(new DataPoint(now, lastAbsoluteLineBasal)); + + DataPoint[] baseBasal = new DataPoint[baseBasalArray.size()]; + baseBasal = baseBasalArray.toArray(baseBasal); + baseBasalsSeries = new LineGraphSeries<>(baseBasal); + baseBasalsSeries.setDrawBackground(true); + baseBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.basebasal)); + baseBasalsSeries.setThickness(0); + + DataPoint[] tempBasal = new DataPoint[tempBasalArray.size()]; + tempBasal = tempBasalArray.toArray(tempBasal); + tempBasalsSeries = new LineGraphSeries<>(tempBasal); + tempBasalsSeries.setDrawBackground(true); + tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); + tempBasalsSeries.setThickness(0); + DataPoint[] basalLine = new DataPoint[basalLineArray.size()]; basalLine = basalLineArray.toArray(basalLine); - bgGraph.addSeries(basalsLineSeries = new LineGraphSeries(basalLine)); - basalsLineSeries.setColor(Color.CYAN); - basalsLineSeries.setDrawDataPoints(false); - basalsLineSeries.setThickness(2); + basalsLineSeries = new LineGraphSeries<>(basalLine); + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{2, 4}, 0)); + paint.setColor(MainApp.sResources.getColor(R.color.basal)); + basalsLineSeries.setCustomPaint(paint); + + DataPoint[] absoluteBasalLine = new DataPoint[absoluteBasalLineArray.size()]; + absoluteBasalLine = absoluteBasalLineArray.toArray(absoluteBasalLine); + absoluteBasalsLineSeries = new LineGraphSeries<>(absoluteBasalLine); + Paint absolutePaint = new Paint(); + absolutePaint.setStyle(Paint.Style.STROKE); + absolutePaint.setStrokeWidth(4); + absolutePaint.setColor(MainApp.sResources.getColor(R.color.basal)); + absoluteBasalsLineSeries.setCustomPaint(absolutePaint); } + //log.debug("updateGUI checkpoint 2"); + + // **** IOB COB DEV graph **** + class DeviationDataPoint extends DataPoint { + public int color; + + public DeviationDataPoint(double x, double y, int color) { + super(x, y); + this.color = color; + } + } + FixedLineGraphSeries iobSeries; + FixedLineGraphSeries cobSeries; + BarGraphSeries devSeries; + Double maxIobValueFound = 0d; + Double maxCobValueFound = 0d; + Double maxDevValueFound = 0d; + + if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked()) { + //Date start = new Date(); + List iobArray = new ArrayList<>(); + List cobArray = new ArrayList<>(); + List devArray = new ArrayList<>(); + double lastIob = 0; + int lastCob = 0; + for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) { + if (showIobView.isChecked()) { + double iob = IobCobCalculatorPlugin.calulateFromTreatmentsAndTemps(time).iob; + if (Math.abs(lastIob - iob) > 0.02) { + if (Math.abs(lastIob - iob) > 0.2) + iobArray.add(new DataPoint(time, lastIob)); + iobArray.add(new DataPoint(time, iob)); + maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); + lastIob = iob; + } + } + if (showCobView.isChecked() || showDeviationsView.isChecked()) { + AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); + if (autosensData != null && showCobView.isChecked()) { + int cob = (int) autosensData.cob; + if (cob != lastCob) { + if (autosensData.carbsFromBolus > 0) + cobArray.add(new DataPoint(time, lastCob)); + cobArray.add(new DataPoint(time, cob)); + maxCobValueFound = Math.max(maxCobValueFound, cob); + lastCob = cob; + } + } + if (autosensData != null && showDeviationsView.isChecked()) { + int color = Color.BLACK; // "=" + if (autosensData.pastSensitivity.equals("C")) color = Color.GRAY; + if (autosensData.pastSensitivity.equals("+")) color = Color.GREEN; + if (autosensData.pastSensitivity.equals("-")) color = Color.RED; + devArray.add(new DeviationDataPoint(time, autosensData.deviation, color)); + maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); + } + } + } + //Profiler.log(log, "IOB processed", start); + DataPoint[] iobData = new DataPoint[iobArray.size()]; + iobData = iobArray.toArray(iobData); + iobSeries = new FixedLineGraphSeries<>(iobData); + iobSeries.setDrawBackground(true); + iobSeries.setBackgroundColor(0x80FFFFFF & MainApp.sResources.getColor(R.color.iob)); //50% + iobSeries.setColor(MainApp.sResources.getColor(R.color.iob)); + iobSeries.setThickness(3); + + + if (showIobView.isChecked() && (showCobView.isChecked() || showDeviationsView.isChecked())) { + List cobArrayRescaled = new ArrayList<>(); + List devArrayRescaled = new ArrayList<>(); + for (int ci = 0; ci < cobArray.size(); ci++) { + cobArrayRescaled.add(new DataPoint(cobArray.get(ci).getX(), cobArray.get(ci).getY() * maxIobValueFound / maxCobValueFound / 2)); + } + for (int ci = 0; ci < devArray.size(); ci++) { + devArrayRescaled.add(new DeviationDataPoint(devArray.get(ci).getX(), devArray.get(ci).getY() * maxIobValueFound / maxDevValueFound, devArray.get(ci).color)); + } + cobArray = cobArrayRescaled; + devArray = devArrayRescaled; + } + // COB + DataPoint[] cobData = new DataPoint[cobArray.size()]; + cobData = cobArray.toArray(cobData); + cobSeries = new FixedLineGraphSeries<>(cobData); + cobSeries.setDrawBackground(true); + cobSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% + cobSeries.setColor(MainApp.sResources.getColor(R.color.cob)); + cobSeries.setThickness(3); + + // DEVIATIONS + DeviationDataPoint[] devData = new DeviationDataPoint[devArray.size()]; + devData = devArray.toArray(devData); + devSeries = new BarGraphSeries<>(devData); + devSeries.setValueDependentColor(new ValueDependentColor() { + @Override + public int get(DeviationDataPoint data) { + return data.color; + } + }); + //devSeries.setBackgroundColor(0xB0FFFFFF & MainApp.sResources.getColor(R.color.cob)); //50% + //devSeries.setColor(MainApp.sResources.getColor(R.color.cob)); + //devSeries.setThickness(3); + + iobGraph.getSeries().clear(); + + if (showIobView.isChecked()) { + addSeriesWithoutInvalidate(iobSeries, iobGraph); + } + if (showCobView.isChecked() && cobData.length > 0) { + addSeriesWithoutInvalidate(cobSeries, iobGraph); + } + if (showDeviationsView.isChecked() && devData.length > 0) { + addSeriesWithoutInvalidate(devSeries, iobGraph); + } + iobGraph.setVisibility(View.VISIBLE); + } else { + iobGraph.setVisibility(View.GONE); + } + //log.debug("updateGUI checkpoint 3"); + + // remove old data from graph + bgGraph.getSecondScale().getSeries().clear(); + bgGraph.getSeries().clear(); + //log.debug("updateGUI checkpoint 4"); + + // **** Area **** + DoubleDataPoint[] areaDataPoints = new DoubleDataPoint[]{ + new DoubleDataPoint(fromTime, lowLine, highLine), + new DoubleDataPoint(endTime, lowLine, highLine) + }; + areaSeries = new AreaGraphSeries<>(areaDataPoints); + addSeriesWithoutInvalidate(areaSeries, bgGraph); + areaSeries.setColor(0); + areaSeries.setDrawBackground(true); + areaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); + // set manual x bounds to have nice steps bgGraph.getViewport().setMaxX(endTime); bgGraph.getViewport().setMinX(fromTime); bgGraph.getViewport().setXAxisBoundsManual(true); bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); bgGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + iobGraph.getViewport().setMaxX(endTime); + iobGraph.getViewport().setMinX(fromTime); + iobGraph.getViewport().setXAxisBoundsManual(true); + iobGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); + iobGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + //log.debug("updateGUI checkpoint 5"); // **** BG graph **** List bgReadingsArray = MainApp.getDbHelper().getBgreadingsDataFromTime(fromTime, true); - List inRangeArray = new ArrayList(); - List outOfRangeArray = new ArrayList(); + List bgListArray = new ArrayList<>(); - if (bgReadingsArray.size() == 0) + if (bgReadingsArray.size() == 0) { + if (updating != null) + updating.setVisibility(View.GONE); return; + } Iterator it = bgReadingsArray.iterator(); Double maxBgValue = 0d; while (it.hasNext()) { BgReading bg = it.next(); if (bg.value > maxBgValue) maxBgValue = bg.value; - if (bg.valueToUnits(units) < lowLine || bg.valueToUnits(units) > highLine) - outOfRangeArray.add(bg); - else - inRangeArray.add(bg); + bgListArray.add(bg); } - maxBgValue = NSProfile.fromMgdlToUnits(maxBgValue, units); + if (showPrediction) { + DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed; + List predArray = amaResult.getPredictions(); + bgListArray.addAll(predArray); + } + + maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; if (highLine > maxBgValue) maxBgValue = highLine; Integer numOfHorizLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); - BgReading[] inRange = new BgReading[inRangeArray.size()]; - BgReading[] outOfRange = new BgReading[outOfRangeArray.size()]; - inRange = inRangeArray.toArray(inRange); - outOfRange = outOfRangeArray.toArray(outOfRange); + DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; + bg = bgListArray.toArray(bg); - - if (inRange.length > 0) { - bgGraph.addSeries(seriesInRage = new PointsGraphSeries(inRange)); - seriesInRage.setShape(PointsGraphSeries.Shape.POINT); - seriesInRage.setSize(5); - seriesInRage.setColor(Color.GREEN); + if (bg.length > 0) { + addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(bg), bgGraph); } - if (outOfRange.length > 0) { - bgGraph.addSeries(seriesOutOfRange = new PointsGraphSeries(outOfRange)); - seriesOutOfRange.setShape(PointsGraphSeries.Shape.POINT); - seriesOutOfRange.setSize(5); - seriesOutOfRange.setColor(Color.RED); + //log.debug("updateGUI checkpoint 6"); + // Treatments + List filteredTreatments = new ArrayList<>(); + + List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); + + for (int tx = 0; tx < treatments.size(); tx++) { + DataPointWithLabelInterface t = treatments.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); + filteredTreatments.add(t); } - if (showPrediction) { - DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed; - List predArray = amaResult.getPredictions(); - BgReading[] pred = new BgReading[predArray.size()]; - pred = predArray.toArray(pred); - if (pred.length > 0) { - bgGraph.addSeries(predSeries = new PointsGraphSeries(pred)); - predSeries.setShape(PointsGraphSeries.Shape.POINT); - predSeries.setSize(4); - predSeries.setColor(Color.MAGENTA); + //log.debug("updateGUI checkpoint 7"); + // ProfileSwitch + List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); + + for (int tx = 0; tx < profileSwitches.size(); tx++) { + DataPointWithLabelInterface t = profileSwitches.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + filteredTreatments.add(t); + } + + //log.debug("updateGUI checkpoint 8"); + // Extended bolus + if (!pump.isFakingTempsByExtendedBoluses()) { + List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); + + for (int tx = 0; tx < extendedBoluses.size(); tx++) { + DataPointWithLabelInterface t = extendedBoluses.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + if (t.getDuration() == 0) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); + filteredTreatments.add(t); } } - // **** NOW line **** - DataPoint[] nowPoints = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxBgValue) - }; - bgGraph.addSeries(seriesNow = new LineGraphSeries(nowPoints)); - seriesNow.setColor(Color.GREEN); - seriesNow.setDrawDataPoints(false); - //seriesNow.setThickness(1); - // custom paint to make a dotted line - Paint paint = new Paint(); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(2); - paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); - paint.setColor(Color.WHITE); - seriesNow.setCustomPaint(paint); + //log.debug("updateGUI checkpoint 9"); + // Careportal + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); - - // Treatments - List treatments = MainApp.getConfigBuilder().getActiveTreatments().getTreatments(); - List filteredTreatments = new ArrayList(); - - for (int tx = 0; tx < treatments.size(); tx++) { - Treatment t = treatments.get(tx); - if (t.getTimeIndex() < fromTime || t.getTimeIndex() > now) continue; - t.setYValue(bgReadingsArray); + for (int tx = 0; tx < careportalEvents.size(); tx++) { + DataPointWithLabelInterface t = careportalEvents.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); filteredTreatments.add(t); } - Treatment[] treatmentsArray = new Treatment[filteredTreatments.size()]; + + DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; treatmentsArray = filteredTreatments.toArray(treatmentsArray); if (treatmentsArray.length > 0) { - bgGraph.addSeries(seriesTreatments = new PointsWithLabelGraphSeries(treatmentsArray)); - seriesTreatments.setShape(PointsWithLabelGraphSeries.Shape.TRIANGLE); - seriesTreatments.setSize(10); - seriesTreatments.setColor(Color.CYAN); + addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(treatmentsArray), bgGraph); } + //log.debug("updateGUI checkpoint 10"); // set manual y bounds to have nice steps bgGraph.getViewport().setMaxY(maxBgValue); @@ -1112,17 +1532,75 @@ public class OverviewFragment extends Fragment { bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfHorizLines); // set second scale - if (pump.getPumpDescription().isTempBasalCapable) { - bgGraph.getSecondScale().addSeries(basalsSeries); - bgGraph.getSecondScale().addSeries(basalsLineSeries); + if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { bgGraph.getSecondScale().setMinY(0); bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); - bgGraph.getGridLabelRenderer().setVerticalLabelsSecondScaleColor(ContextCompat.getColor(MainApp.instance(), R.color.background_material_dark)); // same color as backround = hide + bgGraph.getSecondScale().addSeries(baseBasalsSeries); + bgGraph.getSecondScale().addSeries(tempBasalsSeries); + bgGraph.getSecondScale().addSeries(basalsLineSeries); + bgGraph.getSecondScale().addSeries(absoluteBasalsLineSeries); } + bgGraph.getSecondScale().setLabelFormatter(new LabelFormatter() { + @Override + public String formatLabel(double value, boolean isValueX) { + return ""; + } - //updatePumpStatus(null); + @Override + public void setViewport(Viewport viewport) { + + } + }); + + //log.debug("updateGUI checkpoint 11"); + // **** NOW line **** + DataPoint[] nowPoints = new DataPoint[]{ + new DataPoint(now, 0), + new DataPoint(now, maxBgValue) + }; + addSeriesWithoutInvalidate(seriesNow = new LineGraphSeries<>(nowPoints), bgGraph); + seriesNow.setDrawDataPoints(false); + DataPoint[] nowPoints2 = new DataPoint[]{ + new DataPoint(now, 0), + new DataPoint(now, maxIobValueFound) + }; + addSeriesWithoutInvalidate(seriesNow2 = new LineGraphSeries<>(nowPoints2), iobGraph); + seriesNow2.setDrawDataPoints(false); + //seriesNow.setThickness(1); + // custom paint to make a dotted line + Paint paint = new Paint(); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(2); + paint.setPathEffect(new DashPathEffect(new float[]{10, 20}, 0)); + paint.setColor(Color.WHITE); + seriesNow.setCustomPaint(paint); + seriesNow2.setCustomPaint(paint); + bgGraph.onDataChanged(false, false); + iobGraph.onDataChanged(false, false); + + if (updating != null) + updating.setVisibility(View.GONE); + Profiler.log(log, from, updateGUIStart); } + public double getNearestBg(long date, List bgReadingsArray) { + double bg = 0; + Profile profile = MainApp.getConfigBuilder().getProfile(); + for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { + BgReading reading = bgReadingsArray.get(r); + if (reading.date > date) continue; + bg = Profile.fromMgdlToUnits(reading.value, profile.getUnits()); + break; + } + return bg; + } + + void addSeriesWithoutInvalidate(Series s, GraphView graph) { + s.onGraphViewAttached(graph); + graph.getSeries().add(s); + } + + //Notifications public static class RecyclerViewAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewPlugin.java index a8f0083afc..b513d68dac 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 @@ -70,6 +70,16 @@ public class OverviewPlugin implements PluginBase { return false; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return false; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { // Always enabled diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/QuickWizard.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/QuickWizard.java index 4f3e2a255c..63ad14ab6b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/QuickWizard.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/QuickWizard.java @@ -10,7 +10,7 @@ import org.json.JSONObject; import java.util.Date; import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.DateUtil; /** @@ -47,7 +47,7 @@ public class QuickWizard { } public Boolean isActive() { - return NSProfile.secondsFromMidnight() >= validFrom() && NSProfile.secondsFromMidnight() <= validTo(); + return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo(); } public String buttonText() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/AreaGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/AreaGraphSeries.java new file mode 100644 index 0000000000..08da836210 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/AreaGraphSeries.java @@ -0,0 +1,456 @@ +/** + * GraphView + * Copyright (C) 2014 Jonas Gehring + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * with the "Linking Exception", which can be found at the license.txt + * file in this program. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * with the "Linking Exception" along with this program; if not, + * write to the author Jonas Gehring . + */ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.series.BaseSeries; +import com.jjoe64.graphview.series.DataPointInterface; + +import java.util.Iterator; + +/** + * Series to plot the data as line. + * The line can be styled with many options. + * + * @author jjoe64 + */ +public class AreaGraphSeries extends BaseSeries { + /** + * wrapped styles regarding the line + */ + private final class Styles { + /** + * the thickness of the line. + * This option will be ignored if you are + * using a custom paint via {@link #setCustomPaint(android.graphics.Paint)} + */ + private int thickness = 5; + + /** + * flag whether the area under the line to the bottom + * of the viewport will be filled with a + * specific background color. + * + * @see #backgroundColor + */ + private boolean drawBackground = false; + + /** + * flag whether the data points are highlighted as + * a visible point. + * + * @see #dataPointsRadius + */ + private boolean drawDataPoints = false; + + /** + * the radius for the data points. + * + * @see #drawDataPoints + */ + private float dataPointsRadius = 10f; + + /** + * the background color for the filling under + * the line. + * + * @see #drawBackground + */ + private int backgroundColor = Color.argb(100, 172, 218, 255); + } + + /** + * wrapped styles + */ + private Styles mStyles; + + /** + * internal paint object + */ + private Paint mPaint; + + /** + * paint for the background + */ + private Paint mPaintBackground; + + /** + * path for the background filling + */ + private Path mPathBackground; + + /** + * path to the line + */ + private Path mPath; + private Path mSecondPath; + + /** + * custom paint that can be used. + * this will ignore the thickness and color styles. + */ + private Paint mCustomPaint; + + /** + * creates a series without data + */ + public AreaGraphSeries() { + init(); + } + + /** + * creates a series with data + * + * @param data data points + */ + public AreaGraphSeries(E[] data) { + super(data); + init(); + } + + /** + * do the initialization + * creates internal objects + */ + protected void init() { + mStyles = new Styles(); + mPaint = new Paint(); + mPaint.setStrokeCap(Paint.Cap.ROUND); + mPaint.setStyle(Paint.Style.STROKE); + mPaintBackground = new Paint(); + + mPathBackground = new Path(); + mPath = new Path(); + mSecondPath = new Path(); + } + + /** + * plots the series + * draws the line and the background + * + * @param graphView graphview + * @param canvas canvas + * @param isSecondScale flag if it is the second scale + */ + @Override + public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) { + resetDataPoints(); + + // get data + double maxX = graphView.getViewport().getMaxX(false); + double minX = graphView.getViewport().getMinX(false); + + double maxY; + double minY; + if (isSecondScale) { + maxY = graphView.getSecondScale().getMaxY(); + minY = graphView.getSecondScale().getMinY(); + } else { + maxY = graphView.getViewport().getMaxY(false); + minY = graphView.getViewport().getMinY(false); + } + + Iterator values = getValues(minX, maxX); + + // draw background + double lastEndY1 = 0; + double lastEndY2 = 0; + double lastEndX = 0; + + // draw data + mPaint.setStrokeWidth(mStyles.thickness); + mPaint.setColor(getColor()); + mPaintBackground.setColor(mStyles.backgroundColor); + + Paint paint; + if (mCustomPaint != null) { + paint = mCustomPaint; + } else { + paint = mPaint; + } + + if (mStyles.drawBackground) { + mPathBackground.reset(); + } + + double diffY = maxY - minY; + double diffX = maxX - minX; + + float graphHeight = graphView.getGraphContentHeight(); + float graphWidth = graphView.getGraphContentWidth(); + float graphLeft = graphView.getGraphContentLeft(); + float graphTop = graphView.getGraphContentTop(); + + lastEndY1 = 0; + lastEndY2 = 0; + lastEndX = 0; + double lastUsedEndX = 0; + float firstX = 0; + int i=0; + while (values.hasNext()) { + E value = values.next(); + + double valY1 = value.getY() - minY; + double ratY1 = valY1 / diffY; + double y1 = graphHeight * ratY1; + + double valY2 = value.getY2() - minY; + double ratY2 = valY2 / diffY; + double y2 = graphHeight * ratY2; + + double valX = value.getX() - minX; + double ratX = valX / diffX; + double x = graphWidth * ratX; + + double orgX = x; + double orgY1 = y1; + double orgY2 = y2; + + if (i > 0) { + // overdraw + if (x > graphWidth) { // end right + double b = ((graphWidth - lastEndX) * (y1 - lastEndY1)/(x - lastEndX)); + y1 = lastEndY1+b; + x = graphWidth; + } + if (x > graphWidth) { // end right + double b = ((graphWidth - lastEndX) * (y2 - lastEndY2)/(x - lastEndX)); + y2 = lastEndY2+b; + x = graphWidth; + } + if (y1 < 0) { // end bottom + double b = ((0 - lastEndY1) * (x - lastEndX)/(y1 - lastEndY1)); + x = lastEndX+b; + y1 = 0; + } + if (y2 < 0) { // end bottom + double b = ((0 - lastEndY2) * (x - lastEndX)/(y2 - lastEndY2)); + x = lastEndX+b; + y2 = 0; + } + if (y1 > graphHeight) { // end top + double b = ((graphHeight - lastEndY1) * (x - lastEndX)/(y1 - lastEndY1)); + x = lastEndX+b; + y1 = graphHeight; + } + if (y2 > graphHeight) { // end top + double b = ((graphHeight - lastEndY2) * (x - lastEndX)/(y2 - lastEndY2)); + x = lastEndX+b; + y2 = graphHeight; + } + if (lastEndY1 < 0) { // start bottom + double b = ((0 - y1) * (x - lastEndX)/(lastEndY1 - y1)); + lastEndX = x-b; + lastEndY1 = 0; + } + if (lastEndY2 < 0) { // start bottom + double b = ((0 - y2) * (x - lastEndX)/(lastEndY2 - y2)); + lastEndX = x-b; + lastEndY2 = 0; + } + if (lastEndX < 0) { // start left + double b = ((0 - x) * (y1 - lastEndY1)/(lastEndX - x)); + lastEndY1 = y1-b; + lastEndX = 0; + } + if (lastEndX < 0) { // start left + double b = ((0 - x) * (y2 - lastEndY2)/(lastEndX - x)); + lastEndY2 = y2-b; + lastEndX = 0; + } + if (lastEndY1 > graphHeight) { // start top + double b = ((graphHeight - y1) * (x - lastEndX)/(lastEndY1 - y1)); + lastEndX = x-b; + lastEndY1 = graphHeight; + } + if (lastEndY2 > graphHeight) { // start top + double b = ((graphHeight - y2) * (x - lastEndX)/(lastEndY2 - y2)); + lastEndX = x-b; + lastEndY2 = graphHeight; + } + + float startX = (float) lastEndX + (graphLeft + 1); + float startY1 = (float) (graphTop - lastEndY1) + graphHeight; + float startY2 = (float) (graphTop - lastEndY2) + graphHeight; + float endX = (float) x + (graphLeft + 1); + float endY1 = (float) (graphTop - y1) + graphHeight; + float endY2 = (float) (graphTop - y2) + graphHeight; + + // draw data point + if (mStyles.drawDataPoints) { + //fix: last value was not drawn. Draw here now the end values + canvas.drawCircle(endX, endY1, mStyles.dataPointsRadius, mPaint); + canvas.drawCircle(endX, endY2, mStyles.dataPointsRadius, mPaint); + } + registerDataPoint(endX, endY1, value); + registerDataPoint(endX, endY2, value); + + mPath.reset(); + mSecondPath.reset(); + mPath.moveTo(startX, startY1); + mSecondPath.moveTo(startX, startY2); + mPath.lineTo(endX, endY1); + mSecondPath.lineTo(endX, endY2); + canvas.drawPath(mPath, paint); + canvas.drawPath(mSecondPath, paint); + if (mStyles.drawBackground) { + canvas.drawRect((float)startX, (float)startY2, endX, endY1, mPaintBackground); + } + } else if (mStyles.drawDataPoints) { + //fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above) + //float first_X = (float) x + (graphLeft + 1); + //float first_Y = (float) (graphTop - y) + graphHeight; + //TODO canvas.drawCircle(first_X, first_Y, dataPointsRadius, mPaint); + } + lastEndY1 = orgY1; + lastEndY2 = orgY2; + lastEndX = orgX; + i++; + } + +/* + if (mStyles.drawBackground) { + // end / close path + mPathBackground.lineTo((float) lastUsedEndX, graphHeight + graphTop); + mPathBackground.lineTo(firstX, graphHeight + graphTop); + mPathBackground.close(); + canvas.drawPath(mPathBackground, mPaintBackground); + } +*/ + + } + + /** + * the thickness of the line. + * This option will be ignored if you are + * using a custom paint via {@link #setCustomPaint(android.graphics.Paint)} + * + * @return the thickness of the line + */ + public int getThickness() { + return mStyles.thickness; + } + + /** + * the thickness of the line. + * This option will be ignored if you are + * using a custom paint via {@link #setCustomPaint(android.graphics.Paint)} + * + * @param thickness thickness of the line + */ + public void setThickness(int thickness) { + mStyles.thickness = thickness; + } + + /** + * flag whether the area under the line to the bottom + * of the viewport will be filled with a + * specific background color. + * + * @return whether the background will be drawn + * @see #getBackgroundColor() + */ + public boolean isDrawBackground() { + return mStyles.drawBackground; + } + + /** + * flag whether the area under the line to the bottom + * of the viewport will be filled with a + * specific background color. + * + * @param drawBackground whether the background will be drawn + * @see #setBackgroundColor(int) + */ + public void setDrawBackground(boolean drawBackground) { + mStyles.drawBackground = drawBackground; + } + + /** + * flag whether the data points are highlighted as + * a visible point. + * + * @return flag whether the data points are highlighted + * @see #setDataPointsRadius(float) + */ + public boolean isDrawDataPoints() { + return mStyles.drawDataPoints; + } + + /** + * flag whether the data points are highlighted as + * a visible point. + * + * @param drawDataPoints flag whether the data points are highlighted + * @see #setDataPointsRadius(float) + */ + public void setDrawDataPoints(boolean drawDataPoints) { + mStyles.drawDataPoints = drawDataPoints; + } + + /** + * @return the radius for the data points. + * @see #setDrawDataPoints(boolean) + */ + public float getDataPointsRadius() { + return mStyles.dataPointsRadius; + } + + /** + * @param dataPointsRadius the radius for the data points. + * @see #setDrawDataPoints(boolean) + */ + public void setDataPointsRadius(float dataPointsRadius) { + mStyles.dataPointsRadius = dataPointsRadius; + } + + /** + * @return the background color for the filling under + * the line. + * @see #setDrawBackground(boolean) + */ + public int getBackgroundColor() { + return mStyles.backgroundColor; + } + + /** + * @param backgroundColor the background color for the filling under + * the line. + * @see #setDrawBackground(boolean) + */ + public void setBackgroundColor(int backgroundColor) { + mStyles.backgroundColor = backgroundColor; + } + + /** + * custom paint that can be used. + * this will ignore the thickness and color styles. + * + * @param customPaint the custom paint to be used for rendering the line + */ + public void setCustomPaint(Paint customPaint) { + this.mCustomPaint = customPaint; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DataPointWithLabelInterface.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DataPointWithLabelInterface.java index 1c02eb66d7..20d478692a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DataPointWithLabelInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DataPointWithLabelInterface.java @@ -38,15 +38,21 @@ public interface DataPointWithLabelInterface extends DataPointInterface{ /** * @return the x value */ - public double getX(); + double getX(); /** * @return the y value */ - public double getY(); + double getY(); + void setY(double y); /** * @return the label value */ - public String getLabel(); + String getLabel(); + + long getDuration(); + PointsWithLabelGraphSeries.Shape getShape(); + float getSize(); + int getColor(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DoubleDataPoint.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DoubleDataPoint.java new file mode 100644 index 0000000000..5ac5224c65 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/DoubleDataPoint.java @@ -0,0 +1,41 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +import com.jjoe64.graphview.series.DataPointInterface; + +import java.io.Serializable; +import java.util.Date; + +/** + * Created by mike on 21.04.2017. + */ + +public class DoubleDataPoint implements DataPointInterface, Serializable { + private static final long serialVersionUID=1428267322645L; + + private double x; + private double y1; + private double y2; + + public DoubleDataPoint(double x, double y1, double y2) { + this.x=x; + this.y1=y1; + this.y2=y2; + } + + public double getX() { + return x; + } + + @Override + public double getY() { + return y1; + } + + public double getY1() { + return y1; + } + + public double getY2() { + return y2; + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/FixedLineGraphSeries.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/FixedLineGraphSeries.java new file mode 100644 index 0000000000..922ac3a85b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/FixedLineGraphSeries.java @@ -0,0 +1,405 @@ +package info.nightscout.androidaps.plugins.Overview.graphExtensions; + +/** + * Created by mike on 24.04.2017. + */ + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.series.BaseSeries; +import com.jjoe64.graphview.series.DataPointInterface; + +import java.util.Iterator; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; + +import com.jjoe64.graphview.GraphView; + +import java.util.Iterator; + +/** + * Series to plot the data as line. + * The line can be styled with many options. + * + * @author jjoe64 + */ +public class FixedLineGraphSeries extends BaseSeries { + /** + * wrapped styles regarding the line + */ + private final class Styles { + /** + * the thickness of the line. + * This option will be ignored if you are + * using a custom paint via {@link #setCustomPaint(android.graphics.Paint)} + */ + private int thickness = 5; + + /** + * flag whether the area under the line to the bottom + * of the viewport will be filled with a + * specific background color. + * + * @see #backgroundColor + */ + private boolean drawBackground = false; + + /** + * flag whether the data points are highlighted as + * a visible point. + * + * @see #dataPointsRadius + */ + private boolean drawDataPoints = false; + + /** + * the radius for the data points. + * + * @see #drawDataPoints + */ + private float dataPointsRadius = 10f; + + /** + * the background color for the filling under + * the line. + * + * @see #drawBackground + */ + private int backgroundColor = Color.argb(100, 172, 218, 255); + } + + /** + * wrapped styles + */ + private Styles mStyles; + + /** + * internal paint object + */ + private Paint mPaint; + + /** + * paint for the background + */ + private Paint mPaintBackground; + + /** + * path for the background filling + */ + private Path mPathBackground; + + /** + * path to the line + */ + private Path mPath; + + /** + * custom paint that can be used. + * this will ignore the thickness and color styles. + */ + private Paint mCustomPaint; + + /** + * creates a series without data + */ + public FixedLineGraphSeries() { + init(); + } + + /** + * creates a series with data + * + * @param data data points + */ + public FixedLineGraphSeries(E[] data) { + super(data); + init(); + } + + /** + * do the initialization + * creates internal objects + */ + protected void init() { + mStyles = new Styles(); + mPaint = new Paint(); + mPaint.setStrokeCap(Paint.Cap.ROUND); + mPaint.setStyle(Paint.Style.STROKE); + mPaintBackground = new Paint(); + + mPathBackground = new Path(); + mPath = new Path(); + } + + /** + * plots the series + * draws the line and the background + * + * @param graphView graphview + * @param canvas canvas + * @param isSecondScale flag if it is the second scale + */ + @Override + public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) { + resetDataPoints(); + + // get data + double maxX = graphView.getViewport().getMaxX(false); + double minX = graphView.getViewport().getMinX(false); + + double maxY; + double minY; + if (isSecondScale) { + maxY = graphView.getSecondScale().getMaxY(); + minY = graphView.getSecondScale().getMinY(); + } else { + maxY = graphView.getViewport().getMaxY(false); + minY = graphView.getViewport().getMinY(false); + } + + Iterator values = getValues(minX, maxX); + + // draw background + double lastEndY = 0; + double lastEndX = 0; + + // draw data + mPaint.setStrokeWidth(mStyles.thickness); + mPaint.setColor(getColor()); + mPaintBackground.setColor(mStyles.backgroundColor); + + Paint paint; + if (mCustomPaint != null) { + paint = mCustomPaint; + } else { + paint = mPaint; + } + + if (mStyles.drawBackground) { + mPathBackground.reset(); + } + + double diffY = maxY - minY; + double diffX = maxX - minX; + + float graphHeight = graphView.getGraphContentHeight(); + float graphWidth = graphView.getGraphContentWidth(); + float graphLeft = graphView.getGraphContentLeft(); + float graphTop = graphView.getGraphContentTop(); + + lastEndY = 0; + lastEndX = 0; + double lastUsedEndX = 0; + float firstX = 0; + int i=0; + while (values.hasNext()) { + E value = values.next(); + + double valY = value.getY() - minY; + double ratY = valY / diffY; + double y = graphHeight * ratY; + + double valX = value.getX() - minX; + double ratX = valX / diffX; + double x = graphWidth * ratX; + + double orgX = x; + double orgY = y; + + if (i > 0) { + // overdraw + if (x > graphWidth) { // end right + double b = ((graphWidth - lastEndX) * (y - lastEndY)/(x - lastEndX)); + y = lastEndY+b; + x = graphWidth; + } + if (y < 0) { // end bottom + double b = ((0 - lastEndY) * (x - lastEndX)/(y - lastEndY)); + x = lastEndX+b; + y = 0; + } + if (y > graphHeight) { // end top + double b = ((graphHeight - lastEndY) * (x - lastEndX)/(y - lastEndY)); + x = lastEndX+b; + y = graphHeight; + } + if (lastEndY < 0) { // start bottom + double b = ((0 - y) * (x - lastEndX)/(lastEndY - y)); + lastEndX = x-b; + lastEndY = 0; + } + if (lastEndX < 0) { // start left + double b = ((0 - x) * (y - lastEndY)/(lastEndX - x)); + lastEndY = y-b; + lastEndX = 0; + } + if (lastEndY > graphHeight) { // start top + double b = ((graphHeight - y) * (x - lastEndX)/(lastEndY - y)); + lastEndX = x-b; + lastEndY = graphHeight; + } + + float startX = (float) lastEndX + (graphLeft + 1); + float startY = (float) (graphTop - lastEndY) + graphHeight; + float endX = (float) x + (graphLeft + 1); + float endY = (float) (graphTop - y) + graphHeight; + + // draw data point + if (mStyles.drawDataPoints) { + //fix: last value was not drawn. Draw here now the end values + canvas.drawCircle(endX, endY, mStyles.dataPointsRadius, mPaint); + } + registerDataPoint(endX, endY, value); + + mPath.reset(); + mPath.moveTo(startX, startY); + mPath.lineTo(endX, endY); + canvas.drawPath(mPath, paint); + if (mStyles.drawBackground) { + if (i==1) { + firstX = startX; + mPathBackground.moveTo(startX, startY); + } + mPathBackground.lineTo(endX, endY); + } + lastUsedEndX = endX; + } else if (mStyles.drawDataPoints) { + //fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above) + float first_X = (float) x + (graphLeft + 1); + float first_Y = (float) (graphTop - y) + graphHeight; + //TODO canvas.drawCircle(first_X, first_Y, dataPointsRadius, mPaint); + } + lastEndY = orgY; + lastEndX = orgX; + i++; + } + + if (mStyles.drawBackground) { + // end / close path + mPathBackground.lineTo((float) lastUsedEndX, (float) (graphTop - (-minY / diffY * graphHeight)) + graphHeight); + mPathBackground.lineTo(firstX, (float) (graphTop - (-minY / diffY * graphHeight)) + graphHeight); + mPathBackground.close(); + canvas.drawPath(mPathBackground, mPaintBackground); + } + + } + + /** + * the thickness of the line. + * This option will be ignored if you are + * using a custom paint via {@link #setCustomPaint(android.graphics.Paint)} + * + * @return the thickness of the line + */ + public int getThickness() { + return mStyles.thickness; + } + + /** + * the thickness of the line. + * This option will be ignored if you are + * using a custom paint via {@link #setCustomPaint(android.graphics.Paint)} + * + * @param thickness thickness of the line + */ + public void setThickness(int thickness) { + mStyles.thickness = thickness; + } + + /** + * flag whether the area under the line to the bottom + * of the viewport will be filled with a + * specific background color. + * + * @return whether the background will be drawn + * @see #getBackgroundColor() + */ + public boolean isDrawBackground() { + return mStyles.drawBackground; + } + + /** + * flag whether the area under the line to the bottom + * of the viewport will be filled with a + * specific background color. + * + * @param drawBackground whether the background will be drawn + * @see #setBackgroundColor(int) + */ + public void setDrawBackground(boolean drawBackground) { + mStyles.drawBackground = drawBackground; + } + + /** + * flag whether the data points are highlighted as + * a visible point. + * + * @return flag whether the data points are highlighted + * @see #setDataPointsRadius(float) + */ + public boolean isDrawDataPoints() { + return mStyles.drawDataPoints; + } + + /** + * flag whether the data points are highlighted as + * a visible point. + * + * @param drawDataPoints flag whether the data points are highlighted + * @see #setDataPointsRadius(float) + */ + public void setDrawDataPoints(boolean drawDataPoints) { + mStyles.drawDataPoints = drawDataPoints; + } + + /** + * @return the radius for the data points. + * @see #setDrawDataPoints(boolean) + */ + public float getDataPointsRadius() { + return mStyles.dataPointsRadius; + } + + /** + * @param dataPointsRadius the radius for the data points. + * @see #setDrawDataPoints(boolean) + */ + public void setDataPointsRadius(float dataPointsRadius) { + mStyles.dataPointsRadius = dataPointsRadius; + } + + /** + * @return the background color for the filling under + * the line. + * @see #setDrawBackground(boolean) + */ + public int getBackgroundColor() { + return mStyles.backgroundColor; + } + + /** + * @param backgroundColor the background color for the filling under + * the line. + * @see #setDrawBackground(boolean) + */ + public void setBackgroundColor(int backgroundColor) { + mStyles.backgroundColor = backgroundColor; + } + + /** + * custom paint that can be used. + * this will ignore the thickness and color styles. + * + * @param customPaint the custom paint to be used for rendering the line + */ + public void setCustomPaint(Paint customPaint) { + this.mCustomPaint = customPaint; + } +} 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 7671813090..970aaa8385 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 @@ -28,6 +28,8 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.Typeface; import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.series.BaseSeries; @@ -42,26 +44,6 @@ import java.util.Iterator; * @author jjoe64 */ public class PointsWithLabelGraphSeries extends BaseSeries { - /** - * interface to implement a custom - * drawing for the data points. - */ - public static interface CustomShape { - /** - * called when drawing a single data point. - * use the x and y coordinates to render your - * drawing at this point. - * - * @param canvas canvas to draw on - * @param paint internal paint object. this has the correct color. - * But you can use your own paint. - * @param x x-coordinate the point has to be drawn to - * @param y y-coordinate the point has to be drawn to - * @param dataPoint the related data point - */ - void draw(Canvas canvas, Paint paint, float x, float y, DataPointWithLabelInterface dataPoint); - } - /** * choose a predefined shape to render for * each data point. @@ -77,45 +59,24 @@ public class PointsWithLabelGraphSeries e * draws a triangle */ TRIANGLE, - - /** - * draws a rectangle - */ - RECTANGLE + RECTANGLE, + BOLUS, + EXTENDEDBOLUS, + PROFILE, + MBG, + BGCHECK, + ANNOUNCEMENT, + OPENAPSOFFLINE, + EXERCISE, + GENERAL, + GENERALWITHDURATION } - /** - * wrapped styles for this series - */ - private final class Styles { - /** - * this is used for the size of the shape that - * will be drawn. - * This is useless if you are using a custom shape. - */ - float size; - - /** - * the shape that will be drawn for each point. - */ - Shape shape; - } - - /** - * wrapped styles - */ - private Styles mStyles; - /** * internal paint object */ private Paint mPaint; - /** - * handler to use a custom drawing - */ - private CustomShape mCustomShape; - /** * creates the series without data */ @@ -138,11 +99,8 @@ public class PointsWithLabelGraphSeries e * set the defaults */ protected void init() { - mStyles = new Styles(); - mStyles.size = 20f; mPaint = new Paint(); mPaint.setStrokeCap(Paint.Cap.ROUND); - setShape(Shape.POINT); } /** @@ -177,7 +135,6 @@ public class PointsWithLabelGraphSeries e double lastEndX = 0; // draw data - mPaint.setColor(getColor()); double diffY = maxY - minY; double diffX = maxX - minX; @@ -194,6 +151,8 @@ public class PointsWithLabelGraphSeries e while (values.hasNext()) { E value = values.next(); + mPaint.setColor(value.getColor()); + double valY = value.getY() - minY; double ratY = valY / diffY; double y = graphHeight * ratY; @@ -225,32 +184,136 @@ public class PointsWithLabelGraphSeries e float endY = (float) (graphTop - y) + graphHeight; registerDataPoint(endX, endY, value); + float xpluslength = 0; + if (value.getDuration() > 0) { + xpluslength = endX + Math.min((float) (value.getDuration() * graphWidth / diffX), graphLeft + graphWidth); + } + // draw data point if (!overdraw) { - if (mCustomShape != null) { - mCustomShape.draw(canvas, mPaint, endX, endY, value); - } else if (mStyles.shape == Shape.POINT) { - canvas.drawCircle(endX, endY, mStyles.size, mPaint); - } else if (mStyles.shape == Shape.RECTANGLE) { - canvas.drawRect(endX-mStyles.size, endY-mStyles.size, endX+mStyles.size, endY+mStyles.size, mPaint); - } else if (mStyles.shape == Shape.TRIANGLE) { + if (value.getShape() == Shape.POINT) { + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + } else if (value.getShape() == Shape.RECTANGLE) { + canvas.drawRect(endX-value.getSize(), endY-value.getSize(), endX+value.getSize(), endY+value.getSize(), mPaint); + } else if (value.getShape() == Shape.TRIANGLE) { + mPaint.setStrokeWidth(0); Point[] points = new Point[3]; - points[0] = new Point((int)endX, (int)(endY-getSize())); - points[1] = new Point((int)(endX+getSize()), (int)(endY+getSize()*0.67)); - points[2] = new Point((int)(endX-getSize()), (int)(endY+getSize()*0.67)); + points[0] = new Point((int)endX, (int)(endY-value.getSize())); + points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); + points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67)); drawArrows(points, canvas, mPaint); + } else if (value.getShape() == Shape.BOLUS) { + mPaint.setStrokeWidth(0); + Point[] points = new Point[3]; + points[0] = new Point((int)endX, (int)(endY-value.getSize())); + points[1] = new Point((int)(endX+value.getSize()), (int)(endY+value.getSize()*0.67)); + points[2] = new Point((int)(endX-value.getSize()), (int)(endY+value.getSize()*0.67)); + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + drawArrows(points, canvas, mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.EXTENDEDBOLUS) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + Rect bounds = new Rect((int)endX, (int)endY + 3, (int) (xpluslength), (int) endY + 8); + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + canvas.drawRect(bounds, mPaint); + mPaint.setTextSize((int) (value.getSize() * 2.5)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + mPaint.setFakeBoldText(true); + canvas.drawText(value.getLabel(), endX, endY, mPaint); + } + } else if (value.getShape() == Shape.PROFILE) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setTextSize((int) (value.getSize() * 3)); + 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); + float px = endX + bounds.height() / 2; + float py = (float) (graphHeight * ratY + bounds.width() + 10); + canvas.save(); + canvas.rotate(-90, px, py); + canvas.drawText(value.getLabel(), px, py, mPaint); + canvas.drawRect(px - 3, bounds.top + py - 3, bounds.right + px + 3, bounds.bottom + py + 3, mPaint); + canvas.restore(); + } + } else if (value.getShape() == Shape.MBG) { + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(5); + float w = mPaint.getStrokeWidth(); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + } else if (value.getShape() == Shape.BGCHECK) { + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.ANNOUNCEMENT) { + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.GENERAL) { + mPaint.setStyle(Paint.Style.FILL_AND_STROKE); + mPaint.setStrokeWidth(0); + canvas.drawCircle(endX, endY, value.getSize(), mPaint); + if (value.getLabel() != null) { + drawLabel45(endX, endY, value, canvas); + } + } else if (value.getShape() == Shape.EXERCISE) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setStrokeWidth(0); + mPaint.setTextSize((int) (value.getSize() * 3)); + 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); + float px = endX; + float py = graphTop + 20; + 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); + } + } else if (value.getShape() == Shape.OPENAPSOFFLINE) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setStrokeWidth(0); + mPaint.setTextSize((int) (value.getSize() * 3)); + 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); + float px = endX; + float py = graphTop + 50; + 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); + } + } else if (value.getShape() == Shape.GENERALWITHDURATION) { + mPaint.setStrokeWidth(0); + if (value.getLabel() != null) { + mPaint.setStrokeWidth(0); + mPaint.setTextSize((int) (value.getSize() * 3)); + 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); + float px = endX; + float py = graphTop + 80; + 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); + } } // set values above point - if (value.getLabel() != null) { - float px = endX; - float py = endY - (int) (getSize()); - canvas.save(); - canvas.rotate(-45, px, py); - mPaint.setTextSize((int) (getSize() * 2.5)); - mPaint.setFakeBoldText(true); - canvas.drawText(value.getLabel(), px + getSize(), py, mPaint); - canvas.restore(); - } } i++; @@ -276,57 +339,39 @@ public class PointsWithLabelGraphSeries e points[6] = point[0].x; points[7] = point[0].y; + canvas.save(); canvas.drawVertices(Canvas.VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint); Path path = new Path(); path.moveTo(point[0].x , point[0].y); path.lineTo(point[1].x,point[1].y); path.lineTo(point[2].x,point[2].y); canvas.drawPath(path,paint); + canvas.restore(); } - /** - * This is used for the size of the shape that - * will be drawn. - * This is useless if you are using a custom shape. - * - * @return the size of the shape - */ - public float getSize() { - return mStyles.size; - } - - /** - * This is used for the size of the shape that - * will be drawn. - * This is useless if you are using a custom shape. - * - * @param radius the size of the shape - */ - public void setSize(float radius) { - mStyles.size = radius; - } - - /** - * @return the shape that will be drawn for each point - */ - public Shape getShape() { - return mStyles.shape; - } - - /** - * @param s the shape that will be drawn for each point - */ - public void setShape(Shape s) { - mStyles.shape = s; - } - - /** - * Use a custom handler to render your own - * drawing for each data point. - * - * @param shape handler to use a custom drawing - */ - public void setCustomShape(CustomShape shape) { - mCustomShape = shape; + void drawLabel45(float endX, float endY, E value, Canvas canvas) { + if (value.getLabel().startsWith("~")) { + float px = endX; + float py = endY + value.getSize(); + canvas.save(); + canvas.rotate(-45, px, py); + mPaint.setTextSize((int) (value.getSize() * 2.5)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + mPaint.setFakeBoldText(true); + mPaint.setTextAlign(Paint.Align.RIGHT); + canvas.drawText(value.getLabel().substring(1), px - value.getSize(), py, mPaint); + mPaint.setTextAlign(Paint.Align.LEFT); + canvas.restore(); + } else { + float px = endX; + float py = endY - value.getSize(); + canvas.save(); + canvas.rotate(-45, px, py); + mPaint.setTextSize((int) (value.getSize() * 2.5)); + mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + mPaint.setFakeBoldText(true); + canvas.drawText(value.getLabel(), px + value.getSize(), py, mPaint); + canvas.restore(); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationFragment.java new file mode 100644 index 0000000000..78e7791c2d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationFragment.java @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.plugins.Persistentnotification; + +import android.support.v4.app.Fragment; + +/** + * Created by adrian on 23/12/16. + */ + +public class PersistentNotificationFragment extends Fragment { + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/persistentnotification/PersistentNotificationPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/persistentnotification/PersistentNotificationPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java index a229d906e8..7e7f2ab7a2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/persistentnotification/PersistentNotificationPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationPlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.persistentnotification; +package info.nightscout.androidaps.plugins.Persistentnotification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -18,8 +18,11 @@ import info.nightscout.androidaps.MainActivity; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBasalProfile; @@ -29,16 +32,14 @@ import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.DecimalFormatter; /** * Created by adrian on 23/12/16. */ -public class PersistentNotificationPlugin implements PluginBase{ +public class PersistentNotificationPlugin implements PluginBase { private static final int ONGOING_NOTIFICATION_ID = 4711; static boolean fragmentEnabled = true; @@ -85,20 +86,30 @@ public class PersistentNotificationPlugin implements PluginBase{ return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if(getType() == type){ + if (getType() == type) { this.fragmentEnabled = fragmentEnabled; checkBusRegistration(); - updateNotification(); + //updateNotification(); } } private void updateNotification() { - if(!fragmentEnabled){ + if (!fragmentEnabled) { NotificationManager mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.cancel(ONGOING_NOTIFICATION_ID); @@ -107,14 +118,13 @@ public class PersistentNotificationPlugin implements PluginBase{ String line1 = ctx.getString(R.string.noprofile); - if (MainApp.getConfigBuilder().getActiveProfile() == null) return; - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); - BgReading lastBG = GlucoseStatus.lastBg(); + BgReading lastBG = DatabaseHelper.lastBg(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if(profile != null && lastBG != null) { + if (profile != null && lastBG != null) { line1 = lastBG.valueToUnitsToString(profile.getUnits()); if (glucoseStatus != null) { line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, profile.getUnits()) @@ -128,19 +138,17 @@ public class PersistentNotificationPlugin implements PluginBase{ PumpInterface pump = MainApp.getConfigBuilder(); - if (pump.isTempBasalInProgress()) { - TempBasal activeTemp = pump.getTempBasal(); + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()); line1 += " " + activeTemp.toStringShort(); } //IOB - ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB(); - IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round(); - IobTotal basalIob = new IobTotal(new Date().getTime()); - if (ConfigBuilderPlugin.getActiveTempBasals() != null) { - ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB(); - basalIob = ConfigBuilderPlugin.getActiveTempBasals().getLastCalculation().round(); - } + MainApp.getConfigBuilder().updateTotalIOBTreatments(); + MainApp.getConfigBuilder().updateTotalIOBTempBasals(); + IobTotal bolusIob = MainApp.getConfigBuilder().getLastCalculationTreatments().round(); + IobTotal basalIob = MainApp.getConfigBuilder().getLastCalculationTempBasals().round(); + String line2 = ctx.getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + ctx.getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + ctx.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; @@ -149,9 +157,8 @@ public class PersistentNotificationPlugin implements PluginBase{ String line3 = DecimalFormatter.to2Decimal(pump.getBaseBasalRate()) + " U/h"; - if (profile != null && profile.getActiveProfile() != null) - line3 += " - " + profile.getActiveProfile(); - + line3 += " - " + MainApp.getConfigBuilder().getProfileName(); + NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx); builder.setOngoing(true); @@ -183,32 +190,32 @@ public class PersistentNotificationPlugin implements PluginBase{ } private void checkBusRegistration() { - if(fragmentEnabled){ + if (fragmentEnabled) { MainApp.bus().register(this); } else { try { MainApp.bus().unregister(this); - } catch (Exception e) {} + } catch (Exception e) { + } } } @Override public void setFragmentVisible(int type, boolean fragmentVisible) { - //no visible fragment + //no visible fragment } private String deltastring(double deltaMGDL, double deltaMMOL, String units) { String deltastring = ""; - if (deltaMGDL >=0){ + if (deltaMGDL >= 0) { deltastring += "+"; - } else{ + } else { deltastring += "-"; } - if (units.equals(Constants.MGDL)){ + if (units.equals(Constants.MGDL)) { deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMGDL)); - } - else { + } else { deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMMOL)); } return deltastring; @@ -230,6 +237,11 @@ public class PersistentNotificationPlugin implements PluginBase{ updateNotification(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + updateNotification(); + } + @Subscribe public void onStatusEvent(final EventNewBG ev) { updateNotification(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java similarity index 99% rename from app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java index bb4513b069..7ae97a17b5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.CircadianPercentageProfile; +package info.nightscout.androidaps.plugins.ProfileCircadianPercentage; import android.app.Activity; @@ -33,14 +33,13 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SafeParse; -public class CircadianPercentageProfileFragment extends Fragment implements FragmentBase { +public class CircadianPercentageProfileFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfileFragment.class); private static CircadianPercentageProfilePlugin circadianPercentageProfilePlugin = new CircadianPercentageProfilePlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfilePlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java index 201b2ac37b..0fe6c30c78 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.CircadianPercentageProfile; +package info.nightscout.androidaps.plugins.ProfileCircadianPercentage; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -15,8 +15,9 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -29,10 +30,11 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte public static final String SETTINGS_PREFIX = "CircadianPercentageProfile"; private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfilePlugin.class); - private static boolean fragmentEnabled = true; + private static boolean fragmentEnabled = false; private static boolean fragmentVisible = true; - private static NSProfile convertedProfile = null; + private static ProfileStore convertedProfile = null; + private static String convertedProfileName = null; boolean mgdl; boolean mmol; @@ -90,6 +92,16 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; @@ -129,7 +141,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte mgdl = SP.getBoolean(SETTINGS_PREFIX + "mgdl", true); mmol = SP.getBoolean(SETTINGS_PREFIX + "mmol", false); - dia = SP.getDouble(SETTINGS_PREFIX + "dia", 3d); + dia = SP.getDouble(SETTINGS_PREFIX + "dia", Constants.defaultDIA); targetLow = SP.getDouble(SETTINGS_PREFIX + "targetlow", 80d); targetHigh = SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d); percentage = SP.getInt(SETTINGS_PREFIX + "percentage", 100); @@ -192,22 +204,27 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte } catch (JSONException e) { e.printStackTrace(); } - convertedProfile = new NSProfile(json, profileName); + convertedProfile = new ProfileStore(json); + convertedProfileName = profileName; } @Override - public NSProfile getProfile() { - + public ProfileStore getProfile() { performLimitCheck(); - return convertedProfile; } + @Override + public String getProfileName() { + performLimitCheck(); + return convertedProfileName; + } + private void performLimitCheck() { if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { String msg = String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage"); log.error(msg); - MainApp.getConfigBuilder().uploadError(msg); + NSUpload.uploadError(msg); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), msg, R.raw.error); percentage = Math.max(percentage, Constants.CPP_MIN_PERCENTAGE); percentage = Math.min(percentage, Constants.CPP_MAX_PERCENTAGE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java index 552a05cc28..86a983ae17 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.LocalProfile; +package info.nightscout.androidaps.plugins.ProfileLocal; import android.app.Activity; @@ -11,7 +11,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; -import android.widget.LinearLayout; import android.widget.RadioButton; import com.squareup.otto.Subscribe; @@ -24,14 +23,13 @@ import java.text.DecimalFormat; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.utils.SafeParse; import info.nightscout.utils.TimeListEdit; -public class LocalProfileFragment extends Fragment implements FragmentBase { +public class LocalProfileFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(LocalProfileFragment.class); private static LocalProfilePlugin localProfilePlugin = new LocalProfilePlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfilePlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java index a4c65e83dd..d22361981c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.LocalProfile; +package info.nightscout.androidaps.plugins.ProfileLocal; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -15,9 +15,8 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; /** * Created by mike on 05.08.2016. @@ -25,10 +24,11 @@ import info.nightscout.utils.SafeParse; public class LocalProfilePlugin implements PluginBase, ProfileInterface { private static Logger log = LoggerFactory.getLogger(LocalProfilePlugin.class); - private static boolean fragmentEnabled = true; + private static boolean fragmentEnabled = false; private static boolean fragmentVisible = true; - private static NSProfile convertedProfile = null; + private static ProfileStore convertedProfile = null; + private static String convertedProfileName = null; final private String DEFAULTARRAY = "[{\"timeAsSeconds\":0,\"value\":0}]"; @@ -86,6 +86,16 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; @@ -120,7 +130,7 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { mgdl = SP.getBoolean("LocalProfile" + "mgdl", false); mmol = SP.getBoolean("LocalProfile" + "mmol", true); - dia = SP.getDouble("LocalProfile" + "dia", 3d); + dia = SP.getDouble("LocalProfile" + "dia", Constants.defaultDIA); try { ic = new JSONArray(SP.getString("LocalProfile" + "ic", DEFAULTARRAY)); } catch (JSONException e1) { @@ -221,12 +231,18 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { } catch (JSONException e) { e.printStackTrace(); } - convertedProfile = new NSProfile(json, "LocalProfile"); + convertedProfile = new ProfileStore(json); + convertedProfileName = "LocalProfile"; } @Override - public NSProfile getProfile() { + public ProfileStore getProfile() { return convertedProfile; } + @Override + public String getProfileName() { + return convertedProfileName; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/NSProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java similarity index 76% rename from app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/NSProfileFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java index da54fcb27c..f765fe6ed1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/NSProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.NSProfile; +package info.nightscout.androidaps.plugins.ProfileNS; import android.app.Activity; import android.os.Bundle; @@ -12,11 +12,11 @@ import com.squareup.otto.Subscribe; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.NSProfile.events.EventNSProfileUpdateGUI; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; import info.nightscout.utils.DecimalFormatter; -public class NSProfileFragment extends Fragment implements FragmentBase { +public class NSProfileFragment extends Fragment { private static NSProfilePlugin nsProfilePlugin = new NSProfilePlugin(); public static NSProfilePlugin getPlugin() { @@ -75,19 +75,21 @@ public class NSProfileFragment extends Fragment implements FragmentBase { } private void updateGUI() { - if (nsProfilePlugin.profile == null) { + if (MainApp.getConfigBuilder().getProfile() == null) { noProfile.setVisibility(View.VISIBLE); return; } else { noProfile.setVisibility(View.GONE); } - units.setText(nsProfilePlugin.profile.getUnits()); - dia.setText(DecimalFormatter.to2Decimal(nsProfilePlugin.profile.getDia()) + " h"); - activeProfile.setText(nsProfilePlugin.profile.getActiveProfile()); - ic.setText(nsProfilePlugin.profile.getIcList()); - isf.setText(nsProfilePlugin.profile.getIsfList()); - basal.setText(nsProfilePlugin.profile.getBasalList()); - target.setText(nsProfilePlugin.profile.getTargetList()); + + Profile profile = MainApp.getConfigBuilder().getProfile(); + units.setText(profile.getUnits()); + dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); + activeProfile.setText(MainApp.getConfigBuilder().getProfileName()); + ic.setText(profile.getIcList()); + isf.setText(profile.getIsfList()); + basal.setText(profile.getBasalList()); + target.setText(profile.getTargetList()); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java similarity index 64% rename from app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/NSProfilePlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java index 3c19b5a5c4..b310993584 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java @@ -1,8 +1,6 @@ -package info.nightscout.androidaps.plugins.NSProfile; +package info.nightscout.androidaps.plugins.ProfileNS; import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; import android.support.annotation.Nullable; import com.squareup.otto.Subscribe; @@ -16,11 +14,12 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; -import info.nightscout.androidaps.events.EventNewBasalProfile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.androidaps.plugins.NSProfile.events.EventNSProfileUpdateGUI; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; +import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.utils.SP; /** @@ -37,7 +36,7 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { static boolean fragmentEnabled = true; static boolean fragmentVisible = true; - static NSProfile profile = null; + static ProfileStore profile = null; public NSProfilePlugin() { MainApp.bus().register(this); @@ -53,7 +52,7 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.profileviewer_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -63,12 +62,12 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { @Override public boolean isEnabled(int type) { - return type == PROFILE && fragmentEnabled; + return type == PROFILE && (Config.NSCLIENT || fragmentEnabled); } @Override public boolean isVisibleInTabs(int type) { - return type == PROFILE && fragmentVisible; + return type == PROFILE && (Config.NSCLIENT ||fragmentVisible); } @Override @@ -76,6 +75,16 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return !Config.NSCLIENT; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; @@ -92,18 +101,24 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { } @Subscribe - public void onStatusEvent(final EventNewBasalProfile ev) { - profile = new NSProfile(ev.newNSProfile.getData(), ev.newNSProfile.getActiveProfile()); + public static void storeNewProfile(ProfileStore newProfile) { + profile = new ProfileStore(newProfile.getData()); storeNSProfile(); MainApp.bus().post(new EventNSProfileUpdateGUI()); + PumpInterface pump = MainApp.getConfigBuilder(); + if (SP.getBoolean("syncprofiletopump", false)) { + if (pump.setNewBasalProfile(MainApp.getConfigBuilder().getProfile()) == PumpInterface.SUCCESS) { + SmsCommunicatorPlugin smsCommunicatorPlugin = (SmsCommunicatorPlugin) MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); + if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { + smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); + } + } + } + } - private void storeNSProfile() { - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - SharedPreferences.Editor editor = settings.edit(); - editor.putString("profile", profile.getData().toString()); - editor.putString("activeProfile", profile.getActiveProfile()); - editor.apply(); + private static void storeNSProfile() { + SP.putString("profile", profile.getData().toString()); if (Config.logPrefsChange) log.debug("Storing profile"); } @@ -111,14 +126,12 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { private void loadNSProfile() { if (Config.logPrefsChange) log.debug("Loading stored profile"); - String activeProfile = SP.getString("activeProfile", null); String profileString = SP.getString("profile", null); if (profileString != null) { if (Config.logPrefsChange) { log.debug("Loaded profile: " + profileString); - log.debug("Loaded active profile: " + activeProfile); try { - profile = new NSProfile(new JSONObject(profileString), activeProfile); + profile = new ProfileStore(new JSONObject(profileString)); } catch (JSONException e) { e.printStackTrace(); profile = null; @@ -136,7 +149,12 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { @Nullable @Override - public NSProfile getProfile() { + public ProfileStore getProfile() { return profile; } + + @Override + public String getProfileName() { + return profile.getDefaultProfileName(); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/events/EventNSProfileUpdateGUI.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java similarity index 57% rename from app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/events/EventNSProfileUpdateGUI.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java index df7fe40879..7bb5df792f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSProfile/events/EventNSProfileUpdateGUI.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/events/EventNSProfileUpdateGUI.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.NSProfile.events; +package info.nightscout.androidaps.plugins.ProfileNS.events; /** * Created by mike on 05.08.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java index 4a31333ad9..b183b28a0b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.SimpleProfile; +package info.nightscout.androidaps.plugins.ProfileSimple; import android.app.Activity; @@ -11,30 +11,22 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; -import android.widget.LinearLayout; import android.widget.RadioButton; import com.squareup.otto.Subscribe; -import org.json.JSONArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.DecimalFormat; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.interfaces.FragmentBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SafeParse; -import info.nightscout.utils.TimeListEdit; -public class SimpleProfileFragment extends Fragment implements FragmentBase { +public class SimpleProfileFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(SimpleProfileFragment.class); private static SimpleProfilePlugin simpleProfilePlugin = new SimpleProfilePlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfilePlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java index f40d85371e..40a53d0707 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.SimpleProfile; +package info.nightscout.androidaps.plugins.ProfileSimple; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -15,9 +15,8 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; /** * Created by mike on 05.08.2016. @@ -25,10 +24,10 @@ import info.nightscout.utils.SafeParse; public class SimpleProfilePlugin implements PluginBase, ProfileInterface { private static Logger log = LoggerFactory.getLogger(SimpleProfilePlugin.class); - private static boolean fragmentEnabled = true; + private static boolean fragmentEnabled = false; private static boolean fragmentVisible = true; - private static NSProfile convertedProfile = null; + private static ProfileStore convertedProfile = null; boolean mgdl; boolean mmol; @@ -84,6 +83,16 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PROFILE) this.fragmentEnabled = fragmentEnabled; @@ -118,7 +127,7 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { mgdl = SP.getBoolean("SimpleProfile" + "mgdl", true); mmol = SP.getBoolean("SimpleProfile" + "mmol", false); - dia = SP.getDouble("SimpleProfile" + "dia", 3d); + dia = SP.getDouble("SimpleProfile" + "dia", Constants.defaultDIA); ic = SP.getDouble("SimpleProfile" + "ic", 20d); isf = SP.getDouble("SimpleProfile" + "isf", 200d); basal = SP.getDouble("SimpleProfile" + "basal", 1d); @@ -184,12 +193,17 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { } catch (JSONException e) { e.printStackTrace(); } - convertedProfile = new NSProfile(json, "SimpleProfile"); + convertedProfile = new ProfileStore(json); } @Override - public NSProfile getProfile() { + public ProfileStore getProfile() { return convertedProfile; } + @Override + public String getProfileName() { + return "SimpleProfile"; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/BluetoothDevicePreference.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/BluetoothDevicePreference.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java index ba7ec5f533..63e14f0921 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/BluetoothDevicePreference.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/BluetoothDevicePreference.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR; +package info.nightscout.androidaps.plugins.PumpDanaR; import android.bluetooth.*; import android.content.Context; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java similarity index 84% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java index c0faeddef1..20c8843a31 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR; +package info.nightscout.androidaps.plugins.PumpDanaR; import android.annotation.SuppressLint; @@ -24,24 +24,24 @@ import java.util.Date; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.DanaR.Dialogs.ProfileViewDialog; -import info.nightscout.androidaps.plugins.DanaR.History.DanaRHistoryActivity; -import info.nightscout.androidaps.plugins.DanaR.History.DanaRStatsActivity; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRStatsActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SetWarnColor; -public class DanaRFragment extends Fragment implements FragmentBase { +public class DanaRFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(DanaRFragment.class); private static DanaRPlugin danaRPlugin; public static DanaRPlugin getPlugin() { - if(danaRPlugin==null){ + if (danaRPlugin == null) { danaRPlugin = new DanaRPlugin(); } return danaRPlugin; @@ -64,6 +64,8 @@ public class DanaRFragment extends Fragment implements FragmentBase { TextView reservoirView; TextView iobView; TextView firmwareView; + TextView basalStepView; + TextView bolusStepView; Button viewProfileButton; Button historyButton; Button statsButton; @@ -110,6 +112,8 @@ public class DanaRFragment extends Fragment implements FragmentBase { viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile); historyButton = (Button) view.findViewById(R.id.danar_history); statsButton = (Button) view.findViewById(R.id.danar_stats); + basalStepView = (TextView) view.findViewById(R.id.danar_basalstep); + bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep); viewProfileButton.setOnClickListener(new View.OnClickListener() { @@ -194,6 +198,11 @@ public class DanaRFragment extends Fragment implements FragmentBase { updateGUI(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange s) { + updateGUI(); + } + // GUI functions private void updateGUI() { Activity activity = getActivity(); @@ -202,7 +211,7 @@ public class DanaRFragment extends Fragment implements FragmentBase { @SuppressLint("SetTextI18n") @Override public void run() { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); if (pump.lastConnection.getTime() != 0) { Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); int agoMin = (int) (agoMsec / 60d / 1000d); @@ -211,22 +220,22 @@ public class DanaRFragment extends Fragment implements FragmentBase { } if (pump.lastBolusTime.getTime() != 0) { Long agoMsec = new Date().getTime() - pump.lastBolusTime.getTime(); - double agoHours = agoMsec / 60d / 60d / 1000d; + double agoHours = agoMsec / 60d / 60d / 1000d; if (agoHours < 6) // max 6h back - lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getPlugin().getDanaRPump().lastBolusAmount) + " U"); + lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); else lastBolusView.setText(""); } dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U"); SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d); basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(getPlugin().getBaseBasalRate()) + " U/h"); - if (getPlugin().isRealTempBasalInProgress()) { - tempBasalView.setText(getPlugin().getRealTempBasal().toString()); + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { + tempBasalView.setText(MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()).toStringFull()); } else { tempBasalView.setText(""); } - if (getPlugin().isExtendedBoluslInProgress()) { - extendedBolusView.setText(getPlugin().getExtendedBolus().toString()); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).toString()); } else { extendedBolusView.setText(""); } @@ -240,6 +249,9 @@ public class DanaRFragment extends Fragment implements FragmentBase { } else { firmwareView.setText("OLD"); } + basalStepView.setText("" + pump.basalStep); + bolusStepView.setText("" + pump.bolusStep); + } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java similarity index 69% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index 4a2d9d3a56..6d337048d7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -1,12 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR; +package info.nightscout.androidaps.plugins.PumpDanaR; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.os.IBinder; -import android.preference.PreferenceManager; import android.support.annotation.Nullable; import com.squareup.otto.Subscribe; @@ -24,8 +22,10 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -35,15 +35,17 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService; -import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; +import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. @@ -56,50 +58,43 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf return DanaRFragment.class.getName(); } - static boolean fragmentPumpEnabled = true; - static boolean fragmentProfileEnabled = true; + static boolean fragmentPumpEnabled = false; + static boolean fragmentProfileEnabled = false; static boolean fragmentPumpVisible = true; - public static ExecutionService sExecutionService; + public static DanaRExecutionService sExecutionService; - private static DanaRPump sDanaRPump = new DanaRPump(); + private static DanaRPump pump = DanaRPump.getInstance(); private static boolean useExtendedBoluses = false; public static PumpDescription pumpDescription = new PumpDescription(); - public static DanaRPump getDanaRPump() { - return sDanaRPump; - } - public DanaRPlugin() { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); + useExtendedBoluses = SP.getBoolean("danar_useextended", false); Context context = MainApp.instance().getApplicationContext(); - Intent intent = new Intent(context, ExecutionService.class); + Intent intent = new Intent(context, DanaRExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); MainApp.bus().register(this); - pumpDescription.isBolusCapable = true; // TODO: use description in setTempBasalAbsolute - pumpDescription.bolusStep = 0.05d; + pumpDescription.isBolusCapable = true; + pumpDescription.bolusStep = 0.1d; pumpDescription.isExtendedBolusCapable = true; - pumpDescription.extendedBolusStep = 0.05d; + pumpDescription.extendedBolusStep = 0.1d; + pumpDescription.extendedBolusDurationStep = 30; + pumpDescription.extendedBolusMaxDuration = 8 * 60; pumpDescription.isTempBasalCapable = true; - pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT; - pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT; - pumpDescription.maxHighTempPercent = 200; - pumpDescription.maxHighTempAbsolute = 0; - pumpDescription.lowTempPercentStep = 10; - pumpDescription.lowTempAbsoluteStep = 0; - pumpDescription.lowTempPercentDuration = 60; - pumpDescription.lowTempAbsoluteDuration = 60; - pumpDescription.highTempPercentStep = 10; - pumpDescription.highTempAbsoluteStep = 0.05d; - pumpDescription.highTempPercentDuration = 60; - pumpDescription.highTempAbsoluteDuration = 30; + pumpDescription.tempBasalStyle = PumpDescription.PERCENT; + + pumpDescription.maxTempPercent = 200; + pumpDescription.tempPercentStep = 10; + + pumpDescription.tempDurationStep = 60; + pumpDescription.tempMaxDuration = 24 * 60; + pumpDescription.isSetBasalProfileCapable = true; pumpDescription.basalStep = 0.01d; @@ -117,7 +112,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRExecutionService.LocalBinder mLocalBinder = (DanaRExecutionService.LocalBinder) service; sExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -132,12 +127,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf public void onStatusEvent(final EventPreferenceChange s) { if (isEnabled(PUMP)) { boolean previousValue = useExtendedBoluses; - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); + useExtendedBoluses = SP.getBoolean("danar_useextended", false); - pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT; - - if (useExtendedBoluses != previousValue && isExtendedBoluslInProgress()) { + if (useExtendedBoluses != previousValue && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { sExecutionService.extendedBolusStop(); } } @@ -157,7 +149,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.danarpump_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -185,6 +177,16 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return type == PUMP; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PluginBase.PROFILE) @@ -206,14 +208,19 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf this.fragmentPumpVisible = fragmentVisible; } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return useExtendedBoluses; + } + @Override public boolean isInitialized() { - return getDanaRPump().lastConnection.getTime() > 0 && getDanaRPump().isExtendedBolusEnabled; + return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled; } @Override public boolean isSuspended() { - return getDanaRPump().pumpSuspended; + return pump.pumpSuspended; } @Override @@ -224,23 +231,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf // Pump interface @Override - public boolean isTempBasalInProgress() { - if (getRealTempBasal() != null) return true; - if (getExtendedBolus() != null && useExtendedBoluses) return true; - return false; - } - - public boolean isRealTempBasalInProgress() { - return getRealTempBasal() != null; //TODO: crosscheck here - } - - @Override - public boolean isExtendedBoluslInProgress() { - return getExtendedBolus() != null; //TODO: crosscheck here - } - - @Override - public int setNewBasalProfile(NSProfile profile) { + public int setNewBasalProfile(Profile profile) { if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); return FAILED; @@ -265,10 +256,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf } @Override - public boolean isThisProfileSet(NSProfile profile) { + public boolean isThisProfileSet(Profile profile) { if (!isInitialized()) return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS - DanaRPump pump = getDanaRPump(); if (pump.pumpProfiles == null) return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS int basalValues = pump.basal48Enable ? 48 : 24; @@ -287,7 +277,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Date lastDataTime() { - return getDanaRPump().lastConnection; + return pump.lastConnection; } @Override @@ -299,84 +289,33 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public double getBaseBasalRate() { - return getDanaRPump().currentBasal; + return pump.currentBasal; } @Override - public double getTempBasalAbsoluteRate() { - TempBasal tb = getRealTempBasal(); - if (tb != null) { - if (tb.isAbsolute) { - return tb.absolute; - } else { - Double baseRate = getBaseBasalRate(); - Double tempRate = baseRate * (tb.percent / 100d); - return tempRate; - } - } - TempBasal eb = getExtendedBolus(); - if (eb != null && useExtendedBoluses) { - return getBaseBasalRate() + eb.absolute; - } - return 0; - } - - @Override - public double getTempBasalRemainingMinutes() { - if (isRealTempBasalInProgress()) - return getRealTempBasal().getPlannedRemainingMinutes(); - if (isExtendedBoluslInProgress() && useExtendedBoluses) - return getExtendedBolus().getPlannedRemainingMinutes(); - return 0; - } - - @Override - public TempBasal getTempBasal() { - if (isRealTempBasalInProgress()) - return getRealTempBasal(); - if (isExtendedBoluslInProgress() && useExtendedBoluses) - return getExtendedBolus(); - return null; - } - - public TempBasal getTempBasal(Date time) { - TempBasal temp = MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(time); - if (temp != null) return temp; - if (useExtendedBoluses) - return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(time); - return null; - } - - public TempBasal getRealTempBasal() { - return MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(new Date()); - } - - @Override - public TempBasal getExtendedBolus() { - return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(new Date()); - } - - @Override - public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) { + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - insulin = configBuilderPlugin.applyBolusConstraints(insulin); - if (insulin > 0 || carbs > 0) { - Treatment t = new Treatment(); + detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { + Treatment t = new Treatment(detailedBolusInfo.insulinInterface); boolean connectionOK = false; - if (insulin > 0 || carbs > 0) connectionOK = sExecutionService.bolus(insulin, carbs, t); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; - result.carbsDelivered = carbs; + result.carbsDelivered = detailedBolusInfo.carbs; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); if (Config.logPumpActions) - log.debug("deliverTreatment: OK. Asked: " + insulin + " Delivered: " + result.bolusDelivered); + log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered); + detailedBolusInfo.insulin = t.insulin; + detailedBolusInfo.date = new Date().getTime(); + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); return result; } else { PumpEnactResult result = new PumpEnactResult(); result.success = false; result.bolusDelivered = 0d; - result.carbsDelivered = 0; + result.carbsDelivered = 0d; result.comment = MainApp.instance().getString(R.string.danar_invalidinput); log.error("deliverTreatment: Invalid input"); return result; @@ -396,7 +335,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { // Recheck pump status if older than 30 min - if (getDanaRPump().lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) { + if (pump.lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) { doConnect("setTempBasalAbsolute old data"); } @@ -412,13 +351,13 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf if (doTempOff) { // If extended in progress - if (isExtendedBoluslInProgress() && useExtendedBoluses) { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping extended bolus (doTempOff)"); return cancelExtendedBolus(); } // If temp in progress - if (isRealTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping temp basal (doTempOff)"); return cancelRealTempBasal(); @@ -437,11 +376,11 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); - if (percentRate > 200) { - percentRate = 200; + if (percentRate > getPumpDescription().maxTempPercent) { + percentRate = getPumpDescription().maxTempPercent; } // If extended in progress - if (isExtendedBoluslInProgress() && useExtendedBoluses) { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)"); result = cancelExtendedBolus(); @@ -451,14 +390,14 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf } } // Check if some temp is already in progress - if (isRealTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { // Correct basal already set ? - if (getRealTempBasal().percent == percentRate) { + if (MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()).percentRate == percentRate) { result.success = true; result.percent = percentRate; - result.absolute = getTempBasalAbsoluteRate(); + result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); result.enacted = false; - result.duration = ((Double) getTempBasalRemainingMinutes()).intValue(); + result.duration = ((Double) MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()).intValue(); result.isPercent = true; result.isTempCancel = false; if (Config.logPumpActions) @@ -482,7 +421,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf } if (doExtendedTemp) { // Check if some temp is already in progress - if (isRealTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)"); result = cancelRealTempBasal(); @@ -503,17 +442,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf // What is current rate of extended bolusing in u/h? if (Config.logPumpActions) { - log.debug("setTempBasalAbsolute: Extended bolus in progress: " + isExtendedBoluslInProgress() + " rate: " + getDanaRPump().extendedBolusAbsoluteRate + "U/h duration remaining: " + getDanaRPump().extendedBolusRemainingMinutes + "min"); + log.debug("setTempBasalAbsolute: Extended bolus in progress: " + MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() + " rate: " + pump.extendedBolusAbsoluteRate + "U/h duration remaining: " + pump.extendedBolusRemainingMinutes + "min"); log.debug("setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h"); } // Compare with extended rate in progress - if (isExtendedBoluslInProgress() && Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < getPumpDescription().extendedBolusStep) { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && Math.abs(pump.extendedBolusAbsoluteRate - extendedRateToSet) < getPumpDescription().extendedBolusStep) { // correct extended already set result.success = true; - result.absolute = getDanaRPump().extendedBolusAbsoluteRate; + result.absolute = pump.extendedBolusAbsoluteRate; result.enacted = false; - result.duration = getDanaRPump().extendedBolusRemainingMinutes; + result.duration = pump.extendedBolusRemainingMinutes; result.isPercent = false; result.isTempCancel = false; if (Config.logPumpActions) @@ -555,14 +494,15 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf log.error("setTempBasalPercent: Invalid input"); return result; } - if (percent > 200) percent = 200; - if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { + if (percent > getPumpDescription().maxTempPercent) + percent = getPumpDescription().maxTempPercent; + if (pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { result.enacted = false; result.success = true; result.isTempCancel = false; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = getDanaRPump().tempBasalRemainingMin; - result.percent = getDanaRPump().tempBasalPercent; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: Correct value already set"); @@ -570,13 +510,13 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf } int durationInHours = Math.max(durationInMinutes / 60, 1); boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); - if (connectionOK && getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { + if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { result.enacted = true; result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); result.isTempCancel = false; - result.duration = getDanaRPump().tempBasalRemainingMin; - result.percent = getDanaRPump().tempBasalPercent; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: OK"); @@ -597,28 +537,28 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); PumpEnactResult result = new PumpEnactResult(); - if (getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + if (pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { result.enacted = false; result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = getDanaRPump().extendedBolusRemainingMinutes; - result.absolute = getDanaRPump().extendedBolusAbsoluteRate; + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; result.isPercent = false; result.isTempCancel = false; if (Config.logPumpActions) - log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + getDanaRPump().extendedBolusAmount + " Asked: " + insulin); + log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); return result; } int durationInHalfHours = Math.max(durationInMinutes / 30, 1); boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); - if (connectionOK && getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { result.enacted = true; result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); result.isTempCancel = false; - result.duration = getDanaRPump().extendedBolusRemainingMinutes; - result.absolute = getDanaRPump().extendedBolusAbsoluteRate; - result.bolusDelivered = getDanaRPump().extendedBolusAmount; + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; + result.bolusDelivered = pump.extendedBolusAmount; result.isPercent = false; if (Config.logPumpActions) log.debug("setExtendedBolus: OK"); @@ -633,10 +573,12 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public PumpEnactResult cancelTempBasal() { - if (isRealTempBasalInProgress()) + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) return cancelRealTempBasal(); - if (isExtendedBoluslInProgress()) - return cancelExtendedBolus(); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { + PumpEnactResult cancelEx = cancelExtendedBolus(); + return cancelEx; + } PumpEnactResult result = new PumpEnactResult(); result.success = true; result.enacted = false; @@ -647,12 +589,12 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf public PumpEnactResult cancelRealTempBasal() { PumpEnactResult result = new PumpEnactResult(); - if (getDanaRPump().isTempBasalInProgress) { + if (pump.isTempBasalInProgress) { sExecutionService.tempBasalStop(); result.enacted = true; result.isTempCancel = true; } - if (!getDanaRPump().isTempBasalInProgress) { + if (!pump.isTempBasalInProgress) { result.success = true; result.isTempCancel = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); @@ -671,12 +613,12 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public PumpEnactResult cancelExtendedBolus() { PumpEnactResult result = new PumpEnactResult(); - if (getDanaRPump().isExtendedInProgress) { + if (pump.isExtendedInProgress) { sExecutionService.extendedBolusStop(); result.enacted = true; result.isTempCancel = true; } - if (!getDanaRPump().isExtendedInProgress) { + if (!pump.isExtendedInProgress) { result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); if (Config.logPumpActions) @@ -708,48 +650,55 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public JSONObject getJSONStatus() { - if (getDanaRPump().lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) { + if (pump.lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) { return null; } - JSONObject pump = new JSONObject(); + JSONObject pumpjson = new JSONObject(); JSONObject battery = new JSONObject(); JSONObject status = new JSONObject(); JSONObject extended = new JSONObject(); try { - battery.put("percent", getDanaRPump().batteryRemaining); - status.put("status", getDanaRPump().pumpSuspended ? "suspended" : "normal"); - status.put("timestamp", DateUtil.toISOString(getDanaRPump().lastConnection)); + battery.put("percent", pump.batteryRemaining); + status.put("status", pump.pumpSuspended ? "suspended" : "normal"); + status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); - extended.put("PumpIOB", getDanaRPump().iob); - extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString()); - extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount); - TempBasal tb = getTempBasal(); + extended.put("PumpIOB", pump.iob); + if (pump.lastBolusTime.getTime() != 0) { + extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); + extended.put("LastBolusAmount", pump.lastBolusAmount); + } + TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()); if (tb != null) { - extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate()); - extended.put("TempBasalStart", tb.timeStart.toLocaleString()); + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(new Date().getTime())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - extended.put("IsExtended", tb.isExtended); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()); + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); + extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); + extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); } extended.put("BaseBasalRate", getBaseBasalRate()); try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile()); + extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); } catch (Exception e) { } - pump.put("battery", battery); - pump.put("status", status); - pump.put("extended", extended); - pump.put("reservoir", (int) getDanaRPump().reservoirRemainingUnits); - pump.put("clock", DateUtil.toISOString(new Date())); + pumpjson.put("battery", battery); + pumpjson.put("status", status); + pumpjson.put("extended", extended); + pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); + pumpjson.put("clock", DateUtil.toISOString(new Date())); } catch (JSONException e) { e.printStackTrace(); } - return pump; + return pumpjson; } @Override public String deviceID() { - return getDanaRPump().serialNumber; + return pump.serialNumber; } @Override @@ -785,9 +734,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Double applyBasalConstraints(Double absoluteRate) { double origAbsoluteRate = absoluteRate; - if (getDanaRPump() != null) { - if (absoluteRate > getDanaRPump().maxBasal) { - absoluteRate = getDanaRPump().maxBasal; + if (pump != null) { + if (absoluteRate > pump.maxBasal) { + absoluteRate = pump.maxBasal; if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); } @@ -800,7 +749,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf public Integer applyBasalConstraints(Integer percentRate) { Integer origPercentRate = percentRate; if (percentRate < 0) percentRate = 0; - if (percentRate > 200) percentRate = 200; + if (percentRate > getPumpDescription().maxTempPercent) + percentRate = getPumpDescription().maxTempPercent; if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); return percentRate; @@ -810,9 +760,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Double applyBolusConstraints(Double insulin) { double origInsulin = insulin; - if (getDanaRPump() != null) { - if (insulin > getDanaRPump().maxBolus) { - insulin = getDanaRPump().maxBolus; + if (pump != null) { + if (insulin > pump.maxBolus) { + insulin = pump.maxBolus; if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); } @@ -832,36 +782,40 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Nullable @Override - public NSProfile getProfile() { - DanaRPump pump = getDanaRPump(); + public ProfileStore getProfile() { if (pump.lastSettingsRead.getTime() == 0) return null; // no info now return pump.createConvertedProfile(); } + @Override + public String getProfileName() { + return pump.createConvertedProfileName(); + } + // Reply for sms communicator public String shortStatus(boolean veryShort) { String ret = ""; - if (getDanaRPump().lastConnection.getTime() != 0) { - Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime(); + if (pump.lastConnection.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); int agoMin = (int) (agoMsec / 60d / 1000d); ret += "LastConn: " + agoMin + " minago\n"; } - if (getDanaRPump().lastBolusTime.getTime() != 0) { - ret += "LastBolus: " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", getDanaRPump().lastBolusTime) + "\n"; + if (pump.lastBolusTime.getTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; } - if (isRealTempBasalInProgress()) { - ret += "Temp: " + getRealTempBasal().toString() + "\n"; + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { + ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()).toStringFull() + "\n"; } - if (isExtendedBoluslInProgress()) { - ret += "Extended: " + getExtendedBolus().toString() + "\n"; + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).toString() + "\n"; } - if (!veryShort){ - ret += "TDD: " + DecimalFormatter.to0Decimal(getDanaRPump().dailyTotalUnits) + " / " + getDanaRPump().maxDailyTotalUnits + " U\n"; + if (!veryShort) { + ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; } - ret += "IOB: " + getDanaRPump().iob + "U\n"; - ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n"; - ret += "Batt: " + getDanaRPump().batteryRemaining + "\n"; + ret += "IOB: " + pump.iob + "U\n"; + ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; + ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; } // TODO: daily total constraint diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java similarity index 83% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRPump.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java index c68bac86ac..af36e4059f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRPump.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR; +package info.nightscout.androidaps.plugins.PumpDanaR; import org.json.JSONArray; import org.json.JSONException; @@ -9,13 +9,20 @@ import java.util.Date; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.utils.SP; /** * Created by mike on 04.07.2016. */ public class DanaRPump { + private static DanaRPump instance = null; + + public static DanaRPump getInstance() { + if (instance == null) instance = new DanaRPump(); + return instance; + } + public static final int UNITS_MGDL = 0; public static final int UNITS_MMOL = 1; @@ -26,6 +33,22 @@ public class DanaRPump { public static final String PROFILE_PREFIX = "DanaR-"; + // v2 history entries + public static final int TEMPSTART = 1; + public static final int TEMPSTOP = 2; + public static final int EXTENDEDSTART = 3; + public static final int EXTENDEDSTOP = 4; + public static final int BOLUS = 5; + public static final int DUALBOLUS = 6; + public static final int DUALEXTENDEDSTART = 7; + public static final int DUALEXTENDEDSTOP = 8; + public static final int SUSPENDON = 9; + public static final int SUSPENDOFF = 10; + public static final int REFILL = 11; + public static final int PRIME = 12; + public static final int PROFILECHANGE = 13; + public static final int CARBS = 14; + public Date lastConnection = new Date(0); public Date lastSettingsRead = new Date(0); @@ -45,7 +68,7 @@ public class DanaRPump { public boolean isConfigUD; public boolean isExtendedBolusEnabled; - + public boolean isEasyModeEnabled; // Status public boolean pumpSuspended; @@ -109,7 +132,7 @@ public class DanaRPump { public double maxBolus; public double maxBasal; - public NSProfile createConvertedProfile() { + public ProfileStore createConvertedProfile() { JSONObject json = new JSONObject(); JSONObject store = new JSONObject(); JSONObject profile = new JSONObject(); @@ -119,7 +142,7 @@ public class DanaRPump { // Evening / 17:00–21:59 // Night / 22:00–5:59 - double dia = SP.getDouble(R.string.key_danarprofile_dia, 3d); + double dia = SP.getDouble(R.string.key_danarprofile_dia, Constants.defaultDIA); try { json.put("defaultProfile", PROFILE_PREFIX + (activeProfile + 1)); @@ -166,7 +189,12 @@ public class DanaRPump { } catch (Exception e) { return null; } - return new NSProfile(json, PROFILE_PREFIX + (activeProfile + 1)); + + return new ProfileStore(json); + } + + public String createConvertedProfileName() { + return PROFILE_PREFIX + (activeProfile + 1); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/Dialogs/ProfileViewDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java similarity index 69% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/Dialogs/ProfileViewDialog.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java index 1cedf012fd..9f05a7569a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/Dialogs/ProfileViewDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.Dialogs; +package info.nightscout.androidaps.plugins.PumpDanaR.Dialogs; import android.os.Bundle; import android.os.Handler; @@ -17,8 +17,12 @@ import java.util.Date; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.utils.DecimalFormatter; /** @@ -41,14 +45,11 @@ public class ProfileViewDialog extends DialogFragment { Handler mHandler; static HandlerThread mHandlerThread; - NSProfile profile = null; - public ProfileViewDialog() { mHandlerThread = new HandlerThread(ProfileViewDialog.class.getSimpleName()); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); - profile = ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).getProfile(); } @Override @@ -72,8 +73,13 @@ public class ProfileViewDialog extends DialogFragment { mHandler.post(new Runnable() { @Override public void run() { - DanaRPlugin.getDanaRPump().lastSettingsRead = new Date(0); - DanaRPlugin.doConnect("ProfileViewDialog"); + DanaRPump.getInstance().lastSettingsRead = new Date(0); + if (MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP)) + DanaRPlugin.doConnect("ProfileViewDialog"); + if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP)) + DanaRKoreanPlugin.doConnect("ProfileViewDialog"); + if (MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP)) + DanaRv2Plugin.doConnect("ProfileViewDialog"); } }); dismiss(); @@ -91,15 +97,16 @@ public class ProfileViewDialog extends DialogFragment { } private void setContent() { - if (profile == null) { - noProfile.setVisibility(View.VISIBLE); - return; - } else { - noProfile.setVisibility(View.GONE); - } +// if (profile == null) { +// noProfile.setVisibility(View.VISIBLE); +// return; +// } else { +// noProfile.setVisibility(View.GONE); +// } + Profile profile = MainApp.getConfigBuilder().getProfile(); units.setText(profile.getUnits()); dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); - activeProfile.setText(profile.getActiveProfile()); + activeProfile.setText(MainApp.getConfigBuilder().getProfileName()); ic.setText(profile.getIcList()); isf.setText(profile.getIsfList()); basal.setText(profile.getBasalList()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRHistoryActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java index 994d5b629e..0116498233 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.History; +package info.nightscout.androidaps.plugins.PumpDanaR.History; import android.app.Activity; import android.content.ComponentName; @@ -21,16 +21,11 @@ import android.widget.Button; import android.widget.Spinner; import android.widget.TextView; -import com.j256.ormlite.dao.Dao; -import com.j256.ormlite.stmt.PreparedQuery; -import com.j256.ormlite.stmt.QueryBuilder; -import com.j256.ormlite.stmt.Where; import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -39,11 +34,10 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.ToastUtils; @@ -52,12 +46,12 @@ public class DanaRHistoryActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; - static NSProfile profile = null; + static Profile profile = null; Spinner historyTypeSpinner; TextView statusView; @@ -95,7 +89,7 @@ public class DanaRHistoryActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -131,7 +125,7 @@ public class DanaRHistoryActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRExecutionService.LocalBinder mLocalBinder = (DanaRExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -169,8 +163,7 @@ public class DanaRHistoryActivity extends Activity { typeList.add(new TypeList(RecordTypes.RECORD_TYPE_REFILL, getString(R.string.danar_history_refill))); typeList.add(new TypeList(RecordTypes.RECORD_TYPE_SUSPEND, getString(R.string.danar_history_syspend))); ArrayAdapter spinnerAdapter = new ArrayAdapter<>(this, - android.R.layout.simple_spinner_item, typeList); - spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_centered, typeList); historyTypeSpinner.setAdapter(spinnerAdapter); reloadButton.setOnClickListener(new View.OnClickListener() { @@ -250,7 +243,7 @@ public class DanaRHistoryActivity extends Activity { clearCardView(); } }); - profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); finish(); @@ -274,12 +267,12 @@ public class DanaRHistoryActivity extends Activity { @Override public void onBindViewHolder(HistoryViewHolder holder, int position) { DanaRHistoryRecord record = historyList.get(position); - holder.time.setText(DateUtil.dateAndTimeString(record.getRecordDate())); - holder.value.setText(DecimalFormatter.to2Decimal(record.getRecordValue())); - holder.stringvalue.setText(record.getStringRecordValue()); - holder.bolustype.setText(record.getBolusType()); - holder.duration.setText(DecimalFormatter.to0Decimal(record.getRecordDuration())); - holder.alarm.setText(record.getRecordAlarm()); + holder.time.setText(DateUtil.dateAndTimeString(record.recordDate)); + holder.value.setText(DecimalFormatter.to2Decimal(record.recordValue)); + holder.stringvalue.setText(record.stringRecordValue); + holder.bolustype.setText(record.bolusType); + holder.duration.setText(DecimalFormatter.to0Decimal(record.recordDuration)); + holder.alarm.setText(record.recordAlarm); switch (showingType) { case RecordTypes.RECORD_TYPE_ALARM: holder.time.setVisibility(View.VISIBLE); @@ -304,10 +297,10 @@ public class DanaRHistoryActivity extends Activity { holder.alarm.setVisibility(View.GONE); break; case RecordTypes.RECORD_TYPE_DAILY: - holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + "U"); - holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + "U"); - holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus() + record.getRecordDailyBasal()) + "U"); - holder.time.setText(DateUtil.dateString(record.getRecordDate())); + holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + "U"); + holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + "U"); + holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus + record.recordDailyBasal) + "U"); + holder.time.setText(DateUtil.dateString(record.recordDate)); holder.time.setVisibility(View.VISIBLE); holder.value.setVisibility(View.GONE); holder.stringvalue.setVisibility(View.GONE); @@ -319,7 +312,7 @@ public class DanaRHistoryActivity extends Activity { holder.alarm.setVisibility(View.GONE); break; case RecordTypes.RECORD_TYPE_GLUCOSE: - holder.value.setText(NSProfile.toUnitsString(record.getRecordValue(), record.getRecordValue() * Constants.MGDL_TO_MMOLL, profile.getUnits())); + holder.value.setText(Profile.toUnitsString(record.recordValue, record.recordValue * Constants.MGDL_TO_MMOLL, profile.getUnits())); // rest is the same case RecordTypes.RECORD_TYPE_CARBO: case RecordTypes.RECORD_TYPE_BASALHOUR: @@ -390,19 +383,8 @@ public class DanaRHistoryActivity extends Activity { } private void loadDataFromDB(byte type) { - try { - Dao dao = MainApp.getDbHelper().getDaoDanaRHistory(); - QueryBuilder queryBuilder = dao.queryBuilder(); - queryBuilder.orderBy("recordDate", false); - Where where = queryBuilder.where(); - where.eq("recordCode", type); - queryBuilder.limit(200L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - historyList = dao.query(preparedQuery); - } catch (SQLException e) { - e.printStackTrace(); - historyList = new ArrayList<>(); - } + historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); + runOnUiThread(new Runnable() { @Override public void run() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRNSHistorySync.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRNSHistorySync.java similarity index 68% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRNSHistorySync.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRNSHistorySync.java index 205d83df9c..72ecf91f0f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRNSHistorySync.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRNSHistorySync.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.History; +package info.nightscout.androidaps.plugins.PumpDanaR.History; import org.json.JSONException; import org.json.JSONObject; @@ -10,12 +10,14 @@ import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.ToastUtils; /** @@ -45,7 +47,7 @@ public class DanaRNSHistorySync { public void sync(int what) { try { ConfigBuilderPlugin ConfigBuilderPlugin = MainApp.getConfigBuilder(); - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); return; @@ -58,72 +60,72 @@ public class DanaRNSHistorySync { EventDanaRSyncStatus ev = new EventDanaRSyncStatus(); for (DanaRHistoryRecord record : historyRecords) { processing++; - if (record.get_id() != null) continue; - //log.debug(record.getBytes()); + if (record._id != null) continue; + //log.debug(record.bytes); JSONObject nsrec = new JSONObject(); ev.message = MainApp.sResources.getString(R.string.uploading) + " " + processing + "/" + records + " "; // TODO: translations - switch (record.getRecordCode()) { + switch (record.recordCode) { case RecordTypes.RECORD_TYPE_BOLUS: if ((what & SYNC_BOLUS) == 0) break; - switch (record.getBolusType()) { + switch (record.bolusType) { case "S": - log.debug("Syncing standard bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); + log.debug("Syncing standard bolus record " + record.recordValue + "U " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); nsrec.put("eventType", "Meal Bolus"); - nsrec.put("insulin", record.getRecordValue()); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("insulin", record.recordValue); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_sbolus); break; case "E": - if (record.getRecordDuration() > 0) { - log.debug("Syncing extended bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); - nsrec.put("eventType", "Combo Bolus"); + if (record.recordDuration > 0) { + log.debug("Syncing extended bolus record " + record.recordValue + "U " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); + nsrec.put("eventType", CareportalEvent.COMBOBOLUS); nsrec.put("insulin", 0); - nsrec.put("duration", record.getRecordDuration()); - nsrec.put("relative", record.getRecordValue() / record.getRecordDuration() * 60); + nsrec.put("duration", record.recordDuration); + nsrec.put("relative", record.recordValue / record.recordDuration * 60); nsrec.put("splitNow", 0); nsrec.put("splitExt", 100); - cal.setTimeInMillis(record.getRecordDate()); - cal.add(Calendar.MINUTE, -1 * record.getRecordDuration()); + cal.setTimeInMillis(record.recordDate); + cal.add(Calendar.MINUTE, -1 * record.recordDuration); nsrec.put("created_at", DateUtil.toISOString(cal.getTime())); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_ebolus); } else { - log.debug("NOT Syncing extended bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate()) + " zero duration"); + log.debug("NOT Syncing extended bolus record " + record.recordValue + "U " + DateUtil.toISOString(record.recordDate) + " zero duration"); } break; case "DS": - log.debug("Syncing dual(S) bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); - nsrec.put("eventType", "Combo Bolus"); - nsrec.put("insulin", record.getRecordValue()); + log.debug("Syncing dual(S) bolus record " + record.recordValue + "U " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); + nsrec.put("eventType", CareportalEvent.COMBOBOLUS); + nsrec.put("insulin", record.recordValue); nsrec.put("splitNow", 100); nsrec.put("splitExt", 0); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_dsbolus); break; case "DE": - log.debug("Syncing dual(E) bolus record " + record.getRecordValue() + "U " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); - nsrec.put("eventType", "Combo Bolus"); - nsrec.put("duration", record.getRecordDuration()); - nsrec.put("relative", record.getRecordValue() / record.getRecordDuration() * 60); + log.debug("Syncing dual(E) bolus record " + record.recordValue + "U " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); + nsrec.put("eventType", CareportalEvent.COMBOBOLUS); + nsrec.put("duration", record.recordDuration); + nsrec.put("relative", record.recordValue / record.recordDuration * 60); nsrec.put("splitNow", 0); nsrec.put("splitExt", 100); - cal.setTimeInMillis(record.getRecordDate()); - cal.add(Calendar.MINUTE, -1 * record.getRecordDuration()); + cal.setTimeInMillis(record.recordDate); + cal.add(Calendar.MINUTE, -1 * record.recordDuration); nsrec.put("created_at", DateUtil.toISOString(cal.getTime())); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_debolus); break; @@ -134,78 +136,78 @@ public class DanaRNSHistorySync { break; case RecordTypes.RECORD_TYPE_ERROR: if ((what & SYNC_ERROR) == 0) break; - log.debug("Syncing error record " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); + log.debug("Syncing error record " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); nsrec.put("eventType", "Note"); nsrec.put("notes", "Error"); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_error); break; case RecordTypes.RECORD_TYPE_REFILL: if ((what & SYNC_REFILL) == 0) break; - log.debug("Syncing refill record " + record.getRecordValue() + " " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); + log.debug("Syncing refill record " + record.recordValue + " " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); nsrec.put("eventType", "Insulin Change"); - nsrec.put("notes", "Refill " + record.getRecordValue() + "U"); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("notes", "Refill " + record.recordValue + "U"); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_refill); break; case RecordTypes.RECORD_TYPE_BASALHOUR: if ((what & SYNC_BASALHOURS) == 0) break; - log.debug("Syncing basal hour record " + record.getRecordValue() + " " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); - nsrec.put("eventType", "Temp Basal"); - nsrec.put("absolute", record.getRecordValue()); + log.debug("Syncing basal hour record " + record.recordValue + " " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); + nsrec.put("eventType", CareportalEvent.TEMPBASAL); + nsrec.put("absolute", record.recordValue); nsrec.put("duration", 60); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_basalhour); break; case RecordTypes.RECORD_TYPE_TB: - //log.debug("Ignoring TB record " + record.getBytes() + " " + DateUtil.toISOString(record.getRecordDate())); + //log.debug("Ignoring TB record " + record.bytes + " " + DateUtil.toISOString(record.recordDate)); break; case RecordTypes.RECORD_TYPE_GLUCOSE: if ((what & SYNC_GLUCOSE) == 0) break; - log.debug("Syncing glucose record " + record.getRecordValue() + " " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); + log.debug("Syncing glucose record " + record.recordValue + " " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); nsrec.put("eventType", "BG Check"); - nsrec.put("glucose", NSProfile.fromMgdlToUnits(record.getRecordValue(), profile.getUnits())); + nsrec.put("glucose", Profile.fromMgdlToUnits(record.recordValue, profile.getUnits())); nsrec.put("glucoseType", "Finger"); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_glucose); break; case RecordTypes.RECORD_TYPE_CARBO: if ((what & SYNC_CARBO) == 0) break; - log.debug("Syncing carbo record " + record.getRecordValue() + "g " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); + log.debug("Syncing carbo record " + record.recordValue + "g " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); nsrec.put("eventType", "Meal Bolus"); - nsrec.put("carbs", record.getRecordValue()); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("carbs", record.recordValue); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_carbohydrate); break; case RecordTypes.RECORD_TYPE_ALARM: if ((what & SYNC_ALARM) == 0) break; - log.debug("Syncing alarm record " + record.getRecordAlarm() + " " + DateUtil.toISOString(record.getRecordDate())); - nsrec.put(DANARSIGNATURE, record.getBytes()); + log.debug("Syncing alarm record " + record.recordAlarm + " " + DateUtil.toISOString(record.recordDate)); + nsrec.put(DANARSIGNATURE, record.bytes); nsrec.put("eventType", "Note"); - nsrec.put("notes", "Alarm: " + record.getRecordAlarm()); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); + nsrec.put("notes", "Alarm: " + record.recordAlarm); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_alarm); break; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java new file mode 100644 index 0000000000..6a360b9c26 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java @@ -0,0 +1,539 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.History; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.graphics.Color; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.support.v7.widget.LinearLayoutManager; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; + +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DanaRHistoryRecord; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SP; +import info.nightscout.utils.SafeParse; +import info.nightscout.utils.ToastUtils; + +public class DanaRStatsActivity extends Activity { + private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); + + private boolean mBounded; + private static DanaRExecutionService mExecutionService; + + private Handler mHandler; + private static HandlerThread mHandlerThread; + + TextView statusView, statsMessage, totalBaseBasal2; + EditText totalBaseBasal; + Button reloadButton; + LinearLayoutManager llm; + TableLayout tl, ctl, etl; + String TBB; + double magicNumber; + DecimalFormat decimalFormat; + + List historyList = new ArrayList<>(); + + public DanaRStatsActivity() { + super(); + mHandlerThread = new HandlerThread(DanaRStatsActivity.class.getSimpleName()); + mHandlerThread.start(); + this.mHandler = new Handler(mHandlerThread.getLooper()); + } + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, DanaRExecutionService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Override + protected void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onStop() { + super.onStop(); + if (mBounded) { + unbindService(mConnection); + mBounded = false; + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + View myView = getCurrentFocus(); + if (myView instanceof EditText) { + Rect rect = new Rect(); + myView.getGlobalVisibleRect(rect); + if (!rect.contains((int) event.getRawX(), (int) event.getRawY())) { + myView.clearFocus(); + } + } + } + return super.dispatchTouchEvent(event); + } + + ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + log.debug("Service is disconnected"); + mBounded = false; + mExecutionService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + log.debug("Service is connected"); + mBounded = true; + DanaRExecutionService.LocalBinder mLocalBinder = (DanaRExecutionService.LocalBinder) service; + mExecutionService = mLocalBinder.getServiceInstance(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.danar_statsactivity); + getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + statusView = (TextView) findViewById(R.id.danar_stats_connection_status); + reloadButton = (Button) findViewById(R.id.danar_statsreload); + totalBaseBasal = (EditText) findViewById(R.id.danar_stats_editTotalBaseBasal); + totalBaseBasal2 = (TextView) findViewById(R.id.danar_stats_editTotalBaseBasal2); + statsMessage = (TextView) findViewById(R.id.danar_stats_Message); + + statusView.setVisibility(View.GONE); + statsMessage.setVisibility(View.GONE); + + totalBaseBasal2.setEnabled(false); + totalBaseBasal2.setClickable(false); + totalBaseBasal2.setFocusable(false); + totalBaseBasal2.setInputType(0); + + decimalFormat = new DecimalFormat("0.000"); + llm = new LinearLayoutManager(this); + + TBB = SP.getString("TBB", "10.00"); + totalBaseBasal.setText(TBB); + + ProfileInterface pi = ConfigBuilderPlugin.getActiveProfileInterface(); + if (pi != null && pi instanceof CircadianPercentageProfilePlugin) { + double cppTBB = ((CircadianPercentageProfilePlugin) pi).baseBasalSum(); + totalBaseBasal.setText(decimalFormat.format(cppTBB)); + SP.putString("TBB", totalBaseBasal.getText().toString()); + TBB = SP.getString("TBB", ""); + } + + // stats table + tl = (TableLayout) findViewById(R.id.main_table); + TableRow tr_head = new TableRow(this); + tr_head.setBackgroundColor(Color.DKGRAY); + tr_head.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + TextView label_date = new TextView(this); + label_date.setText(getString(R.string.danar_stats_date)); + label_date.setTextColor(Color.WHITE); + tr_head.addView(label_date); + + TextView label_basalrate = new TextView(this); + label_basalrate.setText(getString(R.string.danar_stats_basalrate)); + label_basalrate.setTextColor(Color.WHITE); + tr_head.addView(label_basalrate); + + TextView label_bolus = new TextView(this); + label_bolus.setText(getString(R.string.danar_stats_bolus)); + label_bolus.setTextColor(Color.WHITE); + tr_head.addView(label_bolus); + + TextView label_tdd = new TextView(this); + label_tdd.setText(getString(R.string.danar_stats_tdd)); + label_tdd.setTextColor(Color.WHITE); + tr_head.addView(label_tdd); + + TextView label_ratio = new TextView(this); + label_ratio.setText(getString(R.string.danar_stats_ratio)); + label_ratio.setTextColor(Color.WHITE); + tr_head.addView(label_ratio); + + // add stats headers to tables + tl.addView(tr_head, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // cumulative table + ctl = (TableLayout) findViewById(R.id.cumulative_table); + TableRow ctr_head = new TableRow(this); + ctr_head.setBackgroundColor(Color.DKGRAY); + ctr_head.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + TextView label_cum_amount_days = new TextView(this); + label_cum_amount_days.setText(getString(R.string.danar_stats_amount_days)); + label_cum_amount_days.setTextColor(Color.WHITE); + ctr_head.addView(label_cum_amount_days); + + TextView label_cum_tdd = new TextView(this); + label_cum_tdd.setText(getString(R.string.danar_stats_tdd)); + label_cum_tdd.setTextColor(Color.WHITE); + ctr_head.addView(label_cum_tdd); + + TextView label_cum_ratio = new TextView(this); + label_cum_ratio.setText(getString(R.string.danar_stats_ratio)); + label_cum_ratio.setTextColor(Color.WHITE); + ctr_head.addView(label_cum_ratio); + + // add cummulative headers to tables + ctl.addView(ctr_head, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // expontial table + etl = (TableLayout) findViewById(R.id.expweight_table); + TableRow etr_head = new TableRow(this); + etr_head.setBackgroundColor(Color.DKGRAY); + etr_head.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + TextView label_exp_weight = new TextView(this); + label_exp_weight.setText(getString(R.string.danar_stats_weight)); + label_exp_weight.setTextColor(Color.WHITE); + etr_head.addView(label_exp_weight); + + TextView label_exp_tdd = new TextView(this); + label_exp_tdd.setText(getString(R.string.danar_stats_tdd)); + label_exp_tdd.setTextColor(Color.WHITE); + etr_head.addView(label_exp_tdd); + + TextView label_exp_ratio = new TextView(this); + label_exp_ratio.setText(getString(R.string.danar_stats_ratio)); + label_exp_ratio.setTextColor(Color.WHITE); + etr_head.addView(label_exp_ratio); + + // add expontial headers to tables + etl.addView(etr_head, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + reloadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mExecutionService.isConnected() || mExecutionService.isConnecting()) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); + return; + } + mHandler.post(new Runnable() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + statsMessage.setVisibility(View.VISIBLE); + statsMessage.setText(getString(R.string.danar_stats_warning_Message)); + } + }); + mExecutionService.loadHistory(RecordTypes.RECORD_TYPE_DAILY); + loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.VISIBLE); + statusView.setVisibility(View.GONE); + statsMessage.setVisibility(View.GONE); + } + }); + } + }); + } + }); + + totalBaseBasal.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + totalBaseBasal.clearFocus(); + return true; + } + return false; + } + }); + + totalBaseBasal.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + totalBaseBasal.getText().clear(); + } else { + SP.putString("TBB", totalBaseBasal.getText().toString()); + TBB = SP.getString("TBB", ""); + loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); + InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0); + } + } + }); + + loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); + } + + private void loadDataFromDB(byte type) { + historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); + + runOnUiThread(new Runnable() { + @Override + public void run() { + cleanTable(tl); + cleanTable(ctl); + cleanTable(etl); + DateFormat df = new SimpleDateFormat("dd.MM."); + + if (TextUtils.isEmpty(TBB)) { + totalBaseBasal.setError("Please Enter Total Base Basal"); + return; + } else { + magicNumber = SafeParse.stringToDouble(TBB); + } + + magicNumber *= 2; + totalBaseBasal2.setText(decimalFormat.format(magicNumber)); + + int i = 0; + double sum = 0d; + double weighted03 = 0d; + double weighted05 = 0d; + double weighted07 = 0d; + + for (DanaRHistoryRecord record : historyList) { + double tdd = record.recordDailyBolus + record.recordDailyBasal; + + // Create the table row + TableRow tr = new TableRow(DanaRStatsActivity.this); + if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY); + tr.setId(100 + i); + tr.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // Here create the TextView dynamically + TextView labelDATE = new TextView(DanaRStatsActivity.this); + labelDATE.setId(200 + i); + labelDATE.setText(df.format(new Date(record.recordDate))); + labelDATE.setTextColor(Color.WHITE); + tr.addView(labelDATE); + + TextView labelBASAL = new TextView(DanaRStatsActivity.this); + labelBASAL.setId(300 + i); + labelBASAL.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + " U"); + labelBASAL.setTextColor(Color.WHITE); + tr.addView(labelBASAL); + + TextView labelBOLUS = new TextView(DanaRStatsActivity.this); + labelBOLUS.setId(400 + i); + labelBOLUS.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + " U"); + labelBOLUS.setTextColor(Color.WHITE); + tr.addView(labelBOLUS); + + TextView labelTDD = new TextView(DanaRStatsActivity.this); + labelTDD.setId(500 + i); + labelTDD.setText(DecimalFormatter.to2Decimal(tdd) + " U"); + labelTDD.setTextColor(Color.WHITE); + tr.addView(labelTDD); + + TextView labelRATIO = new TextView(DanaRStatsActivity.this); + labelRATIO.setId(600 + i); + labelRATIO.setText(Math.round(100 * tdd / magicNumber) + " %"); + labelRATIO.setTextColor(Color.WHITE); + tr.addView(labelRATIO); + + // add stats rows to tables + tl.addView(tr, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + sum = sum + tdd; + i++; + + // Create the cumtable row + TableRow ctr = new TableRow(DanaRStatsActivity.this); + if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY); + ctr.setId(700 + i); + ctr.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // Here create the TextView dynamically + TextView labelDAYS = new TextView(DanaRStatsActivity.this); + labelDAYS.setId(800 + i); + labelDAYS.setText("" + i); + labelDAYS.setTextColor(Color.WHITE); + ctr.addView(labelDAYS); + + TextView labelCUMTDD = new TextView(DanaRStatsActivity.this); + labelCUMTDD.setId(900 + i); + labelCUMTDD.setText(DecimalFormatter.to2Decimal(sum / i) + " U"); + labelCUMTDD.setTextColor(Color.WHITE); + ctr.addView(labelCUMTDD); + + TextView labelCUMRATIO = new TextView(DanaRStatsActivity.this); + labelCUMRATIO.setId(1000 + i); + labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + " %"); + labelCUMRATIO.setTextColor(Color.WHITE); + ctr.addView(labelCUMRATIO); + + // add cummulative rows to tables + ctl.addView(ctr, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + } + + if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).recordDate)).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) { + statsMessage.setVisibility(View.VISIBLE); + statsMessage.setText(getString(R.string.danar_stats_olddata_Message)); + + } else { + tl.setBackgroundColor(Color.TRANSPARENT); + } + + Collections.reverse(historyList); + + i = 0; + + for (DanaRHistoryRecord record : historyList) { + double tdd = record.recordDailyBolus + record.recordDailyBasal; + if (i == 0) { + weighted03 = tdd; + weighted05 = tdd; + weighted07 = tdd; + + } else { + weighted07 = (weighted07 * 0.3 + tdd * 0.7); + weighted05 = (weighted05 * 0.5 + tdd * 0.5); + weighted03 = (weighted03 * 0.7 + tdd * 0.3); + } + i++; + } + + // Create the exptable row + TableRow etr = new TableRow(DanaRStatsActivity.this); + if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY); + etr.setId(1100 + i); + etr.setLayoutParams(new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + + // Here create the TextView dynamically + TextView labelWEIGHT = new TextView(DanaRStatsActivity.this); + labelWEIGHT.setId(1200 + i); + labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7"); + labelWEIGHT.setTextColor(Color.WHITE); + etr.addView(labelWEIGHT); + + TextView labelEXPTDD = new TextView(DanaRStatsActivity.this); + labelEXPTDD.setId(1300 + i); + labelEXPTDD.setText(DecimalFormatter.to2Decimal(weighted03) + + " U\n" + DecimalFormatter.to2Decimal(weighted05) + + " U\n" + DecimalFormatter.to2Decimal(weighted07) + " U"); + labelEXPTDD.setTextColor(Color.WHITE); + etr.addView(labelEXPTDD); + + TextView labelEXPRATIO = new TextView(DanaRStatsActivity.this); + labelEXPRATIO.setId(1400 + i); + labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + " %\n" + + Math.round(100 * weighted05 / magicNumber) + " %\n" + + Math.round(100 * weighted07 / magicNumber) + " %"); + labelEXPRATIO.setTextColor(Color.WHITE); + etr.addView(labelEXPRATIO); + + // add exponentail rows to tables + etl.addView(etr, new TableLayout.LayoutParams( + TableLayout.LayoutParams.MATCH_PARENT, + TableLayout.LayoutParams.WRAP_CONTENT)); + } + }); + } + + private void cleanTable(TableLayout table) { + int childCount = table.getChildCount(); + // Remove all rows except the first one + if (childCount > 1) { + table.removeViews(1, childCount - 1); + } + } + + @Subscribe + public void onStatusEvent(final EventDanaRSyncStatus s) { + log.debug("EventDanaRSyncStatus: " + s.message); + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(s.message); + } + }); + } + + @Subscribe + public void onStatusEvent(final EventPumpStatusChanged c) { + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(c.textStatus()); + } + } + ); + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java similarity index 97% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/SerialIOThread.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java index 9521c00fcc..461b353c3e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR; +package info.nightscout.androidaps.plugins.PumpDanaR; import android.bluetooth.BluetoothSocket; @@ -14,8 +14,8 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageHashTable; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageHashTable; import info.nightscout.utils.CRC; /** @@ -177,7 +177,7 @@ public class SerialIOThread extends Thread { if (!message.received) { log.warn("Reply not received " + message.getMessageName()); if (message.getCommand() == 0xF0F1) { - DanaRPlugin.getDanaRPump().isNewPump = false; + DanaRPump.getInstance().isNewPump = false; log.debug("Old firmware detected"); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageBase.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageBase.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java index 1d97a02ba1..943d4ee502 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageBase.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import android.annotation.TargetApi; import android.os.Build; @@ -47,10 +47,19 @@ public class MessageBase { AddParamByte((byte) (date.get(Calendar.YEAR) - 1900 - 100)); AddParamByte((byte) (date.get(Calendar.MONTH) + 1)); AddParamByte((byte) (date.get(Calendar.DAY_OF_MONTH))); - AddParamByte((byte) (date.get(Calendar.HOUR))); + AddParamByte((byte) (date.get(Calendar.HOUR_OF_DAY))); AddParamByte((byte) (date.get(Calendar.MINUTE))); } + public void AddParamDateTime(GregorianCalendar date) { + AddParamByte((byte) (date.get(Calendar.YEAR) - 1900 - 100)); + AddParamByte((byte) (date.get(Calendar.MONTH) + 1)); + AddParamByte((byte) (date.get(Calendar.DAY_OF_MONTH))); + AddParamByte((byte) (date.get(Calendar.HOUR_OF_DAY))); + AddParamByte((byte) (date.get(Calendar.MINUTE))); + AddParamByte((byte) (date.get(Calendar.SECOND))); + } + public void AddParamDateTime(Date date) { AddParamByte((byte) (date.getSeconds())); AddParamByte((byte) (date.getMinutes())); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java similarity index 98% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageHashTable.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java index 221f7855e9..debdd8a35f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageHashTable.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageOriginalNames.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageOriginalNames.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java index 5aba354812..3712945094 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MessageOriginalNames.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,10 +11,10 @@ import java.util.HashMap; public class MessageOriginalNames { private static Logger log = LoggerFactory.getLogger(MessageOriginalNames.class); - public static HashMap messageNames; + public static HashMap messageNames; static { - messageNames = new HashMap(); + messageNames = new HashMap<>(); messageNames.put(0x3001, "CMD_CONNECT"); messageNames.put(0x3002, "CMD_DISCONNECT"); @@ -150,8 +150,14 @@ public class MessageOriginalNames { messageNames.put(0xF0F3, "CMD_PUMP_TIMECHANGE_CLEAR"); messageNames.put(0x43F2, "CMD_HISTORY_DATEOVER_ALL"); messageNames.put(0x4300, "CMD_HISTORY_DATEOVER_DONE"); + + messageNames.put(0xE001, "CMD_PUMPSTATUS_APS"); + messageNames.put(0xE002, "CMD_PUMPSET_APSTEMP"); + messageNames.put(0xE003, "CMD_GET_HISTORY"); + messageNames.put(0xE004, "CMD_SET_HISTORY_ENTRY"); } + public static String getName(Integer command) { if (messageNames.containsKey(command)) return messageNames.get(command); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusProgress.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java index fe30fea1be..fd18407e5c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import com.squareup.otto.Bus; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java index 3ae5b97b69..0e6a3e814a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java index 68de53d50b..7040b84183 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import com.squareup.otto.Bus; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java similarity index 83% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgCheckValue.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java index 5e97e2c55e..c05029caff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,8 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.utils.ToastUtils; /** @@ -22,9 +22,9 @@ public class MsgCheckValue extends MessageBase { @Override public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); - DanaRPlugin.getDanaRPump().isNewPump = true; + pump.isNewPump = true; log.debug("New firmware confirmed"); pump.model = intFromBuff(bytes, 0, 1); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgError.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgError.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java index c416a8baad..b180d4107b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgError.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,6 +7,7 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; +import info.nightscout.utils.NSUpload; public class MsgError extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgError.class); @@ -48,7 +49,7 @@ public class MsgError extends MessageBase { } if (Config.logDanaMessageDetail) log.debug("Error detected: " + errorString); - MainApp.getConfigBuilder().uploadError(errorString); + NSUpload.uploadError(errorString); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAlarm.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAlarm.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAlarm.java index 1964a58fc9..24ea6d0f37 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAlarm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAlarm.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java similarity index 61% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java index c00f7f6c8e..4e4bc759f5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java @@ -1,16 +1,13 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; - -import com.j256.ormlite.dao.Dao; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.util.Date; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.db.DanaRHistoryRecord; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; import info.nightscout.utils.DateUtil; public class MsgHistoryAll extends MessageBase { @@ -39,82 +36,82 @@ public class MsgHistoryAll extends MessageBase { DanaRHistoryRecord danaRHistoryRecord = new DanaRHistoryRecord(); - danaRHistoryRecord.setRecordCode(recordCode); + danaRHistoryRecord.recordCode = recordCode; danaRHistoryRecord.setBytes(bytes); String messageType = ""; switch (recordCode) { case RecordTypes.RECORD_TYPE_BOLUS: - danaRHistoryRecord.setRecordDate(datetime); + danaRHistoryRecord.recordDate = datetime.getTime(); switch (0xF0 & paramByte8) { case 0xA0: - danaRHistoryRecord.setBolusType("DS"); + danaRHistoryRecord.bolusType = "DS"; messageType += "DS bolus"; break; case 0xC0: - danaRHistoryRecord.setBolusType("E"); + danaRHistoryRecord.bolusType = "E"; messageType += "E bolus"; break; case 0x80: - danaRHistoryRecord.setBolusType("S"); + danaRHistoryRecord.bolusType = "S"; messageType += "S bolus"; break; case 0x90: - danaRHistoryRecord.setBolusType("DE"); + danaRHistoryRecord.bolusType = "DE"; messageType += "DE bolus"; break; default: - danaRHistoryRecord.setBolusType("None"); + danaRHistoryRecord.bolusType = "None"; break; } - danaRHistoryRecord.setRecordDuration(((int) paramByte8 & 0x0F) * 60 + (int) paramByte7); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordDuration = ((int) paramByte8 & 0x0F) * 60 + (int) paramByte7; + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_DAILY: messageType += "dailyinsulin"; - danaRHistoryRecord.setRecordDate(date); - danaRHistoryRecord.setRecordDailyBasal(dailyBasal); - danaRHistoryRecord.setRecordDailyBolus(dailyBolus); + danaRHistoryRecord.recordDate = date.getTime(); + danaRHistoryRecord.recordDailyBasal = dailyBasal; + danaRHistoryRecord.recordDailyBolus = dailyBolus; break; case RecordTypes.RECORD_TYPE_PRIME: messageType += "prime"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_ERROR: messageType += "error"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_REFILL: messageType += "refill"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_BASALHOUR: messageType += "basal hour"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_TB: messageType += "tb"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_GLUCOSE: messageType += "glucose"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value; break; case RecordTypes.RECORD_TYPE_CARBO: messageType += "carbo"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); - danaRHistoryRecord.setRecordValue(value); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); + danaRHistoryRecord.recordValue = value; break; case RecordTypes.RECORD_TYPE_ALARM: messageType += "alarm"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); String strAlarm = "None"; switch ((int) paramByte8) { case 67: @@ -130,27 +127,22 @@ public class MsgHistoryAll extends MessageBase { strAlarm = "Shutdown"; break; } - danaRHistoryRecord.setRecordAlarm(strAlarm); - danaRHistoryRecord.setRecordValue(value * 0.01); + danaRHistoryRecord.recordAlarm = strAlarm; + danaRHistoryRecord.recordValue = value * 0.01; break; case RecordTypes.RECORD_TYPE_SUSPEND: messageType += "suspend"; - danaRHistoryRecord.setRecordDate(datetimewihtsec); + danaRHistoryRecord.recordDate = datetimewihtsec.getTime(); String strRecordValue = "Off"; if ((int) paramByte8 == 79) strRecordValue = "On"; - danaRHistoryRecord.setStringRecordValue(strRecordValue); + danaRHistoryRecord.stringRecordValue = strRecordValue; break; } - try { - Dao daoHistoryRecords = MainApp.getDbHelper().getDaoDanaRHistory(); - daoHistoryRecords.createIfNotExists(danaRHistoryRecord); - } catch (SQLException e) { - log.error(e.getMessage(), e); - } + MainApp.getDbHelper().createOrUpdate(danaRHistoryRecord); - ev.message = DateUtil.dateAndTimeString(danaRHistoryRecord.getRecordDate()); + ev.message = DateUtil.dateAndTimeString(danaRHistoryRecord.recordDate); ev.message += " " + messageType; MainApp.bus().post(ev); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAllDone.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAllDone.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAllDone.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAllDone.java index 1a839f5553..6ce3325715 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryAllDone.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAllDone.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryBasalHour.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBasalHour.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryBasalHour.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBasalHour.java index dee4de6a39..3fd97135f0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryBasalHour.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBasalHour.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBolus.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryBolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBolus.java index 97963955dd..b213ba52fd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryBolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryCarbo.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryCarbo.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryCarbo.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryCarbo.java index 26fe30c89f..115dc73e02 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryCarbo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryCarbo.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryDailyInsulin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDailyInsulin.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryDailyInsulin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDailyInsulin.java index 2d0e6969ea..77933c40da 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryDailyInsulin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDailyInsulin.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryDone.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDone.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryDone.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDone.java index b2fdcbeb61..04d3cb3faf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryDone.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryDone.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryError.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryError.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryError.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryError.java index 85443a271e..3358a88fea 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryError.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryError.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryGlucose.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryGlucose.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryGlucose.java index 903a402810..f07b91e9d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryGlucose.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryGlucose.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryNew.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNew.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryNew.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNew.java index 0bfe82fd30..5de685f65b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryNew.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNew.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryNewDone.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNewDone.java similarity index 91% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryNewDone.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNewDone.java index fb5de7515e..2cde92bf9a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryNewDone.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryNewDone.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryRefill.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryRefill.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryRefill.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryRefill.java index 6db3e972ff..daaed79023 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistoryRefill.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryRefill.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistorySuspend.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistorySuspend.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistorySuspend.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistorySuspend.java index a7a6c5ee04..db807a31b5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgHistorySuspend.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistorySuspend.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java index 6303391d4a..e7f6032c00 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java @@ -1,11 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgInitConnStatusBasic extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic.class); @@ -19,7 +18,7 @@ public class MsgInitConnStatusBasic extends MessageBase { if (bytes.length - 10 < 21) { return; } - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1; pump.calculatorEnabled = intFromBuff(bytes, 1, 1) == 1; pump.dailyTotalUnits = intFromBuff(bytes, 2, 3) / 750d; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusBolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java index 36705c49ec..b39929db5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,8 +6,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; @@ -27,7 +26,7 @@ public class MsgInitConnStatusBolus extends MessageBase { if (bytes.length - 10 > 12) { return; } - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); int bolusConfig = intFromBuff(bytes, 0, 1); pump.isExtendedBolusEnabled = (bolusConfig & 0x01) != 0; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusOption.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusOption.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java index 2b424a949b..560ed8b332 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusOption.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 28.05.2016. @@ -28,9 +28,9 @@ public class MsgInitConnStatusOption extends MessageBase { int lowReservoirAlarmBoundary = intFromBuff(bytes, 7, 1); //int none = intFromBuff(bytes, 8, 1); if (bytes.length >= 21) { - DanaRPlugin.getDanaRPump().password = intFromBuff(bytes, 9, 2) ^ 0x3463; + DanaRPump.getInstance().password = intFromBuff(bytes, 9, 2) ^ 0x3463; if (Config.logDanaMessageDetail) - log.debug("Pump password: " + DanaRPlugin.getDanaRPump().password); + log.debug("Pump password: " + DanaRPump.getInstance().password); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java similarity index 70% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java index d1d5652f4d..a27cfe07bf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,9 +10,9 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.utils.ToastUtils; public class MsgInitConnStatusTime extends MessageBase { @@ -28,10 +28,11 @@ public class MsgInitConnStatusTime extends MessageBase { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model"); log.debug("Wrong model selected. Switching to Korean DanaR"); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentVisible(PluginBase.PUMP, true); - ((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, false); - ((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, false); + DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PROFILE)){ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgPCCommStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStart.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgPCCommStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStart.java index 4e4cab19e5..619bbd9461 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgPCCommStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgPCCommStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStop.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgPCCommStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStop.java index f5e3ce9b1f..20dd4e060f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgPCCommStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgPCCommStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetActivateBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetActivateBasalProfile.java similarity index 94% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetActivateBasalProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetActivateBasalProfile.java index 9357a05aef..64ed0488a4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetActivateBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetActivateBasalProfile.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetBasalProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java index 9acd5ec824..dea2734a3e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetBasalProfile.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetCarbsEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java similarity index 56% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetCarbsEntry.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java index ed3e3ac455..4fcd6dee9c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetCarbsEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,20 +14,21 @@ public class MsgSetCarbsEntry extends MessageBase { SetCommand(0x0402); } - public MsgSetCarbsEntry(Calendar time, int amount) { + public MsgSetCarbsEntry(long time, int amount) { this(); - + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(time); AddParamByte((byte) RecordTypes.RECORD_TYPE_CARBO); - AddParamByte((byte) (time.get(Calendar.YEAR) % 100)); - AddParamByte((byte) (time.get(Calendar.MONTH) + 1)); - AddParamByte((byte) (time.get(Calendar.DAY_OF_MONTH))); - AddParamByte((byte) (time.get(Calendar.HOUR_OF_DAY))); - AddParamByte((byte) (time.get(Calendar.MINUTE))); - AddParamByte((byte) (time.get(Calendar.SECOND))); + AddParamByte((byte) (calendar.get(Calendar.YEAR) % 100)); + AddParamByte((byte) (calendar.get(Calendar.MONTH) + 1)); + AddParamByte((byte) (calendar.get(Calendar.DAY_OF_MONTH))); + AddParamByte((byte) (calendar.get(Calendar.HOUR_OF_DAY))); + AddParamByte((byte) (calendar.get(Calendar.MINUTE))); + AddParamByte((byte) (calendar.get(Calendar.SECOND))); AddParamByte((byte) 0x43); //?? AddParamInt(amount); if (Config.logDanaMessageDetail) - log.debug("Set carb entry: " + amount + " date " + time.getTime().toString()); + log.debug("Set carb entry: " + amount + " date " + calendar.getTime().toString()); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetExtendedBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetExtendedBolusStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java index 9c37fda333..484078825e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetExtendedBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetExtendedBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStop.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetExtendedBolusStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStop.java index 49933fc004..7084949daa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetExtendedBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetSingleBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java similarity index 96% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetSingleBasalProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java index 4e57712b04..32cd3745d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetSingleBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import com.j256.ormlite.stmt.query.Not; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTempBasalStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStart.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTempBasalStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStart.java index 29ab838b37..2b72c35749 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTempBasalStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTempBasalStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStop.java similarity index 92% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTempBasalStop.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStop.java index 02d095c679..39582ac399 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTempBasalStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTempBasalStop.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java index 827958608c..aa15a02709 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSetTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingActiveProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java similarity index 61% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingActiveProfile.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java index 723b4efbbf..20498e28e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingActiveProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java @@ -1,10 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 05.07.2016. @@ -17,9 +17,9 @@ public class MsgSettingActiveProfile extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().activeProfile = intFromBuff(bytes, 0, 1); + DanaRPump.getInstance().activeProfile = intFromBuff(bytes, 0, 1); if (Config.logDanaMessageDetail) - log.debug("Active profile number: " + DanaRPlugin.getDanaRPump().activeProfile); + log.debug("Active profile number: " + DanaRPump.getInstance().activeProfile); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java similarity index 74% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingBasal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java index 319fe787f3..e1a7e45315 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java @@ -1,11 +1,11 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 05.07.2016. @@ -18,7 +18,7 @@ public class MsgSettingBasal extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][]; pump.pumpProfiles[pump.activeProfile] = new double[24]; for (int index = 0; index < 24; index++) { @@ -29,7 +29,7 @@ public class MsgSettingBasal extends MessageBase { if (Config.logDanaMessageDetail) for (int index = 0; index < 24; index++) { - log.debug("Basal " + String.format("%02d", index) + "h: " + DanaRPlugin.getDanaRPump().pumpProfiles[DanaRPlugin.getDanaRPump().activeProfile][index]); + log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingBasalProfileAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java similarity index 81% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingBasalProfileAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java index 4dc9137a4f..24b5043769 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingBasalProfileAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java @@ -1,11 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -22,8 +21,8 @@ public class MsgSettingBasalProfileAll extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); - if (DanaRPlugin.getDanaRPump().basal48Enable) { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.basal48Enable) { pump.pumpProfiles = new double[4][]; for (int profile = 0; profile < 4; profile++) { int position = intFromBuff(bytes, 107 * profile, 1); @@ -50,10 +49,10 @@ public class MsgSettingBasalProfileAll extends MessageBase { } if (Config.logDanaMessageDetail) { - if (DanaRPlugin.getDanaRPump().basal48Enable) { + if (pump.basal48Enable) { for (int profile = 0; profile < 4; profile++) { for (int index = 0; index < 24; index++) { - log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + DanaRPlugin.getDanaRPump().pumpProfiles[profile][index]); + log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profile][index]); } } } else { @@ -62,7 +61,7 @@ public class MsgSettingBasalProfileAll extends MessageBase { log.debug("Basal profile " + profile + ": " + String.format("%02d", (index / 2)) + ":" + String.format("%02d", (index % 2) * 30) + " : " + - DanaRPlugin.getDanaRPump().pumpProfiles[profile][index]); + pump.pumpProfiles[profile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java new file mode 100644 index 0000000000..0f20c0843a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingGlucose.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +/** + * Created by mike on 05.07.2016. + */ +public class MsgSettingGlucose extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSettingGlucose.class); + + public MsgSettingGlucose() { + SetCommand(0x3209); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + pump.units = intFromBuff(bytes, 0, 1); + pump.easyBasalMode = intFromBuff(bytes, 1, 1); + + if (Config.logDanaMessageDetail) { + log.debug("Pump units: " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Easy basal mode: " + pump.easyBasalMode); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java new file mode 100644 index 0000000000..9279f2b1ba --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMaxValues.java @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + + +/** + * Created by mike on 05.07.2016. + */ +public class MsgSettingMaxValues extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSettingMaxValues.class); + + public MsgSettingMaxValues() { + SetCommand(0x3205); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + pump.maxBolus = intFromBuff(bytes, 0, 2) / 100d; + pump.maxBasal = intFromBuff(bytes, 2, 2) / 100d; + pump.maxDailyTotalUnits = intFromBuff(bytes, 4, 2) / 100; + + if (Config.logDanaMessageDetail) { + log.debug("Max bolus: " + pump.maxBolus); + log.debug("Max basal: " + pump.maxBasal); + log.debug("Total daily max units: " + pump.maxDailyTotalUnits); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java similarity index 79% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingMeal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java index 488cf3becf..4ed5de2920 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingMeal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,14 +6,10 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 13.12.2016. @@ -27,7 +23,7 @@ public class MsgSettingMeal extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.basalStep = intFromBuff(bytes, 0, 1) / 100d; pump.bolusStep = intFromBuff(bytes, 1, 1) / 100d; boolean bolusEnabled = intFromBuff(bytes, 2, 1) == 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java new file mode 100644 index 0000000000..0b5150fc84 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatios.java @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +/** + * Created by mike on 05.07.2016. + */ +public class MsgSettingProfileRatios extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatios.class); + + public MsgSettingProfileRatios() { + SetCommand(0x3204); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.units == DanaRPump.UNITS_MGDL) { + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2); + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2); + pump.currentAIDR = intFromBuff(bytes, 8, 1); + } else { + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2) / 100d; + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2) / 100d; + pump.currentAIDR = intFromBuff(bytes, 8, 1); + } + + if (Config.logDanaMessageDetail) { + log.debug("Pump units (saved): " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Current pump CIR: " + pump.currentCIR); + log.debug("Current pump CF: " + pump.currentCF); + log.debug("Current pump AI: " + pump.currentAI); + log.debug("Current pump target: " + pump.currentTarget); + log.debug("Current pump AIDR: " + pump.currentAIDR); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java new file mode 100644 index 0000000000..9dd5a0070d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingProfileRatiosAll.java @@ -0,0 +1,55 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +/** + * Created by mike on 05.07.2016. + */ +public class MsgSettingProfileRatiosAll extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatiosAll.class); + + public MsgSettingProfileRatiosAll() { + SetCommand(0x320D); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.units == DanaRPump.UNITS_MGDL) { + pump.morningCIR = intFromBuff(bytes, 0, 2); + pump.morningCF = intFromBuff(bytes, 2, 2); + pump.afternoonCIR = intFromBuff(bytes, 4, 2); + pump.afternoonCF = intFromBuff(bytes, 6, 2); + pump.eveningCIR = intFromBuff(bytes, 8, 2); + pump.eveningCF = intFromBuff(bytes, 10, 2); + pump.nightCIR = intFromBuff(bytes, 12, 2); + pump.nightCF = intFromBuff(bytes, 14, 2); + } else { + pump.morningCIR = intFromBuff(bytes, 0, 2); + pump.morningCF = intFromBuff(bytes, 2, 2) / 100d; + pump.afternoonCIR = intFromBuff(bytes, 4, 2); + pump.afternoonCF = intFromBuff(bytes, 6, 2) / 100d; + pump.eveningCIR = intFromBuff(bytes, 8, 2); + pump.eveningCF = intFromBuff(bytes, 10, 2) / 100d; + pump.nightCIR = intFromBuff(bytes, 12, 2); + pump.nightCF = intFromBuff(bytes, 14, 2) / 100d; + } + + if (Config.logDanaMessageDetail) { + log.debug("Pump units: " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Current pump morning CIR: " + pump.morningCIR); + log.debug("Current pump morning CF: " + pump.morningCF); + log.debug("Current pump afternoon CIR: " + pump.afternoonCIR); + log.debug("Current pump afternoon CF: " + pump.afternoonCF); + log.debug("Current pump evening CIR: " + pump.eveningCIR); + log.debug("Current pump evening CF: " + pump.eveningCF); + log.debug("Current pump night CIR: " + pump.nightCIR); + log.debug("Current pump night CF: " + pump.nightCF); + } + + pump.createConvertedProfile(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java similarity index 83% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingPumpTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java index e0d81a9614..23f0e4560f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingPumpTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgSettingPumpTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class); @@ -29,6 +29,6 @@ public class MsgSettingPumpTime extends MessageBase { if (Config.logDanaMessageDetail) log.debug("Pump time: " + time); - DanaRPlugin.getDanaRPump().pumpTime = time; + DanaRPump.getInstance().pumpTime = time; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingShippingInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java similarity index 76% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingShippingInfo.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java index faa68c5eb7..9670d92a88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingShippingInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java @@ -1,13 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** * Created by mike on 05.07.2016. @@ -20,7 +17,7 @@ public class MsgSettingShippingInfo extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.serialNumber = stringFromBuff(bytes, 0, 10); pump.shippingDate = dateFromBuff(bytes, 10); pump.shippingCountry = asciiStringFromBuff(bytes, 13, 3); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingUserOptions.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingUserOptions.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingUserOptions.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingUserOptions.java index d1e0e9471b..8fb1e4f712 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgSettingUserOptions.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingUserOptions.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java new file mode 100644 index 0000000000..fb75bfef0e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java @@ -0,0 +1,39 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +public class MsgStatus extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatus.class); + + public MsgStatus() { + SetCommand(0x020B); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + pump.dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d; + pump.isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1; + pump.extendedBolusMinutes = intFromBuff(bytes, 4, 2); + pump.extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d; + Double lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d; + if (lastBolusAmount != 0d) { + pump.lastBolusTime = dateTimeFromBuff(bytes, 8); + pump.lastBolusAmount = lastBolusAmount; + } + pump.iob = intFromBuff(bytes, 15, 2) / 100d; + + if (Config.logDanaMessageDetail) { + log.debug("Daily total: " + pump.dailyTotalUnits); + log.debug("Is extended bolus running: " + pump.isExtendedInProgress); + log.debug("Extended bolus min: " + pump.extendedBolusMinutes); + log.debug("Extended bolus amount: " + pump.extendedBolusAmount); + log.debug("Last bolus time: " + pump.lastBolusTime); + log.debug("Last bolus amount: " + pump.lastBolusAmount); + log.debug("IOB: " + pump.iob); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java similarity index 88% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java index d79dd6aea8..ba8374f383 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/MsgStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java @@ -1,11 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgStatusBasic extends MessageBase { @@ -16,7 +15,7 @@ public class MsgStatusBasic extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1; pump.calculatorEnabled = intFromBuff(bytes, 1, 1) == 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java new file mode 100644 index 0000000000..9d9ccde307 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBolusExtended.java @@ -0,0 +1,106 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import android.support.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +public class MsgStatusBolusExtended extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended.class); + + public MsgStatusBolusExtended() { + SetCommand(0x0207); + } + + public void handleMessage(byte[] bytes) { + boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1; + int extendedBolusHalfHours = intFromBuff(bytes, 1, 1); + int extendedBolusMinutes = extendedBolusHalfHours * 30; + + double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d; + int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3); +// This is available only on korean, but not needed now +// int extendedBolusDeliveryPulse = intFromBuff(bytes, 7, 2); +// int isEasyUIUserSleep = intFromBuff(bytes, 9, 1); + + int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60; + double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d; + Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0); + int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes; + + DanaRPump pump = DanaRPump.getInstance(); + pump.isExtendedInProgress = isExtendedInProgress; + pump.extendedBolusMinutes = extendedBolusMinutes; + pump.extendedBolusAmount = extendedBolusAmount; + pump.extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; + pump.extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; + pump.extendedBolusStart = extendedBolusStart; + pump.extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; + + updateExtendedBolusInDB(); + + if (Config.logDanaMessageDetail) { + log.debug("Is extended bolus running: " + isExtendedInProgress); + log.debug("Extended bolus min: " + extendedBolusMinutes); + log.debug("Extended bolus amount: " + extendedBolusAmount); + log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes); + log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate); + log.debug("Extended bolus start: " + extendedBolusStart); + log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes); + } + } + + @NonNull + private Date getDateFromSecAgo(int tempBasalAgoSecs) { + return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + } + + public static void updateExtendedBolusInDB() { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + DanaRPump pump = DanaRPump.getInstance(); + long now = new Date().getTime(); + + if (treatmentsInterface.isInHistoryExtendedBoluslInProgress()) { + ExtendedBolus extendedBolus = treatmentsInterface.getExtendedBolusFromHistory(new Date().getTime()); + if (pump.isExtendedInProgress) { + if (extendedBolus.absoluteRate() != pump.extendedBolusAbsoluteRate) { + // Close current extended + ExtendedBolus exStop = new ExtendedBolus(pump.extendedBolusStart.getTime() - 1000); + exStop.source = Source.USER; + treatmentsInterface.addToHistoryExtendedBolus(exStop); + // Create new + ExtendedBolus newExtended = new ExtendedBolus(); + newExtended.date = pump.extendedBolusStart.getTime(); + newExtended.insulin = pump.extendedBolusAmount; + newExtended.durationInMinutes = pump.extendedBolusMinutes; + newExtended.source = Source.USER; + treatmentsInterface.addToHistoryExtendedBolus(newExtended); + } + } else { + // Close curent temp basal + ExtendedBolus exStop = new ExtendedBolus(now); + exStop.source = Source.USER; + treatmentsInterface.addToHistoryExtendedBolus(exStop); + } + } else { + if (pump.isExtendedInProgress) { + // Create new + ExtendedBolus newExtended = new ExtendedBolus(); + newExtended.date = pump.extendedBolusStart.getTime(); + newExtended.insulin = pump.extendedBolusAmount; + newExtended.durationInMinutes = pump.extendedBolusMinutes; + newExtended.source = Source.USER; + treatmentsInterface.addToHistoryExtendedBolus(newExtended); + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java new file mode 100644 index 0000000000..70b67c3b77 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusProfile.java @@ -0,0 +1,42 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +/** + * Created by mike on 05.07.2016. + */ +public class MsgStatusProfile extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusProfile.class); + + public MsgStatusProfile() { + SetCommand(0x0204); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.units == DanaRPump.UNITS_MGDL) { + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2); + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2); + } else { + pump.currentCIR = intFromBuff(bytes, 0, 2); + pump.currentCF = intFromBuff(bytes, 2, 2) / 100d; + pump.currentAI = intFromBuff(bytes, 4, 2) / 100d; + pump.currentTarget = intFromBuff(bytes, 6, 2) / 100d; + } + + if (Config.logDanaMessageDetail) { + log.debug("Pump units (saved): " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL")); + log.debug("Current pump CIR: " + pump.currentCIR); + log.debug("Current pump CF: " + pump.currentCF); + log.debug("Current pump AI: " + pump.currentAI); + log.debug("Current pump target: " + pump.currentTarget); + log.debug("Current pump AIDR: " + pump.currentAIDR); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java new file mode 100644 index 0000000000..bcfd56a8fe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusTempBasal.java @@ -0,0 +1,102 @@ +package info.nightscout.androidaps.plugins.PumpDanaR.comm; + +import android.support.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; + +public class MsgStatusTempBasal extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal.class); + + public MsgStatusTempBasal() { + SetCommand(0x0205); + } + + public void handleMessage(byte[] bytes) { + boolean isTempBasalInProgress = (intFromBuff(bytes, 0, 1) & 0x01) == 0x01; + boolean isAPSTempBasalInProgress = (intFromBuff(bytes, 0, 1) & 0x02) == 0x02; + int tempBasalPercent = intFromBuff(bytes, 1, 1); + if (tempBasalPercent > 200) tempBasalPercent = (tempBasalPercent - 200) * 10; + int tempBasalTotalSec; + if (intFromBuff(bytes, 2, 1) == 150) tempBasalTotalSec = 15 * 60; + else if (intFromBuff(bytes, 2, 1) == 160) tempBasalTotalSec = 30 * 60; + else tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60; + int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3); + int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60; + Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0); + + DanaRPump pump = DanaRPump.getInstance(); + pump.isTempBasalInProgress = isTempBasalInProgress; + pump.tempBasalPercent = tempBasalPercent; + pump.tempBasalRemainingMin = tempBasalRemainingMin; + pump.tempBasalTotalSec = tempBasalTotalSec; + pump.tempBasalStart = tempBasalStart; + + updateTempBasalInDB(); + + if (Config.logDanaMessageDetail) { + log.debug("Is temp basal running: " + isTempBasalInProgress); + log.debug("Is APS temp basal running: " + isAPSTempBasalInProgress); + log.debug("Current temp basal percent: " + tempBasalPercent); + log.debug("Current temp basal remaining min: " + tempBasalRemainingMin); + log.debug("Current temp basal total sec: " + tempBasalTotalSec); + log.debug("Current temp basal start: " + tempBasalStart); + } + } + + @NonNull + private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) { + return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + } + + public static void updateTempBasalInDB() { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + DanaRPump danaRPump = DanaRPump.getInstance(); + long now = new Date().getTime(); + + if (treatmentsInterface.isInHistoryRealTempBasalInProgress()) { + TemporaryBasal tempBasal = treatmentsInterface.getRealTempBasalFromHistory(new Date().getTime()); + if (danaRPump.isTempBasalInProgress) { + if (tempBasal.percentRate != danaRPump.tempBasalPercent) { + // Close current temp basal + TemporaryBasal tempStop = new TemporaryBasal(danaRPump.tempBasalStart.getTime() - 1000); + tempStop.source = Source.USER; + treatmentsInterface.addToHistoryTempBasal(tempStop); + // Create new + TemporaryBasal newTempBasal = new TemporaryBasal(); + newTempBasal.date = danaRPump.tempBasalStart.getTime(); + newTempBasal.percentRate = danaRPump.tempBasalPercent; + newTempBasal.isAbsolute = false; + newTempBasal.durationInMinutes = danaRPump.tempBasalTotalSec / 60; + newTempBasal.source = Source.USER; + treatmentsInterface.addToHistoryTempBasal(newTempBasal); + } + } else { + // Close current temp basal + TemporaryBasal tempStop = new TemporaryBasal(now); + tempStop.source = Source.USER; + treatmentsInterface.addToHistoryTempBasal(tempStop); + } + } else { + if (danaRPump.isTempBasalInProgress) { + // Create new + TemporaryBasal newTempBasal = new TemporaryBasal(); + newTempBasal.date = danaRPump.tempBasalStart.getTime(); + newTempBasal.percentRate = danaRPump.tempBasalPercent; + newTempBasal.isAbsolute = false; + newTempBasal.durationInMinutes = danaRPump.tempBasalTotalSec / 60; + newTempBasal.source = Source.USER; + treatmentsInterface.addToHistoryTempBasal(newTempBasal); + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/RecordTypes.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/RecordTypes.java similarity index 93% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/RecordTypes.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/RecordTypes.java index 9d6b2e4d64..f0de05810a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/comm/RecordTypes.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/RecordTypes.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.comm; +package info.nightscout.androidaps.plugins.PumpDanaR.comm; /** * Created by mike on 28.05.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java similarity index 57% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRBolusStart.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java index 0be3cfb770..8217b51432 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRBolusStart.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.events; +package info.nightscout.androidaps.plugins.PumpDanaR.events; /** * Created by mike on 03.08.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRNewStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java similarity index 56% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRNewStatus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java index af57fabf8d..a04f27f2d6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRNewStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRNewStatus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.events; +package info.nightscout.androidaps.plugins.PumpDanaR.events; /** * Created by mike on 08.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRSyncStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java similarity index 79% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRSyncStatus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java index 628fdb5aab..b64cf22748 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/events/EventDanaRSyncStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/events/EventDanaRSyncStatus.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.events; +package info.nightscout.androidaps.plugins.PumpDanaR.events; /** * Created by mike on 20.07.2016. diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/Services/ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java similarity index 77% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/Services/ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java index 37ff192c9d..957819aaf9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/Services/ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.Services; +package info.nightscout.androidaps.plugins.PumpDanaR.services; import android.app.Service; import android.bluetooth.BluetoothAdapter; @@ -8,11 +8,9 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.SharedPreferences; import android.os.Binder; import android.os.IBinder; import android.os.PowerManager; -import android.preference.PreferenceManager; import com.squareup.otto.Subscribe; @@ -20,7 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.util.Calendar; import java.util.Date; import java.util.Set; import java.util.UUID; @@ -35,59 +32,59 @@ import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.DanaRPump; -import info.nightscout.androidaps.plugins.DanaR.SerialIOThread; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgCheckValue; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAlarm; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBasalHour; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBolus; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryCarbo; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDailyInsulin; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDone; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryError; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryGlucose; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryRefill; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistorySuspend; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetActivateBasalProfile; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetBasalProfile; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetCarbsEntry; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTime; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingActiveProfile; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingBasal; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingMeal; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingGlucose; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingMaxValues; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingProfileRatios; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingProfileRatiosAll; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingPumpTime; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSettingShippingInfo; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatus; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatusBasic; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatusBolusExtended; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgStatusTempBasal; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusStart; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.data.Profile; +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; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetActivateBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetBasalProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; +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.MsgSettingActiveProfile; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingBasal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; +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.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.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; -public class ExecutionService extends Service { - private static Logger log = LoggerFactory.getLogger(ExecutionService.class); +public class DanaRExecutionService extends Service { + private static Logger log = LoggerFactory.getLogger(DanaRExecutionService.class); private String devName; @@ -98,7 +95,7 @@ public class ExecutionService extends Service { private PowerManager.WakeLock mWakeLock; private IBinder mBinder = new LocalBinder(); - private DanaRPump danaRPump; + private DanaRPump danaRPump = DanaRPump.getInstance(); private Treatment bolusingTreatment = null; private static Boolean connectionInProgress = false; @@ -123,18 +120,17 @@ public class ExecutionService extends Service { } }; - public ExecutionService() { + public DanaRExecutionService() { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); - danaRPump = DanaRPlugin.getDanaRPump(); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExecutionService"); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRExecutionService"); } public class LocalBinder extends Binder { - public ExecutionService getServiceInstance() { - return ExecutionService.this; + public DanaRExecutionService getServiceInstance() { + return DanaRExecutionService.this; } } @@ -341,12 +337,12 @@ public class ExecutionService extends Service { danaRPump.lastConnection = now; MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); - MainApp.getConfigBuilder().uploadDeviceStatus(); + 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.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); - MainApp.getConfigBuilder().uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); + NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); } } catch (Exception e) { e.printStackTrace(); @@ -394,7 +390,7 @@ public class ExecutionService extends Service { return true; } - public boolean bolus(Double amount, int carbs, Treatment t) { + public boolean bolus(double amount, int carbs, Treatment t) { bolusingTreatment = t; MsgBolusStart start = new MsgBolusStart(amount); MsgBolusStop stop = new MsgBolusStop(amount, t); @@ -403,11 +399,12 @@ public class ExecutionService extends Service { if (!isConnected()) return false; if (carbs > 0) { - Calendar time = Calendar.getInstance(); - mSerialIOThread.sendMessage(new MsgSetCarbsEntry(time, carbs)); + mSerialIOThread.sendMessage(new MsgSetCarbsEntry(new Date().getTime(), carbs)); } + MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables MainApp.bus().post(new EventDanaRBolusStart()); + long startTime = new Date().getTime(); if (!stop.stopped) { mSerialIOThread.sendMessage(start); @@ -425,7 +422,23 @@ public class ExecutionService extends Service { } waitMsec(300); bolusingTreatment = null; - getPumpStatus(); + // try to find real amount if bolusing was interrupted or comm failed + if (t.insulin != amount) { + disconnect("bolusingInterrupted"); + long now = new Date().getTime(); + long estimatedBolusEnd = (long) (startTime + amount / 5d * 60 * 1000); // std delivery rate 5 U/min + waitMsec(Math.max(5000, estimatedBolusEnd - now + 3000)); + connect("bolusingInterrupted"); + getPumpStatus(); + if (danaRPump.lastBolusTime.getTime() > now - 60 * 1000L) { // last bolus max 1 min old + t.insulin = danaRPump.lastBolusAmount; + log.debug("Used bolus amount from history: " + danaRPump.lastBolusAmount); + } else { + log.debug("Bolus amount in history too old: " + danaRPump.lastBolusTime.toLocaleString()); + } + } else { + getPumpStatus(); + } return true; } @@ -448,8 +461,7 @@ public class ExecutionService extends Service { public boolean carbsEntry(int amount) { connect("carbsEntry"); if (!isConnected()) return false; - Calendar time = Calendar.getInstance(); - MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount); + MsgSetCarbsEntry msg = new MsgSetCarbsEntry(new Date().getTime(), amount); mSerialIOThread.sendMessage(msg); return true; } @@ -499,7 +511,7 @@ public class ExecutionService extends Service { return true; } - public boolean updateBasalsInPump(final NSProfile profile) { + public boolean updateBasalsInPump(final Profile profile) { connect("updateBasalsInPump"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); @@ -514,10 +526,12 @@ public class ExecutionService extends Service { return true; } - private double[] buildDanaRProfileRecord(NSProfile nsProfile) { + private double[] buildDanaRProfileRecord(Profile nsProfile) { double[] record = new double[24]; for (Integer hour = 0; hour < 24; hour++) { - double value = nsProfile.getBasal(hour * 60 * 60); + //Some values get truncated to the next lower one. + // -> round them to two decimals and make sure we are a small delta larger (that will get truncated) + double value = Math.round(100d * nsProfile.getBasal(hour * 60 * 60))/100d + 0.00001; if (Config.logDanaMessageDetail) log.debug("NS basal value for " + hour + ":00 is " + value); record[hour] = value; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanFragment.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanFragment.java index af4d12e5ef..5a3a5a4f36 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean; +package info.nightscout.androidaps.plugins.PumpDanaRKorean; import android.annotation.SuppressLint; @@ -24,18 +24,19 @@ import java.util.Date; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.DanaR.Dialogs.ProfileViewDialog; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.DanaRKorean.History.DanaRHistoryActivity; -import info.nightscout.androidaps.plugins.DanaRKorean.History.DanaRStatsActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.History.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.History.DanaRStatsActivity; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SetWarnColor; -public class DanaRKoreanFragment extends Fragment implements FragmentBase { +public class DanaRKoreanFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(DanaRKoreanFragment.class); private static DanaRKoreanPlugin danaRKoreanPlugin = new DanaRKoreanPlugin(); @@ -61,6 +62,8 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase { TextView reservoirView; TextView iobView; TextView firmwareView; + TextView basalStepView; + TextView bolusStepView; Button viewProfileButton; Button historyButton; Button statsButton; @@ -107,6 +110,8 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase { viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile); historyButton = (Button) view.findViewById(R.id.danar_history); statsButton = (Button) view.findViewById(R.id.danar_stats); + basalStepView = (TextView) view.findViewById(R.id.danar_basalstep); + bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep); viewProfileButton.setOnClickListener(new View.OnClickListener() { @@ -191,6 +196,11 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase { updateGUI(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange s) { + updateGUI(); + } + // GUI functions private void updateGUI() { @@ -200,7 +210,7 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase { @SuppressLint("SetTextI18n") @Override public void run() { - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); if (pump.lastConnection.getTime() != 0) { Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); int agoMin = (int) (agoMsec / 60d / 1000d); @@ -218,13 +228,13 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase { 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(danaRKoreanPlugin.getBaseBasalRate()) + " U/h"); - if (danaRKoreanPlugin.isRealTempBasalInProgress()) { - tempBasalView.setText(danaRKoreanPlugin.getRealTempBasal().toString()); + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { + tempBasalView.setText(MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()).toStringFull()); } else { tempBasalView.setText(""); } - if (danaRKoreanPlugin.isExtendedBoluslInProgress()) { - extendedBolusView.setText(danaRKoreanPlugin.getExtendedBolus().toString()); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).toString()); } else { extendedBolusView.setText(""); } @@ -238,6 +248,8 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase { } else { firmwareView.setText("OLD"); } + basalStepView.setText("" + pump.basalStep); + bolusStepView.setText("" + pump.bolusStep); } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java similarity index 69% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index 11debc415a..45330dc6d7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -1,12 +1,10 @@ -package info.nightscout.androidaps.plugins.DanaRKorean; +package info.nightscout.androidaps.plugins.PumpDanaRKorean; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.os.IBinder; -import android.preference.PreferenceManager; import android.support.annotation.Nullable; import com.squareup.otto.Subscribe; @@ -24,8 +22,10 @@ import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -35,15 +35,18 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService; -import info.nightscout.androidaps.plugins.NSProfile.NSProfilePlugin; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; +import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. @@ -56,52 +59,45 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints return DanaRKoreanFragment.class.getName(); } - static boolean fragmentPumpEnabled = true; - static boolean fragmentProfileEnabled = true; + static boolean fragmentPumpEnabled = false; + static boolean fragmentProfileEnabled = false; static boolean fragmentPumpVisible = true; - public static ExecutionService sExecutionService; + public static DanaRKoreanExecutionService sExecutionService; - private static DanaRKoreanPump sDanaRKoreanPump = new DanaRKoreanPump(); + private static DanaRPump pump = DanaRPump.getInstance(); private static boolean useExtendedBoluses = false; public static PumpDescription pumpDescription = new PumpDescription(); - public static DanaRKoreanPump getDanaRPump() { - return sDanaRKoreanPump; - } - String textStatus = ""; public DanaRKoreanPlugin() { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); + useExtendedBoluses = SP.getBoolean("danar_useextended", false); Context context = MainApp.instance().getApplicationContext(); - Intent intent = new Intent(context, ExecutionService.class); + Intent intent = new Intent(context, DanaRKoreanExecutionService.class); context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); MainApp.bus().register(this); - pumpDescription.isBolusCapable = true; // TODO: use description in setTempBasalAbsolute + pumpDescription.isBolusCapable = true; pumpDescription.bolusStep = 0.1d; pumpDescription.isExtendedBolusCapable = true; - pumpDescription.extendedBolusStep = 0.05d; + pumpDescription.extendedBolusStep = 0.1d; + pumpDescription.extendedBolusDurationStep = 30; + pumpDescription.extendedBolusMaxDuration = 8 * 60; pumpDescription.isTempBasalCapable = true; - pumpDescription.lowTempBasalStyle = PumpDescription.PERCENT; - pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT; - pumpDescription.maxHighTempPercent = 200; - pumpDescription.maxHighTempAbsolute = 0; - pumpDescription.lowTempPercentStep = 10; - pumpDescription.lowTempAbsoluteStep = 0; - pumpDescription.lowTempPercentDuration = 60; - pumpDescription.lowTempAbsoluteDuration = 60; - pumpDescription.highTempPercentStep = 10; - pumpDescription.highTempAbsoluteStep = 0.05d; - pumpDescription.highTempPercentDuration = 60; - pumpDescription.highTempAbsoluteDuration = 30; + pumpDescription.tempBasalStyle = PumpDescription.PERCENT; + + pumpDescription.maxTempPercent = 200; + pumpDescription.tempPercentStep = 10; + + pumpDescription.tempDurationStep = 60; + pumpDescription.tempMaxDuration = 24 * 60; + pumpDescription.isSetBasalProfileCapable = true; pumpDescription.basalStep = 0.01d; @@ -119,7 +115,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service; sExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -134,12 +130,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints public void onStatusEvent(final EventPreferenceChange s) { if (isEnabled(PUMP)) { boolean previousValue = useExtendedBoluses; - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); + useExtendedBoluses = SP.getBoolean("danar_useextended", false); - pumpDescription.highTempBasalStyle = useExtendedBoluses ? PumpDescription.EXTENDED : PumpDescription.PERCENT; - - if (useExtendedBoluses != previousValue && isExtendedBoluslInProgress()) { + if (useExtendedBoluses != previousValue && MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { sExecutionService.extendedBolusStop(); } } @@ -159,7 +152,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.danarpump_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -187,6 +180,16 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return type == PUMP; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PluginBase.PROFILE) @@ -208,14 +211,19 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints this.fragmentPumpVisible = fragmentVisible; } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return useExtendedBoluses; + } + @Override public boolean isInitialized() { - return getDanaRPump().lastConnection.getTime() > 0 && !getDanaRPump().isConfigUD && !getDanaRPump().isEasyModeEnabled && getDanaRPump().isExtendedBolusEnabled; + return pump.lastConnection.getTime() > 0 && !pump.isConfigUD && !pump.isEasyModeEnabled && pump.isExtendedBolusEnabled; } @Override public boolean isSuspended() { - return getDanaRPump().pumpSuspended; + return pump.pumpSuspended; } @Override @@ -226,23 +234,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints // Pump interface @Override - public boolean isTempBasalInProgress() { - if (getRealTempBasal() != null) return true; - if (getExtendedBolus() != null && useExtendedBoluses) return true; - return false; - } - - public boolean isRealTempBasalInProgress() { - return getRealTempBasal() != null; //TODO: crosscheck here - } - - @Override - public boolean isExtendedBoluslInProgress() { - return getExtendedBolus() != null; //TODO: crosscheck here - } - - @Override - public int setNewBasalProfile(NSProfile profile) { + public int setNewBasalProfile(Profile profile) { if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); return FAILED; @@ -267,10 +259,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints } @Override - public boolean isThisProfileSet(NSProfile profile) { + public boolean isThisProfileSet(Profile profile) { if (!isInitialized()) return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS - DanaRKoreanPump pump = getDanaRPump(); if (pump.pumpProfiles == null) return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS int basalValues = pump.basal48Enable ? 48 : 24; @@ -278,6 +269,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints for (int h = 0; h < basalValues; h++) { Double pumpValue = pump.pumpProfiles[pump.activeProfile][h]; Double profileValue = profile.getBasal(h * basalIncrement); + if (profileValue == null) return true; if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) { log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue); return false; @@ -288,7 +280,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public Date lastDataTime() { - return getDanaRPump().lastConnection; + return pump.lastConnection; } @Override @@ -300,84 +292,34 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public double getBaseBasalRate() { - return getDanaRPump().currentBasal; + return pump.currentBasal; } @Override - public double getTempBasalAbsoluteRate() { - TempBasal tb = getRealTempBasal(); - if (tb != null) { - if (tb.isAbsolute) { - return tb.absolute; - } else { - Double baseRate = getBaseBasalRate(); - Double tempRate = baseRate * (tb.percent / 100d); - return tempRate; - } - } - TempBasal eb = getExtendedBolus(); - if (eb != null && useExtendedBoluses) { - return getBaseBasalRate() + eb.absolute; - } - return 0; - } - - @Override - public double getTempBasalRemainingMinutes() { - if (isRealTempBasalInProgress()) - return getRealTempBasal().getPlannedRemainingMinutes(); - if (isExtendedBoluslInProgress() && useExtendedBoluses) - return getExtendedBolus().getPlannedRemainingMinutes(); - return 0; - } - - @Override - public TempBasal getTempBasal() { - if (isRealTempBasalInProgress()) - return getRealTempBasal(); - if (isExtendedBoluslInProgress() && useExtendedBoluses) - return getExtendedBolus(); - return null; - } - - public TempBasal getTempBasal(Date time) { - TempBasal temp = MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(time); - if (temp != null) return temp; - if (useExtendedBoluses) - return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(time); - return null; - } - - public TempBasal getRealTempBasal() { - return MainApp.getConfigBuilder().getActiveTempBasals().getTempBasal(new Date()); - } - - @Override - public TempBasal getExtendedBolus() { - return MainApp.getConfigBuilder().getActiveTempBasals().getExtendedBolus(new Date()); - } - - @Override - public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) { + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); - insulin = configBuilderPlugin.applyBolusConstraints(insulin); - if (insulin > 0 || carbs > 0) { - Treatment t = new Treatment(); + detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { + Treatment t = new Treatment(detailedBolusInfo.insulinInterface); boolean connectionOK = false; - if (insulin > 0 || carbs > 0) connectionOK = sExecutionService.bolus(insulin, carbs, t); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) + connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, t); PumpEnactResult result = new PumpEnactResult(); result.success = connectionOK; result.bolusDelivered = t.insulin; - result.carbsDelivered = carbs; + result.carbsDelivered = detailedBolusInfo.carbs; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); if (Config.logPumpActions) - log.debug("deliverTreatment: OK. Asked: " + insulin + " Delivered: " + result.bolusDelivered); + log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered); + detailedBolusInfo.insulin = t.insulin; + detailedBolusInfo.date = new Date().getTime(); + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); return result; } else { PumpEnactResult result = new PumpEnactResult(); result.success = false; result.bolusDelivered = 0d; - result.carbsDelivered = 0; + result.carbsDelivered = 0d; result.comment = MainApp.instance().getString(R.string.danar_invalidinput); log.error("deliverTreatment: Invalid input"); return result; @@ -397,7 +339,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { // Recheck pump status if older than 30 min - if (getDanaRPump().lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) { + if (pump.lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) { doConnect("setTempBasalAbsolute old data"); } @@ -413,13 +355,13 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints if (doTempOff) { // If extended in progress - if (isExtendedBoluslInProgress() && useExtendedBoluses) { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping extended bolus (doTempOff)"); return cancelExtendedBolus(); } // If temp in progress - if (isRealTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping temp basal (doTempOff)"); return cancelRealTempBasal(); @@ -442,7 +384,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints percentRate = 200; } // If extended in progress - if (isExtendedBoluslInProgress() && useExtendedBoluses) { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)"); result = cancelExtendedBolus(); @@ -452,14 +394,14 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints } } // Check if some temp is already in progress - if (isRealTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { // Correct basal already set ? - if (getRealTempBasal().percent == percentRate) { + if (MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()).percentRate == percentRate) { result.success = true; result.percent = percentRate; - result.absolute = getTempBasalAbsoluteRate(); + result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); result.enacted = false; - result.duration = ((Double) getTempBasalRemainingMinutes()).intValue(); + result.duration = ((Double) MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()).intValue(); result.isPercent = true; result.isTempCancel = false; if (Config.logPumpActions) @@ -483,7 +425,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints } if (doExtendedTemp) { // Check if some temp is already in progress - if (isRealTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { if (Config.logPumpActions) log.debug("setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)"); result = cancelRealTempBasal(); @@ -504,17 +446,17 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints // What is current rate of extended bolusing in u/h? if (Config.logPumpActions) { - log.debug("setTempBasalAbsolute: Extended bolus in progress: " + isExtendedBoluslInProgress() + " rate: " + getDanaRPump().extendedBolusAbsoluteRate + "U/h duration remaining: " + getDanaRPump().extendedBolusRemainingMinutes + "min"); + log.debug("setTempBasalAbsolute: Extended bolus in progress: " + MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() + " rate: " + pump.extendedBolusAbsoluteRate + "U/h duration remaining: " + pump.extendedBolusRemainingMinutes + "min"); log.debug("setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h"); } // Compare with extended rate in progress - if (isExtendedBoluslInProgress() && Math.abs(getDanaRPump().extendedBolusAbsoluteRate - extendedRateToSet) < getPumpDescription().extendedBolusStep) { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && Math.abs(pump.extendedBolusAbsoluteRate - extendedRateToSet) < getPumpDescription().extendedBolusStep) { // correct extended already set result.success = true; - result.absolute = getDanaRPump().extendedBolusAbsoluteRate; + result.absolute = pump.extendedBolusAbsoluteRate; result.enacted = false; - result.duration = getDanaRPump().extendedBolusRemainingMinutes; + result.duration = pump.extendedBolusRemainingMinutes; result.isPercent = false; result.isTempCancel = false; if (Config.logPumpActions) @@ -556,14 +498,15 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints log.error("setTempBasalPercent: Invalid input"); return result; } - if (percent > 200) percent = 200; - if (getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { + if (percent > getPumpDescription().maxTempPercent) + percent = getPumpDescription().maxTempPercent; + if (pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { result.enacted = false; result.success = true; result.isTempCancel = false; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = getDanaRPump().tempBasalRemainingMin; - result.percent = getDanaRPump().tempBasalPercent; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: Correct value already set"); @@ -571,13 +514,13 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints } int durationInHours = Math.max(durationInMinutes / 60, 1); boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); - if (connectionOK && getDanaRPump().isTempBasalInProgress && getDanaRPump().tempBasalPercent == percent) { + if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { result.enacted = true; result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); result.isTempCancel = false; - result.duration = getDanaRPump().tempBasalRemainingMin; - result.percent = getDanaRPump().tempBasalPercent; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: OK"); @@ -598,28 +541,28 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); PumpEnactResult result = new PumpEnactResult(); - if (getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + if (pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { result.enacted = false; result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - result.duration = getDanaRPump().extendedBolusRemainingMinutes; - result.absolute = getDanaRPump().extendedBolusAbsoluteRate; + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; result.isPercent = false; result.isTempCancel = false; if (Config.logPumpActions) - log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + getDanaRPump().extendedBolusAmount + " Asked: " + insulin); + log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); return result; } int durationInHalfHours = Math.max(durationInMinutes / 30, 1); boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); - if (connectionOK && getDanaRPump().isExtendedInProgress && Math.abs(getDanaRPump().extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { result.enacted = true; result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); result.isTempCancel = false; - result.duration = getDanaRPump().extendedBolusRemainingMinutes; - result.absolute = getDanaRPump().extendedBolusAbsoluteRate; - result.bolusDelivered = getDanaRPump().extendedBolusAmount; + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; + result.bolusDelivered = pump.extendedBolusAmount; result.isPercent = false; if (Config.logPumpActions) log.debug("setExtendedBolus: OK"); @@ -634,10 +577,12 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public PumpEnactResult cancelTempBasal() { - if (isRealTempBasalInProgress()) + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) return cancelRealTempBasal(); - if (isExtendedBoluslInProgress()) - return cancelExtendedBolus(); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress() && useExtendedBoluses) { + PumpEnactResult cancelEx = cancelExtendedBolus(); + return cancelEx; + } PumpEnactResult result = new PumpEnactResult(); result.success = true; result.enacted = false; @@ -648,12 +593,12 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints public PumpEnactResult cancelRealTempBasal() { PumpEnactResult result = new PumpEnactResult(); - if (getDanaRPump().isTempBasalInProgress) { + if (pump.isTempBasalInProgress) { sExecutionService.tempBasalStop(); result.enacted = true; result.isTempCancel = true; } - if (!getDanaRPump().isTempBasalInProgress) { + if (!pump.isTempBasalInProgress) { result.success = true; result.isTempCancel = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); @@ -672,12 +617,12 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public PumpEnactResult cancelExtendedBolus() { PumpEnactResult result = new PumpEnactResult(); - if (getDanaRPump().isExtendedInProgress) { + if (pump.isExtendedInProgress) { sExecutionService.extendedBolusStop(); result.enacted = true; result.isTempCancel = true; } - if (!getDanaRPump().isExtendedInProgress) { + if (!pump.isExtendedInProgress) { result.success = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); if (Config.logPumpActions) @@ -709,48 +654,55 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public JSONObject getJSONStatus() { - if (getDanaRPump().lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) { + if (pump.lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) { return null; } - JSONObject pump = new JSONObject(); + JSONObject pumpjson = new JSONObject(); JSONObject battery = new JSONObject(); JSONObject status = new JSONObject(); JSONObject extended = new JSONObject(); try { - battery.put("percent", getDanaRPump().batteryRemaining); - status.put("status", "normal"); - status.put("timestamp", DateUtil.toISOString(getDanaRPump().lastConnection)); + battery.put("percent", pump.batteryRemaining); + status.put("status", pump.pumpSuspended ? "suspended" : "normal"); + status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); - extended.put("PumpIOB", getDanaRPump().iob); -// extended.put("LastBolus", getDanaRPump().lastBolusTime.toLocaleString()); -// extended.put("LastBolusAmount", getDanaRPump().lastBolusAmount); - TempBasal tb = getTempBasal(); + extended.put("PumpIOB", pump.iob); + if (pump.lastBolusTime.getTime() != 0) { + extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); + extended.put("LastBolusAmount", pump.lastBolusAmount); + } + TemporaryBasal tb = MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()); if (tb != null) { - extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate()); - extended.put("TempBasalStart", tb.timeStart.toLocaleString()); + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(new Date().getTime())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - extended.put("IsExtended", tb.isExtended); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()); + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); + extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); + extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); } extended.put("BaseBasalRate", getBaseBasalRate()); try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile()); + extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); } catch (Exception e) { } - pump.put("battery", battery); - pump.put("status", status); - pump.put("extended", extended); - pump.put("reservoir", (int) getDanaRPump().reservoirRemainingUnits); - pump.put("clock", DateUtil.toISOString(new Date())); + pumpjson.put("battery", battery); + pumpjson.put("status", status); + pumpjson.put("extended", extended); + pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); + pumpjson.put("clock", DateUtil.toISOString(new Date())); } catch (JSONException e) { e.printStackTrace(); } - return pump; + return pumpjson; } @Override public String deviceID() { - return getDanaRPump().serialNumber; + return pump.serialNumber; } @Override @@ -786,9 +738,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public Double applyBasalConstraints(Double absoluteRate) { double origAbsoluteRate = absoluteRate; - if (getDanaRPump() != null) { - if (absoluteRate > getDanaRPump().maxBasal) { - absoluteRate = getDanaRPump().maxBasal; + if (pump != null) { + if (absoluteRate > pump.maxBasal) { + absoluteRate = pump.maxBasal; if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); } @@ -801,7 +753,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints public Integer applyBasalConstraints(Integer percentRate) { Integer origPercentRate = percentRate; if (percentRate < 0) percentRate = 0; - if (percentRate > 200) percentRate = 200; + if (percentRate > getPumpDescription().maxTempPercent) + percentRate = getPumpDescription().maxTempPercent; if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); return percentRate; @@ -811,9 +764,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public Double applyBolusConstraints(Double insulin) { double origInsulin = insulin; - if (getDanaRPump() != null) { - if (insulin > getDanaRPump().maxBolus) { - insulin = getDanaRPump().maxBolus; + if (pump != null) { + if (insulin > pump.maxBolus) { + insulin = pump.maxBolus; if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); } @@ -833,36 +786,40 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Nullable @Override - public NSProfile getProfile() { - DanaRKoreanPump pump = getDanaRPump(); + public ProfileStore getProfile() { if (pump.lastSettingsRead.getTime() == 0) return null; // no info now return pump.createConvertedProfile(); } + @Override + public String getProfileName() { + return pump.createConvertedProfileName(); + } + // Reply for sms communicator public String shortStatus(boolean veryShort) { String ret = ""; - if (getDanaRPump().lastConnection.getTime() != 0) { - Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime(); + if (pump.lastConnection.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); int agoMin = (int) (agoMsec / 60d / 1000d); ret += "LastConn: " + agoMin + " minago\n"; } -// if (getDanaRPump().lastBolusTime.getTime() != 0) { -// ret += "LastBolus: " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", getDanaRPump().lastBolusTime) + "\n"; -// } - if (isRealTempBasalInProgress()) { - ret += "Temp: " + getRealTempBasal().toString() + "\n"; + if (pump.lastBolusTime.getTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; } - if (isExtendedBoluslInProgress()) { - ret += "Extended: " + getExtendedBolus().toString() + "\n"; + if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) { + ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(new Date().getTime()).toStringFull() + "\n"; } - if (!veryShort){ - ret += "TDD: " + DecimalFormatter.to0Decimal(getDanaRPump().dailyTotalUnits) + " / " + getDanaRPump().maxDailyTotalUnits + " U\n"; + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).toString() + "\n"; } - ret += "IOB: " + getDanaRPump().iob + "U\n"; - ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n"; - ret += "Batt: " + getDanaRPump().batteryRemaining + "\n"; + if (!veryShort) { + ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; + } + ret += "IOB: " + pump.iob + "U\n"; + ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; + ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; } // TODO: daily total constraint diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java new file mode 100644 index 0000000000..d9802c016c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java @@ -0,0 +1,430 @@ +package info.nightscout.androidaps.plugins.PumpDanaRKorean.History; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.Spinner; +import android.widget.TextView; + +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.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DanaRHistoryRecord; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.ToastUtils; + +public class DanaRHistoryActivity extends Activity { + private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); + + private boolean mBounded; + private static DanaRKoreanExecutionService mExecutionService; + + private Handler mHandler; + private static HandlerThread mHandlerThread; + + static Profile profile = null; + + Spinner historyTypeSpinner; + TextView statusView; + Button reloadButton; + Button syncButton; + RecyclerView recyclerView; + LinearLayoutManager llm; + + static byte showingType = RecordTypes.RECORD_TYPE_ALARM; + List historyList = new ArrayList<>(); + + public static class TypeList { + public byte type; + String name; + + public TypeList(byte type, String name) { + this.type = type; + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + + public DanaRHistoryActivity() { + super(); + mHandlerThread = new HandlerThread(DanaRHistoryActivity.class.getSimpleName()); + mHandlerThread.start(); + this.mHandler = new Handler(mHandlerThread.getLooper()); + } + + + @Override + public void onStart() { + super.onStart(); + Intent intent = new Intent(this, DanaRKoreanExecutionService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Override + protected void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onStop() { + super.onStop(); + if (mBounded) { + unbindService(mConnection); + mBounded = false; + } + } + + ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + log.debug("Service is disconnected"); + mBounded = false; + mExecutionService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + log.debug("Service is connected"); + mBounded = true; + DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service; + mExecutionService = mLocalBinder.getServiceInstance(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.danar_historyactivity); + + historyTypeSpinner = (Spinner) findViewById(R.id.danar_historytype); + statusView = (TextView) findViewById(R.id.danar_historystatus); + reloadButton = (Button) findViewById(R.id.danar_historyreload); + syncButton = (Button) findViewById(R.id.danar_historysync); + recyclerView = (RecyclerView) findViewById(R.id.danar_history_recyclerview); + + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(this); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(historyList); + recyclerView.setAdapter(adapter); + + statusView.setVisibility(View.GONE); + + // Types + + ArrayList typeList = new ArrayList<>(); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ALARM, getString(R.string.danar_history_alarm))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BASALHOUR, getString(R.string.danar_history_basalhours))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_BOLUS, getString(R.string.danar_history_bolus))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_CARBO, getString(R.string.danar_history_carbohydrates))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_DAILY, getString(R.string.danar_history_dailyinsulin))); + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_GLUCOSE, getString(R.string.danar_history_glucose))); + + ArrayAdapter spinnerAdapter = new ArrayAdapter<>(this, + R.layout.spinner_centered, typeList); + historyTypeSpinner.setAdapter(spinnerAdapter); + + reloadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mExecutionService.isConnected() || mExecutionService.isConnecting()) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); + return; + } + mHandler.post(new Runnable() { + @Override + public void run() { + TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + syncButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + } + }); + clearCardView(); + mExecutionService.loadHistory(selected.type); + loadDataFromDB(selected.type); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.VISIBLE); + syncButton.setVisibility(View.VISIBLE); + statusView.setVisibility(View.GONE); + } + }); + } + }); + } + }); + + syncButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mHandler.post(new Runnable() { + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.GONE); + syncButton.setVisibility(View.GONE); + statusView.setVisibility(View.VISIBLE); + } + }); + DanaRNSHistorySync sync = new DanaRNSHistorySync(historyList); + sync.sync(DanaRNSHistorySync.SYNC_ALL); + runOnUiThread(new Runnable() { + @Override + public void run() { + reloadButton.setVisibility(View.VISIBLE); + syncButton.setVisibility(View.VISIBLE); + statusView.setVisibility(View.GONE); + } + }); + } + }); + } + }); + + historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); + loadDataFromDB(selected.type); + showingType = selected.type; + } + + @Override + public void onNothingSelected(AdapterView parent) { + clearCardView(); + } + }); + profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); + finish(); + } + } + + public static class RecyclerViewAdapter extends RecyclerView.Adapter { + + List historyList; + + RecyclerViewAdapter(List historyList) { + this.historyList = historyList; + } + + @Override + public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.danar_history_item, viewGroup, false); + return new HistoryViewHolder(v); + } + + @Override + public void onBindViewHolder(HistoryViewHolder holder, int position) { + DanaRHistoryRecord record = historyList.get(position); + holder.time.setText(DateUtil.dateAndTimeString(record.recordDate)); + holder.value.setText(DecimalFormatter.to2Decimal(record.recordValue)); + holder.stringvalue.setText(record.stringRecordValue); + holder.bolustype.setText(record.bolusType); + holder.duration.setText(DecimalFormatter.to0Decimal(record.recordDuration)); + holder.alarm.setText(record.recordAlarm); + switch (showingType) { + case RecordTypes.RECORD_TYPE_ALARM: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.VISIBLE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.VISIBLE); + break; + case RecordTypes.RECORD_TYPE_BOLUS: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.VISIBLE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.VISIBLE); + holder.duration.setVisibility(View.VISIBLE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.GONE); + break; + case RecordTypes.RECORD_TYPE_DAILY: + holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + "U"); + holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + "U"); + holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus + record.recordDailyBasal) + "U"); + holder.time.setText(DateUtil.dateString(record.recordDate)); + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.GONE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.VISIBLE); + holder.dailybolus.setVisibility(View.VISIBLE); + holder.dailytotal.setVisibility(View.VISIBLE); + holder.alarm.setVisibility(View.GONE); + break; + case RecordTypes.RECORD_TYPE_GLUCOSE: + holder.value.setText(Profile.toUnitsString(record.recordValue, record.recordValue * Constants.MGDL_TO_MMOLL, profile.getUnits())); + // rest is the same + case RecordTypes.RECORD_TYPE_CARBO: + case RecordTypes.RECORD_TYPE_BASALHOUR: + case RecordTypes.RECORD_TYPE_ERROR: + case RecordTypes.RECORD_TYPE_PRIME: + case RecordTypes.RECORD_TYPE_REFILL: + case RecordTypes.RECORD_TYPE_TB: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.VISIBLE); + holder.stringvalue.setVisibility(View.GONE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.GONE); + break; + case RecordTypes.RECORD_TYPE_SUSPEND: + holder.time.setVisibility(View.VISIBLE); + holder.value.setVisibility(View.GONE); + holder.stringvalue.setVisibility(View.VISIBLE); + holder.bolustype.setVisibility(View.GONE); + holder.duration.setVisibility(View.GONE); + holder.dailybasal.setVisibility(View.GONE); + holder.dailybolus.setVisibility(View.GONE); + holder.dailytotal.setVisibility(View.GONE); + holder.alarm.setVisibility(View.GONE); + break; + } + } + + @Override + public int getItemCount() { + return historyList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public static class HistoryViewHolder extends RecyclerView.ViewHolder { + CardView cv; + TextView time; + TextView value; + TextView bolustype; + TextView stringvalue; + TextView duration; + TextView dailybasal; + TextView dailybolus; + TextView dailytotal; + TextView alarm; + + HistoryViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.danar_history_cardview); + time = (TextView) itemView.findViewById(R.id.danar_history_time); + value = (TextView) itemView.findViewById(R.id.danar_history_value); + bolustype = (TextView) itemView.findViewById(R.id.danar_history_bolustype); + stringvalue = (TextView) itemView.findViewById(R.id.danar_history_stringvalue); + duration = (TextView) itemView.findViewById(R.id.danar_history_duration); + dailybasal = (TextView) itemView.findViewById(R.id.danar_history_dailybasal); + dailybolus = (TextView) itemView.findViewById(R.id.danar_history_dailybolus); + dailytotal = (TextView) itemView.findViewById(R.id.danar_history_dailytotal); + alarm = (TextView) itemView.findViewById(R.id.danar_history_alarm); + } + } + } + + private void loadDataFromDB(byte type) { + historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); + + runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false); + } + }); + } + + private void clearCardView() { + historyList = new ArrayList<>(); + runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(historyList), false); + } + }); + } + + @Subscribe + public void onStatusEvent(final EventDanaRSyncStatus s) { + log.debug("EventDanaRSyncStatus: " + s.message); + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(s.message); + } + }); + } + + @Subscribe + public void onStatusEvent(final EventPumpStatusChanged c) { + runOnUiThread( + new Runnable() { + @Override + public void run() { + statusView.setText(c.textStatus()); + } + } + ); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java similarity index 89% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/History/DanaRStatsActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java index 0c0e2f112b..dc014b5eaa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/History/DanaRStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java @@ -1,18 +1,16 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.History; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.History; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.preference.PreferenceManager; import android.support.v7.widget.LinearLayoutManager; import android.text.TextUtils; import android.view.KeyEvent; @@ -27,16 +25,11 @@ import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; -import com.j256.ormlite.dao.Dao; -import com.j256.ormlite.stmt.PreparedQuery; -import com.j256.ormlite.stmt.QueryBuilder; -import com.j256.ormlite.stmt.Where; import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; @@ -50,12 +43,13 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -63,7 +57,7 @@ public class DanaRStatsActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRKoreanExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -89,7 +83,7 @@ public class DanaRStatsActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRKoreanExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -140,7 +134,7 @@ public class DanaRStatsActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -167,18 +161,15 @@ public class DanaRStatsActivity extends Activity { decimalFormat = new DecimalFormat("0.000"); llm = new LinearLayoutManager(this); - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - TBB = preferences.getString("TBB", "10.00"); + TBB = SP.getString("TBB", "10.00"); totalBaseBasal.setText(TBB); - ProfileInterface pi = ConfigBuilderPlugin.getActiveProfile(); + ProfileInterface pi = ConfigBuilderPlugin.getActiveProfileInterface(); if (pi != null && pi instanceof CircadianPercentageProfilePlugin) { double cppTBB = ((CircadianPercentageProfilePlugin) pi).baseBasalSum(); totalBaseBasal.setText(decimalFormat.format(cppTBB)); - SharedPreferences.Editor edit = preferences.edit(); - edit.putString("TBB", totalBaseBasal.getText().toString()); - edit.commit(); - TBB = preferences.getString("TBB", ""); + SP.putString("TBB", totalBaseBasal.getText().toString()); + TBB = SP.getString("TBB", ""); } // stats table @@ -326,10 +317,8 @@ public class DanaRStatsActivity extends Activity { if (hasFocus) { totalBaseBasal.getText().clear(); } else { - SharedPreferences.Editor edit = preferences.edit(); - edit.putString("TBB", totalBaseBasal.getText().toString()); - edit.commit(); - TBB = preferences.getString("TBB", ""); + SP.putString("TBB", totalBaseBasal.getText().toString()); + TBB = SP.getString("TBB", ""); loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0); @@ -341,19 +330,8 @@ public class DanaRStatsActivity extends Activity { } private void loadDataFromDB(byte type) { - try { - Dao dao = MainApp.getDbHelper().getDaoDanaRHistory(); - QueryBuilder queryBuilder = dao.queryBuilder(); - queryBuilder.orderBy("recordDate", false); - Where where = queryBuilder.where(); - where.eq("recordCode", type); - queryBuilder.limit(10L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - historyList = dao.query(preparedQuery); - } catch (SQLException e) { - e.printStackTrace(); - historyList = new ArrayList<>(); - } + historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); + runOnUiThread(new Runnable() { @Override public void run() { @@ -379,7 +357,7 @@ public class DanaRStatsActivity extends Activity { double weighted07 = 0d; for (DanaRHistoryRecord record : historyList) { - double tdd = record.getRecordDailyBolus() + record.getRecordDailyBasal(); + double tdd = record.recordDailyBolus + record.recordDailyBasal; // Create the table row TableRow tr = new TableRow(DanaRStatsActivity.this); @@ -392,19 +370,19 @@ public class DanaRStatsActivity extends Activity { // Here create the TextView dynamically TextView labelDATE = new TextView(DanaRStatsActivity.this); labelDATE.setId(200 + i); - labelDATE.setText(df.format(new Date(record.getRecordDate()))); + labelDATE.setText(df.format(new Date(record.recordDate))); labelDATE.setTextColor(Color.WHITE); tr.addView(labelDATE); TextView labelBASAL = new TextView(DanaRStatsActivity.this); labelBASAL.setId(300 + i); - labelBASAL.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + " U"); + labelBASAL.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + " U"); labelBASAL.setTextColor(Color.WHITE); tr.addView(labelBASAL); TextView labelBOLUS = new TextView(DanaRStatsActivity.this); labelBOLUS.setId(400 + i); - labelBOLUS.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + " U"); + labelBOLUS.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + " U"); labelBOLUS.setTextColor(Color.WHITE); tr.addView(labelBOLUS); @@ -461,7 +439,7 @@ public class DanaRStatsActivity extends Activity { TableLayout.LayoutParams.WRAP_CONTENT)); } - if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).getRecordDate())).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) { + if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).recordDate)).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) { statsMessage.setVisibility(View.VISIBLE); statsMessage.setText(getString(R.string.danar_stats_olddata_Message)); @@ -474,7 +452,7 @@ public class DanaRStatsActivity extends Activity { i = 0; for (DanaRHistoryRecord record : historyList) { - double tdd = record.getRecordDailyBolus() + record.getRecordDailyBasal(); + double tdd = record.recordDailyBolus + record.recordDailyBasal; if (i == 0) { weighted03 = tdd; weighted05 = tdd; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java new file mode 100644 index 0000000000..597a49a676 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java @@ -0,0 +1,229 @@ +package info.nightscout.androidaps.plugins.PumpDanaRKorean; + +import android.bluetooth.BluetoothSocket; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MessageHashTable_k; +import info.nightscout.utils.CRC; + +/** + * Created by mike on 17.07.2016. + */ +public class SerialIOThread extends Thread { + private static Logger log = LoggerFactory.getLogger(SerialIOThread.class); + + private InputStream mInputStream = null; + private OutputStream mOutputStream = null; + private BluetoothSocket mRfCommSocket; + + private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); + private static ScheduledFuture scheduledDisconnection = null; + + private boolean mKeepRunning = true; + private byte[] mReadBuff = new byte[0]; + + MessageBase processedMessage; + + public SerialIOThread(BluetoothSocket rfcommSocket) { + super(SerialIOThread.class.toString()); + + mRfCommSocket = rfcommSocket; + try { + mOutputStream = mRfCommSocket.getOutputStream(); + mInputStream = mRfCommSocket.getInputStream(); + } catch (IOException e) { + e.printStackTrace(); + } + this.start(); + } + + @Override + public final void run() { + try { + while (mKeepRunning) { + int availableBytes = mInputStream.available(); + // Ask for 1024 byte (or more if available) + byte[] newData = new byte[Math.max(1024, availableBytes)]; + int gotBytes = mInputStream.read(newData); + // When we are here there is some new data available + appendToBuffer(newData, gotBytes); + + // process all messages we already got + while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size + byte[] extractedBuff = cutMessageFromBuffer(); + if (extractedBuff == null) break; // message is not complete in buffer (wrong packet calls disconnection) + + int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); + + MessageBase message; + if (processedMessage != null && processedMessage.getCommand() == command) { + message = processedMessage; + } else { + // get it from hash table + message = MessageHashTable_k.findMessage(command); + } + + if (Config.logDanaMessageDetail) + log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); + + // process the message content + message.received = true; + message.handleMessage(extractedBuff); + synchronized (message) { + message.notify(); + } + scheduleDisconnection(); + } + } + } catch (Exception e) { + if (Config.logDanaSerialEngine && e.getMessage().indexOf("bt socket closed") < 0) + log.error("Thread exception: ", e); + mKeepRunning = false; + } + disconnect("EndOfLoop"); + } + + void appendToBuffer(byte[] newData, int gotBytes) { + // add newData to mReadBuff + byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; + System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); + System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes); + mReadBuff = newReadBuff; + } + + byte[] cutMessageFromBuffer() { + if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { + int length = (mReadBuff[2] & 0xFF) + 7; + // Check if we have enough data + if (mReadBuff.length < length) { + return null; + } + if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) { + log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff)); + disconnect("wrong packet"); + return null; + } + + short crc = CRC.getCrc16(mReadBuff, 3, length - 7); + byte crcByte0 = (byte) (crc >> 8 & 0xFF); + byte crcByte1 = (byte) (crc & 0xFF); + + byte crcByte0received = mReadBuff[length - 4]; + byte crcByte1received = mReadBuff[length - 3]; + + if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) { + log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received)); + disconnect("crc error"); + return null; + } + // Packet is verified here. extract data + byte[] extractedBuff = new byte[length]; + System.arraycopy(mReadBuff, 0, extractedBuff, 0, length); + // remove extracted data from read buffer + byte[] unprocessedData = new byte[mReadBuff.length - length]; + System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length); + mReadBuff = unprocessedData; + return extractedBuff; + } else { + log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff)); + disconnect("Wrong beginning of packet"); + return null; + } + } + + public synchronized void sendMessage(MessageBase message) { + if (!mRfCommSocket.isConnected()) { + log.error("Socket not connected on sendMessage"); + return; + } + processedMessage = message; + + byte[] messageBytes = message.getRawMessageBytes(); + if (Config.logDanaSerialEngine) + log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); + + try { + mOutputStream.write(messageBytes); + } catch (Exception e) { + log.error("sendMessage write exception: ", e); + e.printStackTrace(); + } + + synchronized (message) { + try { + message.wait(5000); + } catch (InterruptedException e) { + log.error("sendMessage InterruptedException", e); + e.printStackTrace(); + } + } + + try { + Thread.sleep(200); + } catch (InterruptedException e) { + } + if (!message.received) { + log.warn("Reply not received " + message.getMessageName()); + if (message.getCommand() == 0xF0F1) { + DanaRPump.getInstance().isNewPump = false; + log.debug("Old firmware detected"); + } + } + scheduleDisconnection(); + } + + public void scheduleDisconnection() { + class DisconnectRunnable implements Runnable { + public void run() { + disconnect("scheduleDisconnection"); + scheduledDisconnection = null; + } + } + // prepare task for execution in 5 sec + // cancel waiting task to prevent sending multiple disconnections + if (scheduledDisconnection != null) + scheduledDisconnection.cancel(false); + Runnable task = new DisconnectRunnable(); + final int sec = 5; + scheduledDisconnection = worker.schedule(task, sec, TimeUnit.SECONDS); + } + + public void disconnect(String reason) { + mKeepRunning = false; + try { + mInputStream.close(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + try { + mOutputStream.close(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + try { + mRfCommSocket.close(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + try { + System.runFinalization(); + } catch (Exception e) { + if (Config.logDanaSerialEngine) log.debug(e.getMessage()); + } + if (Config.logDanaSerialEngine) log.debug("Disconnected: " + reason); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable_k.java new file mode 100644 index 0000000000..422391c127 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable_k.java @@ -0,0 +1,76 @@ +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; + +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; + +/** + * Created by mike on 28.05.2016. + */ +public class MessageHashTable_k { + private static Logger log = LoggerFactory.getLogger(MessageHashTable_k.class); + + public static HashMap messages = null; + + static { + if (messages == null) { + messages = new HashMap(); + put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP + put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA + put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING + put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE + put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I + put(new MsgStatusBasic_k()); // 0x020A CMD_PUMP_INITVIEW_I + put(new MsgStatus_k()); // 0x020B CMD_PUMP_STATUS + put(new MsgInitConnStatusTime_k()); // 0x0301 CMD_PUMPINIT_TIME_INFO + put(new MsgInitConnStatusBolus_k()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(new MsgInitConnStatusBasic_k()); // 0x0303 CMD_PUMPINIT_INIT_INFO + put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S + put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S + put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT + put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT + put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS + put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS + put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE + put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM + put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY + put(new MsgSettingBasal_k()); // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I + put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(new MsgSettingBasalProfileAll_k()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I + put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I + put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S + put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL + put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE + put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW + put(new MsgCheckValue_k()); // 0xF0F1 CMD_PUMP_CHECK_VALUE + } + } + + public static void put(MessageBase message) { + int command = message.getCommand(); + //String name = MessageOriginalNames.getName(command); + messages.put(command, message); + //log.debug(String.format("%04x ", command) + " " + name); + } + + public static MessageBase findMessage(Integer command) { + if (messages.containsKey(command)) { + return messages.get(command); + } else { + return new MessageBase(); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java similarity index 69% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgCheckValue.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java index efcb32f2ba..7536bd278c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,32 +6,32 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.utils.ToastUtils; /** * Created by mike on 30.06.2016. */ -public class MsgCheckValue extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgCheckValue.class); +public class MsgCheckValue_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgCheckValue_k.class); - public MsgCheckValue() { + public MsgCheckValue_k() { SetCommand(0xF0F1); } @Override public void handleMessage(byte[] bytes) { - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); - DanaRKoreanPlugin.getDanaRPump().isNewPump = true; + pump.isNewPump = true; log.debug("New firmware confirmed"); pump.model = intFromBuff(bytes, 0, 1); pump.protocol = intFromBuff(bytes, 1, 1); pump.productCode = intFromBuff(bytes, 2, 1); - if (pump.model != DanaRKoreanPump.DOMESTIC_MODEL) { + if (pump.model != DanaRPump.DOMESTIC_MODEL) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); log.debug("Wrong model selected"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java index e21db06d4c..26462987d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,17 +6,16 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -public class MsgInitConnStatusBasic extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic.class); +public class MsgInitConnStatusBasic_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic_k.class); - public MsgInitConnStatusBasic() { + public MsgInitConnStatusBasic_k() { SetCommand(0x0303); } @@ -25,7 +24,7 @@ public class MsgInitConnStatusBasic extends MessageBase { if (bytes.length - 10 > 6) { return; } - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); pump.pumpSuspended = intFromBuff(bytes, 0, 1) == 1; int isUtilityEnable = intFromBuff(bytes, 1, 1); pump.isEasyModeEnabled = intFromBuff(bytes, 2, 1) == 1; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java similarity index 79% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusBolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java index b391fe11e3..2e6d6234f0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,9 +6,8 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; @@ -16,10 +15,10 @@ import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; /** * Created by mike on 28.05.2016. */ -public class MsgInitConnStatusBolus extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBolus.class); +public class MsgInitConnStatusBolus_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBolus_k.class); - public MsgInitConnStatusBolus() { + public MsgInitConnStatusBolus_k() { SetCommand(0x0302); } @@ -28,7 +27,7 @@ public class MsgInitConnStatusBolus extends MessageBase { if (bytes.length - 10 < 13) { return; } - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); int bolusConfig = intFromBuff(bytes, 0, 1); pump.isExtendedBolusEnabled = (bolusConfig & 0x01) != 0; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java similarity index 68% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java index 5e904a493b..0a73555b52 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,15 +10,16 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.utils.ToastUtils; -public class MsgInitConnStatusTime extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime.class); +public class MsgInitConnStatusTime_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime_k.class); - public MsgInitConnStatusTime() { + public MsgInitConnStatusTime_k() { SetCommand(0x0301); } @@ -29,10 +30,11 @@ public class MsgInitConnStatusTime extends MessageBase { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); log.debug("Wrong model selected. Switching to export DanaR"); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentEnabled(PluginBase.PUMP, false); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).setFragmentVisible(PluginBase.PUMP, false); - ((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true); - ((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false); + MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); + MainApp.getSpecificPlugin(DanaRPlugin.class).setFragmentVisible(PluginBase.PUMP, true); + DanaRPump.getInstance().lastConnection = new Date(0); // mark not initialized //If profile coming from pump, switch it as well if(MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PROFILE)){ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingBasalProfileAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java similarity index 74% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingBasalProfileAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java index 9397ed86c6..304ec9fc37 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingBasalProfileAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java @@ -1,12 +1,11 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; /** @@ -15,16 +14,16 @@ import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; *

* THIS IS BROKEN IN PUMP... SENDING ONLY 1 PROFILE */ -public class MsgSettingBasalProfileAll extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingBasalProfileAll.class); +public class MsgSettingBasalProfileAll_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSettingBasalProfileAll_k.class); - public MsgSettingBasalProfileAll() { + public MsgSettingBasalProfileAll_k() { SetCommand(0x3206); } public void handleMessage(byte[] bytes) { - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); - if (DanaRKoreanPlugin.getDanaRPump().basal48Enable) { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.basal48Enable) { pump.pumpProfiles = new double[4][]; for (int profile = 0; profile < 4; profile++) { int position = intFromBuff(bytes, 107 * profile, 1); @@ -51,10 +50,10 @@ public class MsgSettingBasalProfileAll extends MessageBase { } if (Config.logDanaMessageDetail) { - if (DanaRKoreanPlugin.getDanaRPump().basal48Enable) { + if (pump.basal48Enable) { for (int profile = 0; profile < 4; profile++) { for (int index = 0; index < 24; index++) { - log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + DanaRKoreanPlugin.getDanaRPump().pumpProfiles[profile][index]); + log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profile][index]); } } } else { @@ -63,7 +62,7 @@ public class MsgSettingBasalProfileAll extends MessageBase { log.debug("Basal profile " + profile + ": " + String.format("%02d", (index / 2)) + ":" + String.format("%02d", (index % 2) * 30) + " : " + - DanaRKoreanPlugin.getDanaRPump().pumpProfiles[profile][index]); + pump.pumpProfiles[profile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java similarity index 61% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingBasal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java index 57f63efa5a..72a8be4e42 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgSettingBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java @@ -1,25 +1,25 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; /** * Created by mike on 05.07.2016. */ -public class MsgSettingBasal extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgSettingBasal.class); +public class MsgSettingBasal_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSettingBasal_k.class); - public MsgSettingBasal() { + public MsgSettingBasal_k() { SetCommand(0x3202); } public void handleMessage(byte[] bytes) { - DanaRKoreanPump pump = DanaRKoreanPlugin.getDanaRPump(); + DanaRPump pump = DanaRPump.getInstance(); if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][]; pump.pumpProfiles[pump.activeProfile] = new double[24]; for (int index = 0; index < 24; index++) { @@ -30,7 +30,7 @@ public class MsgSettingBasal extends MessageBase { if (Config.logDanaMessageDetail) for (int index = 0; index < 24; index++) { - log.debug("Basal " + String.format("%02d", index) + "h: " + DanaRKoreanPlugin.getDanaRPump().pumpProfiles[DanaRKoreanPlugin.getDanaRPump().activeProfile][index]); + log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java similarity index 56% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java index 46a230b184..0fcaf17d83 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MsgStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java @@ -1,32 +1,33 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -public class MsgStatusBasic extends MessageBase { - private static Logger log = LoggerFactory.getLogger(MsgStatusBasic.class); +public class MsgStatusBasic_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusBasic_k.class); - public MsgStatusBasic() { + public MsgStatusBasic_k() { SetCommand(0x020A); } public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); double currentBasal = intFromBuff(bytes, 0, 2) / 100d; int batteryRemaining = intFromBuff(bytes, 2, 1); double reservoirRemainingUnits = intFromBuff(bytes, 3, 3) / 750d; double dailyTotalUnits = intFromBuff(bytes, 6, 3) / 750d; int maxDailyTotalUnits = intFromBuff(bytes, 9, 2) / 100; - DanaRKoreanPlugin.getDanaRPump().dailyTotalUnits = dailyTotalUnits; - DanaRKoreanPlugin.getDanaRPump().maxDailyTotalUnits = maxDailyTotalUnits; - DanaRKoreanPlugin.getDanaRPump().reservoirRemainingUnits = reservoirRemainingUnits; - DanaRKoreanPlugin.getDanaRPump().currentBasal = currentBasal; - DanaRKoreanPlugin.getDanaRPump().batteryRemaining = batteryRemaining; + pump.dailyTotalUnits = dailyTotalUnits; + pump.maxDailyTotalUnits = maxDailyTotalUnits; + pump.reservoirRemainingUnits = reservoirRemainingUnits; + pump.currentBasal = currentBasal; + pump.batteryRemaining = batteryRemaining; if (Config.logDanaMessageDetail) { log.debug("Daily total units: " + dailyTotalUnits); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus_k.java new file mode 100644 index 0000000000..3bf1aa2e5f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus_k.java @@ -0,0 +1,40 @@ +package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgStatus_k extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatus_k.class); + + public MsgStatus_k() { + SetCommand(0x020B); + } + + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + pump.dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d; + pump.isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1; + pump.extendedBolusMinutes = intFromBuff(bytes, 4, 2); + pump.extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d; + Double lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d; +// if (lastBolusAmount != 0d) { +// pump.lastBolusTime = dateTimeFromBuff(bytes, 8); +// pump.lastBolusAmount = lastBolusAmount; +// } + pump.iob = intFromBuff(bytes, 15, 2) / 100d; + + if (Config.logDanaMessageDetail) { + log.debug("Daily total: " + pump.dailyTotalUnits); + log.debug("Is extended bolus running: " + pump.isExtendedInProgress); + log.debug("Extended bolus min: " + pump.extendedBolusMinutes); + log.debug("Extended bolus amount: " + pump.extendedBolusAmount); +// log.debug("Last bolus time: " + pump.lastBolusTime); +// log.debug("Last bolus amount: " + pump.lastBolusAmount); + log.debug("IOB: " + pump.iob); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/Services/ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java similarity index 76% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/Services/ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java index bbe4906b10..89976c6778 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/Services/ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.Services; +package info.nightscout.androidaps.plugins.PumpDanaRKorean.services; import android.app.Service; import android.bluetooth.BluetoothAdapter; @@ -18,7 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.util.Calendar; import java.util.Date; import java.util.Set; import java.util.UUID; @@ -33,54 +32,55 @@ import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAlarm; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBasalHour; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBolus; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryCarbo; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDailyInsulin; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDone; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryError; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryGlucose; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryRefill; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistorySuspend; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetCarbsEntry; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetSingleBasalProfile; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTime; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusStart; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPump; -import info.nightscout.androidaps.plugins.DanaRKorean.SerialIOThread; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgCheckValue; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingBasal; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingGlucose; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingMaxValues; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingMeal; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingProfileRatios; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingPumpTime; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgSettingShippingInfo; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusBasic; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusBolusExtended; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MsgStatusTempBasal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBasalHour; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryBolus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryCarbo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDailyInsulin; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryDone; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryError; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryRefill; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistorySuspend; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgPCCommStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetCarbsEntry; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetExtendedBolusStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetSingleBasalProfile; +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.MsgSettingGlucose; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMaxValues; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingMeal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingProfileRatios; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingPumpTime; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSettingShippingInfo; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusBolusExtended; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgStatusTempBasal; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue_k; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal_k; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic_k; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; -public class ExecutionService extends Service { - private static Logger log = LoggerFactory.getLogger(ExecutionService.class); +public class DanaRKoreanExecutionService extends Service { + private static Logger log = LoggerFactory.getLogger(DanaRKoreanExecutionService.class); private String devName; @@ -91,7 +91,7 @@ public class ExecutionService extends Service { private PowerManager.WakeLock mWakeLock; private IBinder mBinder = new LocalBinder(); - private DanaRKoreanPump danaRKoreanPump; + private DanaRPump danaRPump = DanaRPump.getInstance(); private Treatment bolusingTreatment = null; private static Boolean connectionInProgress = false; @@ -116,18 +116,17 @@ public class ExecutionService extends Service { } }; - public ExecutionService() { + public DanaRKoreanExecutionService() { registerBus(); MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); - danaRKoreanPump = DanaRKoreanPlugin.getDanaRPump(); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ExecutionService"); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRKoreanExecutionService"); } public class LocalBinder extends Binder { - public ExecutionService getServiceInstance() { - return ExecutionService.this; + public DanaRKoreanExecutionService getServiceInstance() { + return DanaRKoreanExecutionService.this; } } @@ -180,7 +179,7 @@ public class ExecutionService extends Service { } public void connect(String from) { - if (danaRKoreanPump.password != -1 && danaRKoreanPump.password != SP.getInt(R.string.key_danar_password, -1)) { + if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); return; } @@ -219,7 +218,7 @@ public class ExecutionService extends Service { mSerialIOThread.disconnect("Recreate SerialIOThread"); } mSerialIOThread = new SerialIOThread(mRfcommSocket); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED)); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); if (!getPumpStatus()) { mSerialIOThread.disconnect("getPumpStatus failed"); waitMsec(3000); @@ -274,13 +273,13 @@ public class ExecutionService extends Service { private boolean getPumpStatus() { try { MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); - //MsgStatus statusMsg = new MsgStatus(); - MsgStatusBasic statusBasicMsg = new MsgStatusBasic(); + //MsgStatus_k statusMsg = new MsgStatus_k(); + MsgStatusBasic_k statusBasicMsg = new MsgStatusBasic_k(); MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal(); MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended(); - MsgCheckValue checkValue = new MsgCheckValue(); + MsgCheckValue_k checkValue = new MsgCheckValue_k(); - if (danaRKoreanPump.isNewPump) { + if (danaRPump.isNewPump) { mSerialIOThread.sendMessage(checkValue); if (!checkValue.received) { return false; @@ -316,28 +315,28 @@ public class ExecutionService extends Service { } Date now = new Date(); - if (danaRKoreanPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).isInitialized()) { + if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).isInitialized()) { mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingMeal()); - mSerialIOThread.sendMessage(new MsgSettingBasal()); + mSerialIOThread.sendMessage(new MsgSettingBasal_k()); //0x3201 mSerialIOThread.sendMessage(new MsgSettingMaxValues()); mSerialIOThread.sendMessage(new MsgSettingGlucose()); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); mSerialIOThread.sendMessage(new MsgSetTime(new Date())); - danaRKoreanPump.lastSettingsRead = now; + danaRPump.lastSettingsRead = now; } - danaRKoreanPump.lastConnection = now; + danaRPump.lastConnection = now; MainApp.bus().post(new EventDanaRNewStatus()); MainApp.bus().post(new EventInitializationChanged()); - MainApp.getConfigBuilder().uploadDeviceStatus(); - if (danaRKoreanPump.dailyTotalUnits > danaRKoreanPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) { - log.debug("Approaching daily limit: " + danaRKoreanPump.dailyTotalUnits + "/" + danaRKoreanPump.maxDailyTotalUnits); + 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.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); MainApp.bus().post(new EventNewNotification(reportFail)); - MainApp.getConfigBuilder().uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRKoreanPump.dailyTotalUnits + "/" + danaRKoreanPump.maxDailyTotalUnits + "U"); + NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); } } catch (Exception e) { e.printStackTrace(); @@ -385,7 +384,7 @@ public class ExecutionService extends Service { return true; } - public boolean bolus(Double amount, int carbs, Treatment t) { + public boolean bolus(double amount, int carbs, Treatment t) { bolusingTreatment = t; MsgBolusStart start = new MsgBolusStart(amount); MsgBolusStop stop = new MsgBolusStop(amount, t); @@ -394,8 +393,7 @@ public class ExecutionService extends Service { if (!isConnected()) return false; if (carbs > 0) { - Calendar time = Calendar.getInstance(); - mSerialIOThread.sendMessage(new MsgSetCarbsEntry(time, carbs)); + mSerialIOThread.sendMessage(new MsgSetCarbsEntry(new Date().getTime(), carbs)); } MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables @@ -440,8 +438,7 @@ public class ExecutionService extends Service { public boolean carbsEntry(int amount) { connect("carbsEntry"); if (!isConnected()) return false; - Calendar time = Calendar.getInstance(); - MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount); + MsgSetCarbsEntry msg = new MsgSetCarbsEntry(new Date().getTime(), amount); mSerialIOThread.sendMessage(msg); return true; } @@ -491,23 +488,23 @@ public class ExecutionService extends Service { return true; } - public boolean updateBasalsInPump(final NSProfile profile) { + public boolean updateBasalsInPump(final Profile profile) { connect("updateBasalsInPump"); if (!isConnected()) return false; MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); double[] basal = buildDanaRProfileRecord(profile); MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal); mSerialIOThread.sendMessage(msgSet); - danaRKoreanPump.lastSettingsRead = new Date(0); // force read full settings + danaRPump.lastSettingsRead = new Date(0); // force read full settings getPumpStatus(); MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); return true; } - private double[] buildDanaRProfileRecord(NSProfile nsProfile) { + private double[] buildDanaRProfileRecord(Profile nsProfile) { double[] record = new double[24]; for (Integer hour = 0; hour < 24; hour++) { - double value = nsProfile.getBasal(hour * 60 * 60); + double value = Math.round(100d * nsProfile.getBasal(hour * 60 * 60))/100d + 0.00001; if (Config.logDanaMessageDetail) log.debug("NS basal value for " + hour + ":00 is " + value); record[hour] = value; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java new file mode 100644 index 0000000000..a0480685ad --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java @@ -0,0 +1,254 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2; + + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventExtendedBolusChange; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.History.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaRv2.History.DanaRStatsActivity; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SetWarnColor; + +public class DanaRv2Fragment extends Fragment { + private static Logger log = LoggerFactory.getLogger(DanaRv2Fragment.class); + + private static DanaRv2Plugin danaRPlugin; + + public static DanaRv2Plugin getPlugin() { + if (danaRPlugin == null) { + danaRPlugin = new DanaRv2Plugin(); + } + return danaRPlugin; + } + + private static Handler sHandler; + private static HandlerThread sHandlerThread; + + private Handler loopHandler = new Handler(); + private Runnable refreshLoop = null; + + TextView lastConnectionView; + TextView btConnectionView; + TextView lastBolusView; + TextView dailyUnitsView; + TextView basaBasalRateView; + TextView tempBasalView; + TextView extendedBolusView; + TextView batteryView; + TextView reservoirView; + TextView iobView; + TextView firmwareView; + Button viewProfileButton; + Button historyButton; + Button statsButton; + + + public DanaRv2Fragment() { + if (sHandlerThread == null) { + sHandlerThread = new HandlerThread(DanaRv2Fragment.class.getSimpleName()); + sHandlerThread.start(); + sHandler = new Handler(sHandlerThread.getLooper()); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (refreshLoop == null) { + refreshLoop = new Runnable() { + @Override + public void run() { + updateGUI(); + loopHandler.postDelayed(refreshLoop, 60 * 1000L); + } + }; + loopHandler.postDelayed(refreshLoop, 60 * 1000L); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.danar_fragment, container, false); + btConnectionView = (TextView) view.findViewById(R.id.danar_btconnection); + lastConnectionView = (TextView) view.findViewById(R.id.danar_lastconnection); + lastBolusView = (TextView) view.findViewById(R.id.danar_lastbolus); + dailyUnitsView = (TextView) view.findViewById(R.id.danar_dailyunits); + basaBasalRateView = (TextView) view.findViewById(R.id.danar_basabasalrate); + tempBasalView = (TextView) view.findViewById(R.id.danar_tempbasal); + extendedBolusView = (TextView) view.findViewById(R.id.danar_extendedbolus); + batteryView = (TextView) view.findViewById(R.id.danar_battery); + reservoirView = (TextView) view.findViewById(R.id.danar_reservoir); + iobView = (TextView) view.findViewById(R.id.danar_iob); + firmwareView = (TextView) view.findViewById(R.id.danar_firmware); + viewProfileButton = (Button) view.findViewById(R.id.danar_viewprofile); + historyButton = (Button) view.findViewById(R.id.danar_history); + statsButton = (Button) view.findViewById(R.id.danar_stats); + + + viewProfileButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentManager manager = getFragmentManager(); + ProfileViewDialog profileViewDialog = new ProfileViewDialog(); + profileViewDialog.show(manager, "ProfileViewDialog"); + } + }); + + historyButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(getContext(), DanaRHistoryActivity.class)); + } + }); + + statsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivity(new Intent(getContext(), DanaRStatsActivity.class)); + } + }); + + btConnectionView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + sHandler.post(new Runnable() { + @Override + public void run() { + DanaRv2Plugin.sExecutionService.connect("Connect request from GUI"); + } + } + ); + } + }); + + updateGUI(); + return view; + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventPumpStatusChanged c) { + Activity activity = getActivity(); + if (activity != null) { + 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}"); + } + } + ); + } + } + + @Subscribe + public void onStatusEvent(final EventDanaRNewStatus s) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventTempBasalChange s) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange s) { + updateGUI(); + } + + // GUI functions + private void updateGUI() { + Activity activity = getActivity(); + if (activity != null && basaBasalRateView != null) + activity.runOnUiThread(new Runnable() { + @SuppressLint("SetTextI18n") + @Override + public void run() { + DanaRPump pump = DanaRPump.getInstance(); + if (pump.lastConnection.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); + int agoMin = (int) (agoMsec / 60d / 1000d); + lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")"); + SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d); + } + if (pump.lastBolusTime.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastBolusTime.getTime(); + double agoHours = agoMsec / 60d / 60d / 1000d; + if (agoHours < 6) // max 6h back + lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); + else lastBolusView.setText(""); + } + + dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U"); + SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d); + basaBasalRateView.setText("( " + (pump.activeProfile + 1) + " ) " + DecimalFormatter.to2Decimal(getPlugin().getBaseBasalRate()) + " U/h"); + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + tempBasalView.setText(MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()).toStringFull()); + } else { + tempBasalView.setText(""); + } + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).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.isNewPump) { + firmwareView.setText(String.format(MainApp.sResources.getString(R.string.danar_model), pump.model, pump.protocol, pump.productCode)); + } else { + firmwareView.setText("OLD"); + } + } + }); + + } + +} 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 new file mode 100644 index 0000000000..cf2cad1527 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -0,0 +1,741 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.support.annotation.Nullable; + +import com.squareup.otto.Subscribe; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.Objects; + +import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventAppExit; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.interfaces.PumpDescription; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.Round; + +/** + * Created by mike on 05.08.2016. + */ +public class DanaRv2Plugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface { + private static Logger log = LoggerFactory.getLogger(DanaRv2Plugin.class); + + @Override + public String getFragmentClass() { + return DanaRv2Fragment.class.getName(); + } + + static boolean fragmentPumpEnabled = false; + static boolean fragmentProfileEnabled = false; + static boolean fragmentPumpVisible = false; + + public static DanaRv2ExecutionService sExecutionService; + + + private static DanaRPump pump = DanaRPump.getInstance(); + + public static PumpDescription pumpDescription = new PumpDescription(); + + public DanaRv2Plugin() { + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + + Context context = MainApp.instance().getApplicationContext(); + Intent intent = new Intent(context, DanaRv2ExecutionService.class); + context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + MainApp.bus().register(this); + + pumpDescription.isBolusCapable = true; + pumpDescription.bolusStep = 0.1d; + + pumpDescription.isExtendedBolusCapable = true; + pumpDescription.extendedBolusStep = 0.05d; + pumpDescription.extendedBolusDurationStep = 30; + pumpDescription.extendedBolusMaxDuration = 8 * 60; + + pumpDescription.isTempBasalCapable = true; + pumpDescription.tempBasalStyle = PumpDescription.PERCENT; + + pumpDescription.maxTempPercent = 200; + pumpDescription.tempPercentStep = 10; + + pumpDescription.tempDurationStep = 60; + pumpDescription.tempMaxDuration = 24 * 60; + + + pumpDescription.isSetBasalProfileCapable = true; + pumpDescription.basalStep = 0.01d; + pumpDescription.basalMinimumRate = 0.04d; + + pumpDescription.isRefillingCapable = true; + } + + ServiceConnection mConnection = new ServiceConnection() { + + public void onServiceDisconnected(ComponentName name) { + log.debug("Service is disconnected"); + sExecutionService = null; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + log.debug("Service is connected"); + DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service; + sExecutionService = mLocalBinder.getServiceInstance(); + } + }; + + @SuppressWarnings("UnusedParameters") + @Subscribe + public void onStatusEvent(final EventAppExit e) { + MainApp.instance().getApplicationContext().unbindService(mConnection); + } + + // Plugin base interface + @Override + public int getType() { + return PluginBase.PUMP; + } + + @Override + public String getName() { + return MainApp.instance().getString(R.string.danarv2pump); + } + + @Override + public String getNameShort() { + String name = MainApp.sResources.getString(R.string.danarpump_shortname); + if (!name.trim().isEmpty()) { + //only if translation exists + return name; + } + // use long name as fallback + return getName(); + } + + @Override + public boolean isEnabled(int type) { + if (type == PluginBase.PROFILE) return fragmentProfileEnabled && fragmentPumpEnabled; + else if (type == PluginBase.PUMP) return fragmentPumpEnabled; + else if (type == PluginBase.CONSTRAINTS) return fragmentPumpEnabled; + return false; + } + + @Override + public boolean isVisibleInTabs(int type) { + if (type == PluginBase.PROFILE || type == PluginBase.CONSTRAINTS) return false; + else if (type == PluginBase.PUMP) return fragmentPumpVisible; + return false; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return type == PUMP; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == PluginBase.PROFILE) + this.fragmentProfileEnabled = fragmentEnabled; + else if (type == PluginBase.PUMP) + this.fragmentPumpEnabled = fragmentEnabled; + // if pump profile was enabled need to switch to another too + if (type == PluginBase.PUMP && !fragmentEnabled && this.fragmentProfileEnabled) { + setFragmentEnabled(PluginBase.PROFILE, false); + setFragmentVisible(PluginBase.PROFILE, false); + MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentEnabled(PluginBase.PROFILE, true); + MainApp.getSpecificPlugin(NSProfilePlugin.class).setFragmentVisible(PluginBase.PROFILE, true); + } + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == PluginBase.PUMP) + this.fragmentPumpVisible = fragmentVisible; + } + + @Override + public boolean isFakingTempsByExtendedBoluses() { + return false; + } + + @Override + public boolean isInitialized() { + return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled; + } + + @Override + public boolean isSuspended() { + return pump.pumpSuspended; + } + + @Override + public boolean isBusy() { + if (sExecutionService == null) return false; + return sExecutionService.isConnected() || sExecutionService.isConnecting(); + } + + // Pump interface + @Override + public int setNewBasalProfile(Profile profile) { + if (sExecutionService == null) { + log.error("setNewBasalProfile sExecutionService is null"); + return FAILED; + } + if (!isInitialized()) { + log.error("setNewBasalProfile not initialized"); + Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + return FAILED; + } else { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + } + if (!sExecutionService.updateBasalsInPump(profile)) { + Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + return FAILED; + } else { + MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); + MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); + return SUCCESS; + } + } + + @Override + public boolean isThisProfileSet(Profile profile) { + if (!isInitialized()) + return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS + if (pump.pumpProfiles == null) + return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS + int basalValues = pump.basal48Enable ? 48 : 24; + int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60; + for (int h = 0; h < basalValues; h++) { + Double pumpValue = pump.pumpProfiles[pump.activeProfile][h]; + Double profileValue = profile.getBasal(h * basalIncrement); + if (profileValue == null) return true; + if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) { + log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue); + return false; + } + } + return true; + } + + @Override + public Date lastDataTime() { + return pump.lastConnection; + } + + @Override + public void refreshDataFromPump(String reason) { + if (!isConnected() && !isConnecting()) { + doConnect(reason); + } + } + + @Override + public double getBaseBasalRate() { + return pump.currentBasal; + } + + @Override + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { + Treatment t = new Treatment(detailedBolusInfo.insulinInterface); + boolean connectionOK = false; + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) + connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, new Date().getTime() + detailedBolusInfo.carbTime * 60 * 1000 + 1000, t); // +1000 to make the record different + PumpEnactResult result = new PumpEnactResult(); + result.success = connectionOK; + result.bolusDelivered = t.insulin; + result.carbsDelivered = detailedBolusInfo.carbs; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + if (Config.logPumpActions) + log.debug("deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered); + return result; + } else { + PumpEnactResult result = new PumpEnactResult(); + result.success = false; + result.bolusDelivered = 0d; + result.carbsDelivered = 0d; + result.comment = MainApp.instance().getString(R.string.danar_invalidinput); + log.error("deliverTreatment: Invalid input"); + return result; + } + } + + @Override + public void stopBolusDelivering() { + if (sExecutionService == null) { + log.error("stopBolusDelivering sExecutionService is null"); + return; + } + sExecutionService.bolusStop(); + } + + // This is called from APS + @Override + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + // Recheck pump status if older than 30 min + if (pump.lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) { + doConnect("setTempBasalAbsolute old data"); + } + + PumpEnactResult result = new PumpEnactResult(); + + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + absoluteRate = configBuilderPlugin.applyBasalConstraints(absoluteRate); + + final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d; + final boolean doLowTemp = absoluteRate < getBaseBasalRate(); + final boolean doHighTemp = absoluteRate > getBaseBasalRate(); + + if (doTempOff) { + // If temp in progress + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Stopping temp basal (doTempOff)"); + return cancelTempBasal(); + } + result.success = true; + result.enacted = false; + result.percent = 100; + result.isPercent = true; + result.isTempCancel = true; + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: doTempOff OK"); + return result; + } + + if (doLowTemp || doHighTemp) { + Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue(); + if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue(); + else percentRate = Round.floorTo((double) percentRate, 10d).intValue(); + if (percentRate > 500) // Special high temp 500/15min + percentRate = 500; + // Check if some temp is already in progress + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + // Correct basal already set ? + if (MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()).percentRate == percentRate) { + result.success = true; + result.percent = percentRate; + result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); + result.enacted = false; + result.duration = ((Double) MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory()).intValue(); + result.isPercent = true; + result.isTempCancel = false; + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); + return result; + } } + // 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 (!result.success) { + log.error("setTempBasalAbsolute: Failed to set hightemp basal"); + return result; + } + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: hightemp basal set ok"); + return result; + } + // We should never end here + log.error("setTempBasalAbsolute: Internal error"); + result.success = false; + result.comment = "Internal error"; + return result; + } + + @Override + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) { + PumpEnactResult result = new PumpEnactResult(); + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + percent = configBuilderPlugin.applyBasalConstraints(percent); + if (percent < 0) { + result.isTempCancel = false; + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_invalidinput); + log.error("setTempBasalPercent: Invalid input"); + return result; + } + if (percent > getPumpDescription().maxTempPercent) + percent = getPumpDescription().maxTempPercent; + if (pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { + result.enacted = false; + result.success = true; + result.isTempCancel = false; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; + result.isPercent = true; + if (Config.logPumpActions) + log.debug("setTempBasalPercent: Correct value already set"); + return result; + } + int durationInHours = Math.max(durationInMinutes / 60, 1); + boolean connectionOK = sExecutionService.tempBasal(percent, durationInHours); + if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; + result.isPercent = true; + if (Config.logPumpActions) + log.debug("setTempBasalPercent: OK"); + return result; + } + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.tempbasaldeliveryerror); + log.error("setTempBasalPercent: Failed to set temp basal"); + return result; + } + + public PumpEnactResult setHighTempBasalPercent(Integer percent) { + PumpEnactResult result = new PumpEnactResult(); + boolean connectionOK = sExecutionService.highTempBasal(percent); + if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = pump.tempBasalRemainingMin; + result.percent = pump.tempBasalPercent; + result.isPercent = true; + if (Config.logPumpActions) + log.debug("setHighTempBasalPercent: OK"); + return result; + } + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + log.error("setHighTempBasalPercent: Failed to set temp basal"); + return result; + } + + @Override + public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { + ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); + insulin = configBuilderPlugin.applyBolusConstraints(insulin); + // needs to be rounded + insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); + + PumpEnactResult result = new PumpEnactResult(); + if (pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + result.enacted = false; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; + result.isPercent = false; + result.isTempCancel = false; + if (Config.logPumpActions) + log.debug("setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulin); + return result; + } + int durationInHalfHours = Math.max(durationInMinutes / 30, 1); + boolean connectionOK = sExecutionService.extendedBolus(insulin, durationInHalfHours); + if (connectionOK && pump.isExtendedInProgress && Math.abs(pump.extendedBolusAmount - insulin) < getPumpDescription().extendedBolusStep) { + result.enacted = true; + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + result.isTempCancel = false; + result.duration = pump.extendedBolusRemainingMinutes; + result.absolute = pump.extendedBolusAbsoluteRate; + result.bolusDelivered = pump.extendedBolusAmount; + result.isPercent = false; + if (Config.logPumpActions) + log.debug("setExtendedBolus: OK"); + return result; + } + result.enacted = false; + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + log.error("setExtendedBolus: Failed to extended bolus"); + return result; + } + + @Override + public PumpEnactResult cancelTempBasal() { + PumpEnactResult result = new PumpEnactResult(); + if (pump.isTempBasalInProgress) { + sExecutionService.tempBasalStop(); + result.enacted = true; + result.isTempCancel = true; + } + if (!pump.isTempBasalInProgress) { + result.success = true; + result.isTempCancel = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + if (Config.logPumpActions) + log.debug("cancelRealTempBasal: OK"); + return result; + } else { + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + result.isTempCancel = true; + log.error("cancelRealTempBasal: Failed to cancel temp basal"); + return result; + } + } + + @Override + public PumpEnactResult cancelExtendedBolus() { + PumpEnactResult result = new PumpEnactResult(); + if (pump.isExtendedInProgress) { + sExecutionService.extendedBolusStop(); + result.enacted = true; + result.isTempCancel = true; + } + if (!pump.isExtendedInProgress) { + result.success = true; + result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + if (Config.logPumpActions) + log.debug("cancelExtendedBolus: OK"); + return result; + } else { + result.success = false; + result.comment = MainApp.instance().getString(R.string.danar_valuenotsetproperly); + log.error("cancelExtendedBolus: Failed to cancel extended bolus"); + return result; + } + } + + public static void doConnect(String from) { + if (sExecutionService != null) sExecutionService.connect(from); + } + + public static boolean isConnected() { + return sExecutionService != null && sExecutionService.isConnected(); + } + + public static boolean isConnecting() { + return sExecutionService != null && sExecutionService.isConnecting(); + } + + public static void doDisconnect(String from) { + if (sExecutionService != null) sExecutionService.disconnect(from); + } + + @Override + public JSONObject getJSONStatus() { + if (pump.lastConnection.getTime() + 5 * 60 * 1000L < new Date().getTime()) { + return null; + } + JSONObject pumpjson = new JSONObject(); + JSONObject battery = new JSONObject(); + JSONObject status = new JSONObject(); + JSONObject extended = new JSONObject(); + try { + battery.put("percent", pump.batteryRemaining); + status.put("status", pump.pumpSuspended ? "suspended" : "normal"); + status.put("timestamp", DateUtil.toISOString(pump.lastConnection)); + extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); + extended.put("PumpIOB", pump.iob); + if (pump.lastBolusTime.getTime() != 0) { + extended.put("LastBolus", pump.lastBolusTime.toLocaleString()); + extended.put("LastBolusAmount", pump.lastBolusAmount); + } + TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(new Date().getTime())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()); + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); + extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); + extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); + } + extended.put("BaseBasalRate", getBaseBasalRate()); + try { + extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); + } catch (Exception e) { + } + + pumpjson.put("battery", battery); + pumpjson.put("status", status); + pumpjson.put("extended", extended); + pumpjson.put("reservoir", (int) pump.reservoirRemainingUnits); + pumpjson.put("clock", DateUtil.toISOString(new Date())); + } catch (JSONException e) { + e.printStackTrace(); + } + return pumpjson; + } + + @Override + public String deviceID() { + return pump.serialNumber; + } + + @Override + public PumpDescription getPumpDescription() { + return pumpDescription; + } + + /** + * Constraint interface + */ + + @Override + public boolean isLoopEnabled() { + return true; + } + + @Override + public boolean isClosedModeEnabled() { + return true; + } + + @Override + public boolean isAutosensModeEnabled() { + return true; + } + + @Override + public boolean isAMAModeEnabled() { + return true; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Double applyBasalConstraints(Double absoluteRate) { + double origAbsoluteRate = absoluteRate; + if (pump != null) { + if (absoluteRate > pump.maxBasal) { + absoluteRate = pump.maxBasal; + if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) + log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); + } + } + return absoluteRate; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Integer applyBasalConstraints(Integer percentRate) { + Integer origPercentRate = percentRate; + if (percentRate < 0) percentRate = 0; + if (percentRate > getPumpDescription().maxTempPercent) + percentRate = getPumpDescription().maxTempPercent; + if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) + log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); + return percentRate; + } + + @SuppressWarnings("PointlessBooleanExpression") + @Override + public Double applyBolusConstraints(Double insulin) { + double origInsulin = insulin; + if (pump != null) { + if (insulin > pump.maxBolus) { + insulin = pump.maxBolus; + if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) + log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); + } + } + return insulin; + } + + @Override + public Integer applyCarbsConstraints(Integer carbs) { + return carbs; + } + + @Override + public Double applyMaxIOBConstraints(Double maxIob) { + return maxIob; + } + + @Nullable + @Override + public ProfileStore getProfile() { + if (pump.lastSettingsRead.getTime() == 0) + return null; // no info now + return pump.createConvertedProfile(); + } + + @Override + public String getProfileName() { + return pump.createConvertedProfileName(); + } + + // Reply for sms communicator + public String shortStatus(boolean veryShort) { + String ret = ""; + if (pump.lastConnection.getTime() != 0) { + Long agoMsec = new Date().getTime() - pump.lastConnection.getTime(); + int agoMin = (int) (agoMsec / 60d / 1000d); + ret += "LastConn: " + agoMin + " minago\n"; + } + if (pump.lastBolusTime.getTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n"; + } + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + ret += "Temp: " + MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()).toStringFull() + "\n"; + } + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).toString() + "\n"; + } + if (!veryShort) { + ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; + } + ret += "IOB: " + pump.iob + "U\n"; + ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; + ret += "Batt: " + pump.batteryRemaining + "\n"; + return ret; + } + // TODO: daily total constraint + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRHistoryActivity.java similarity index 87% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/History/DanaRHistoryActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRHistoryActivity.java index 158d0b43cb..1391b753f8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/History/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRHistoryActivity.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.History; +package info.nightscout.androidaps.plugins.PumpDanaRv2.History; import android.app.Activity; import android.content.ComponentName; @@ -21,16 +21,11 @@ import android.widget.Button; import android.widget.Spinner; import android.widget.TextView; -import com.j256.ormlite.dao.Dao; -import com.j256.ormlite.stmt.PreparedQuery; -import com.j256.ormlite.stmt.QueryBuilder; -import com.j256.ormlite.stmt.Where; import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -39,12 +34,11 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.History.DanaRNSHistorySync; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.DanaRKorean.Services.ExecutionService; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.ToastUtils; @@ -53,12 +47,12 @@ public class DanaRHistoryActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRv2ExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; - static NSProfile profile = null; + static Profile profile = null; Spinner historyTypeSpinner; TextView statusView; @@ -96,7 +90,7 @@ public class DanaRHistoryActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRv2ExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -132,7 +126,7 @@ public class DanaRHistoryActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -249,7 +243,7 @@ public class DanaRHistoryActivity extends Activity { clearCardView(); } }); - profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); finish(); @@ -273,12 +267,12 @@ public class DanaRHistoryActivity extends Activity { @Override public void onBindViewHolder(HistoryViewHolder holder, int position) { DanaRHistoryRecord record = historyList.get(position); - holder.time.setText(DateUtil.dateAndTimeString(record.getRecordDate())); - holder.value.setText(DecimalFormatter.to2Decimal(record.getRecordValue())); - holder.stringvalue.setText(record.getStringRecordValue()); - holder.bolustype.setText(record.getBolusType()); - holder.duration.setText(DecimalFormatter.to0Decimal(record.getRecordDuration())); - holder.alarm.setText(record.getRecordAlarm()); + holder.time.setText(DateUtil.dateAndTimeString(record.recordDate)); + holder.value.setText(DecimalFormatter.to2Decimal(record.recordValue)); + holder.stringvalue.setText(record.stringRecordValue); + holder.bolustype.setText(record.bolusType); + holder.duration.setText(DecimalFormatter.to0Decimal(record.recordDuration)); + holder.alarm.setText(record.recordAlarm); switch (showingType) { case RecordTypes.RECORD_TYPE_ALARM: holder.time.setVisibility(View.VISIBLE); @@ -303,10 +297,10 @@ public class DanaRHistoryActivity extends Activity { holder.alarm.setVisibility(View.GONE); break; case RecordTypes.RECORD_TYPE_DAILY: - holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + "U"); - holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + "U"); - holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus() + record.getRecordDailyBasal()) + "U"); - holder.time.setText(DateUtil.dateString(record.getRecordDate())); + holder.dailybasal.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + "U"); + holder.dailybolus.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + "U"); + holder.dailytotal.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus + record.recordDailyBasal) + "U"); + holder.time.setText(DateUtil.dateString(record.recordDate)); holder.time.setVisibility(View.VISIBLE); holder.value.setVisibility(View.GONE); holder.stringvalue.setVisibility(View.GONE); @@ -318,7 +312,7 @@ public class DanaRHistoryActivity extends Activity { holder.alarm.setVisibility(View.GONE); break; case RecordTypes.RECORD_TYPE_GLUCOSE: - holder.value.setText(NSProfile.toUnitsString(record.getRecordValue(), record.getRecordValue() * Constants.MGDL_TO_MMOLL, profile.getUnits())); + holder.value.setText(Profile.toUnitsString(record.recordValue, record.recordValue * Constants.MGDL_TO_MMOLL, profile.getUnits())); // rest is the same case RecordTypes.RECORD_TYPE_CARBO: case RecordTypes.RECORD_TYPE_BASALHOUR: @@ -389,19 +383,8 @@ public class DanaRHistoryActivity extends Activity { } private void loadDataFromDB(byte type) { - try { - Dao dao = MainApp.getDbHelper().getDaoDanaRHistory(); - QueryBuilder queryBuilder = dao.queryBuilder(); - queryBuilder.orderBy("recordDate", false); - Where where = queryBuilder.where(); - where.eq("recordCode", type); - queryBuilder.limit(200L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - historyList = dao.query(preparedQuery); - } catch (SQLException e) { - e.printStackTrace(); - historyList = new ArrayList<>(); - } + historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); + runOnUiThread(new Runnable() { @Override public void run() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRStatsActivity.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRStatsActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRStatsActivity.java index 7d5bf0c548..d366c42df7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/History/DanaRStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/History/DanaRStatsActivity.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaR.History; +package info.nightscout.androidaps.plugins.PumpDanaRv2.History; import android.app.Activity; import android.content.ComponentName; @@ -50,12 +50,13 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.db.DanaRHistoryRecord; import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.CircadianPercentageProfile.CircadianPercentageProfilePlugin; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.DanaR.Services.ExecutionService; -import info.nightscout.androidaps.plugins.DanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -63,7 +64,7 @@ public class DanaRStatsActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; + private static DanaRv2ExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -89,7 +90,7 @@ public class DanaRStatsActivity extends Activity { @Override public void onStart() { super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); + Intent intent = new Intent(this, DanaRv2ExecutionService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @@ -140,7 +141,7 @@ public class DanaRStatsActivity extends Activity { public void onServiceConnected(ComponentName name, IBinder service) { log.debug("Service is connected"); mBounded = true; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; + DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service; mExecutionService = mLocalBinder.getServiceInstance(); } }; @@ -167,18 +168,15 @@ public class DanaRStatsActivity extends Activity { decimalFormat = new DecimalFormat("0.000"); llm = new LinearLayoutManager(this); - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - TBB = preferences.getString("TBB", "10.00"); + TBB = SP.getString("TBB", "10.00"); totalBaseBasal.setText(TBB); - ProfileInterface pi = ConfigBuilderPlugin.getActiveProfile(); + ProfileInterface pi = ConfigBuilderPlugin.getActiveProfileInterface(); if (pi != null && pi instanceof CircadianPercentageProfilePlugin) { double cppTBB = ((CircadianPercentageProfilePlugin) pi).baseBasalSum(); totalBaseBasal.setText(decimalFormat.format(cppTBB)); - SharedPreferences.Editor edit = preferences.edit(); - edit.putString("TBB", totalBaseBasal.getText().toString()); - edit.commit(); - TBB = preferences.getString("TBB", ""); + SP.putString("TBB", totalBaseBasal.getText().toString()); + TBB = SP.getString("TBB", ""); } // stats table @@ -326,10 +324,8 @@ public class DanaRStatsActivity extends Activity { if (hasFocus) { totalBaseBasal.getText().clear(); } else { - SharedPreferences.Editor edit = preferences.edit(); - edit.putString("TBB", totalBaseBasal.getText().toString()); - edit.commit(); - TBB = preferences.getString("TBB", ""); + SP.putString("TBB", totalBaseBasal.getText().toString()); + TBB = SP.getString("TBB", ""); loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0); @@ -341,19 +337,8 @@ public class DanaRStatsActivity extends Activity { } private void loadDataFromDB(byte type) { - try { - Dao dao = MainApp.getDbHelper().getDaoDanaRHistory(); - QueryBuilder queryBuilder = dao.queryBuilder(); - queryBuilder.orderBy("recordDate", false); - Where where = queryBuilder.where(); - where.eq("recordCode", type); - queryBuilder.limit(10L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - historyList = dao.query(preparedQuery); - } catch (SQLException e) { - e.printStackTrace(); - historyList = new ArrayList<>(); - } + historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(type); + runOnUiThread(new Runnable() { @Override public void run() { @@ -379,7 +364,7 @@ public class DanaRStatsActivity extends Activity { double weighted07 = 0d; for (DanaRHistoryRecord record : historyList) { - double tdd = record.getRecordDailyBolus() + record.getRecordDailyBasal(); + double tdd = record.recordDailyBolus + record.recordDailyBasal; // Create the table row TableRow tr = new TableRow(DanaRStatsActivity.this); @@ -392,19 +377,19 @@ public class DanaRStatsActivity extends Activity { // Here create the TextView dynamically TextView labelDATE = new TextView(DanaRStatsActivity.this); labelDATE.setId(200 + i); - labelDATE.setText(df.format(new Date(record.getRecordDate()))); + labelDATE.setText(df.format(new Date(record.recordDate))); labelDATE.setTextColor(Color.WHITE); tr.addView(labelDATE); TextView labelBASAL = new TextView(DanaRStatsActivity.this); labelBASAL.setId(300 + i); - labelBASAL.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBasal()) + " U"); + labelBASAL.setText(DecimalFormatter.to2Decimal(record.recordDailyBasal) + " U"); labelBASAL.setTextColor(Color.WHITE); tr.addView(labelBASAL); TextView labelBOLUS = new TextView(DanaRStatsActivity.this); labelBOLUS.setId(400 + i); - labelBOLUS.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + " U"); + labelBOLUS.setText(DecimalFormatter.to2Decimal(record.recordDailyBolus) + " U"); labelBOLUS.setTextColor(Color.WHITE); tr.addView(labelBOLUS); @@ -461,7 +446,7 @@ public class DanaRStatsActivity extends Activity { TableLayout.LayoutParams.WRAP_CONTENT)); } - if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).getRecordDate())).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) { + if (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).recordDate)).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))) { statsMessage.setVisibility(View.VISIBLE); statsMessage.setText(getString(R.string.danar_stats_olddata_Message)); @@ -474,7 +459,7 @@ public class DanaRStatsActivity extends Activity { i = 0; for (DanaRHistoryRecord record : historyList) { - double tdd = record.getRecordDailyBolus() + record.getRecordDailyBasal(); + double tdd = record.recordDailyBolus + record.recordDailyBasal; if (i == 0) { weighted03 = tdd; weighted05 = tdd; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java similarity index 95% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/SerialIOThread.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java index 50f9e855ef..0b67b6acc6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.DanaRKorean; +package info.nightscout.androidaps.plugins.PumpDanaRv2; import android.bluetooth.BluetoothSocket; @@ -14,8 +14,9 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaRKorean.comm.MessageHashTable; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MessageHashTable_v2; import info.nightscout.utils.CRC; /** @@ -72,7 +73,7 @@ public class SerialIOThread extends Thread { message = processedMessage; } else { // get it from hash table - message = MessageHashTable.findMessage(command); + message = MessageHashTable_v2.findMessage(command); } if (Config.logDanaMessageDetail) @@ -177,7 +178,7 @@ public class SerialIOThread extends Thread { if (!message.received) { log.warn("Reply not received " + message.getMessageName()); if (message.getCommand() == 0xF0F1) { - DanaRKoreanPlugin.getDanaRPump().isNewPump = false; + DanaRPump.getInstance().isNewPump = false; log.debug("Old firmware detected"); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java similarity index 68% rename from app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MessageHashTable.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java index 084ad11074..0940efd73f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/comm/MessageHashTable.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java @@ -1,37 +1,19 @@ -package info.nightscout.androidaps.plugins.DanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; -import info.nightscout.androidaps.plugins.DanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusProgress; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgBolusStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgError; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAlarm; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryAll; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryBolus; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryCarbo; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryDailyInsulin; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryGlucose; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryNew; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgHistoryNewDone; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgPCCommStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetCarbsEntry; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetExtendedBolusStop; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetSingleBasalProfile; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStart; -import info.nightscout.androidaps.plugins.DanaR.comm.MsgSetTempBasalStop; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; + /** * Created by mike on 28.05.2016. */ -public class MessageHashTable { - private static Logger log = LoggerFactory.getLogger(MessageHashTable.class); +public class MessageHashTable_v2 { + private static Logger log = LoggerFactory.getLogger(MessageHashTable_v2.class); public static HashMap messages = null; @@ -42,13 +24,16 @@ public class MessageHashTable { put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I + + put(new MsgStatusTempBasal_v2()); // 0x0205 CMD_PUMP_EXERCISE_MODE + put(new MsgStatusBolusExtended_v2()); // 0x0207 CMD_PUMP_EXPANS_INS_I + put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO + put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP @@ -61,7 +46,12 @@ public class MessageHashTable { put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM + put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY + put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL + put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND + put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR + put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I @@ -70,11 +60,21 @@ public class MessageHashTable { put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I + put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS + put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER + 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 MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S + put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE + put(new MsgCheckValue_v2()); // 0xF0F1 CMD_PUMP_CHECK_VALUE + put(new MsgStatusAPS_v2()); // 0xE001 CMD_PUMPSTATUS_APS + put(new MsgSetAPSTempBasalStart_v2()); // 0xE002 CMD_PUMPSET_APSTEMP + put(new MsgHistoryEvents_v2()); // 0xE003 CMD_GET_HISTORY + put(new MsgSetHistoryEntry_v2()); // 0xE004 CMD_SET_HISTORY_ENTRY } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java new file mode 100644 index 0000000000..801cfb80cc --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java @@ -0,0 +1,70 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.utils.ToastUtils; + +/** + * Created by mike on 30.06.2016. + */ +public class MsgCheckValue_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgCheckValue_v2.class); + + public MsgCheckValue_v2() { + SetCommand(0xF0F1); + } + + @Override + public void handleMessage(byte[] bytes) { + DanaRPump pump = DanaRPump.getInstance(); + + pump.isNewPump = true; + log.debug("New firmware confirmed"); + + pump.model = intFromBuff(bytes, 0, 1); + pump.protocol = intFromBuff(bytes, 1, 1); + pump.productCode = intFromBuff(bytes, 2, 1); + if (pump.model != DanaRPump.EXPORT_MODEL) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); + DanaRv2Plugin.doDisconnect("Wrong Model"); + log.debug("Wrong model selected"); + } + + if (pump.protocol != 2) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); + DanaRKoreanPlugin.doDisconnect("Wrong Model"); + log.debug("Wrong model selected. Switching to non APS DanaR"); + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PUMP, false); + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentVisible(PluginBase.PUMP, false); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PUMP, true); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentVisible(PluginBase.PUMP, true); + + //If profile coming from pump, switch it as well + if(MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PROFILE)){ + (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PROFILE, false); + (MainApp.getSpecificPlugin(DanaRPlugin.class)).setFragmentEnabled(PluginBase.PROFILE, true); + } + + MainApp.getConfigBuilder().storeSettings(); + MainApp.bus().post(new EventRefreshGui(false)); + return; + } + if (Config.logDanaMessageDetail) { + log.debug("Model: " + String.format("%02X ", pump.model)); + log.debug("Protocol: " + String.format("%02X ", pump.protocol)); + log.debug("Product Code: " + String.format("%02X ", pump.productCode)); + } + } + +} 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 new file mode 100644 index 0000000000..fa3cff5c39 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java @@ -0,0 +1,141 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.GregorianCalendar; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgHistoryEvents_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgHistoryEvents_v2.class); + public boolean done; + + public static long lastEventTimeLoaded = 0; + + public MsgHistoryEvents_v2(long from) { + SetCommand(0xE003); + GregorianCalendar gfrom = new GregorianCalendar(); + gfrom.setTimeInMillis(from); + AddParamDate(gfrom); + done = false; + } + + public MsgHistoryEvents_v2() { + SetCommand(0xE003); + AddParamByte((byte) 0); + AddParamByte((byte) 1); + AddParamByte((byte) 1); + AddParamByte((byte) 0); + AddParamByte((byte) 0); + done = false; + } + + @Override + public void handleMessage(byte[] bytes) { + byte recordCode = (byte) intFromBuff(bytes, 0, 1); + + // Last record + if (recordCode == (byte) 0xFF) { + done = true; + return; + } + + Date datetime = dateTimeSecFromBuff(bytes, 1); // 6 bytes + int param1 = intFromBuff(bytes, 7, 2); + int param2 = intFromBuff(bytes, 9, 2); + + TemporaryBasal temporaryBasal = new TemporaryBasal(); + temporaryBasal.date = datetime.getTime(); + temporaryBasal.source = Source.PUMP; + temporaryBasal.pumpId = datetime.getTime(); + + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = datetime.getTime(); + extendedBolus.source = Source.PUMP; + extendedBolus.pumpId = datetime.getTime(); + + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.date = datetime.getTime(); + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = datetime.getTime(); + detailedBolusInfo.source = Source.PUMP; + + switch (recordCode) { + case DanaRPump.TEMPSTART: + log.debug("EVENT TEMPSTART (" + recordCode + ") " + datetime.toLocaleString() + " Ratio: " + param1 + "% Duration: " + param2 + "min"); + temporaryBasal.percentRate = param1; + temporaryBasal.durationInMinutes = param2; + MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal); + break; + case DanaRPump.TEMPSTOP: + log.debug("EVENT TEMPSTOP (" + recordCode + ") " + datetime.toLocaleString()); + MainApp.getConfigBuilder().addToHistoryTempBasal(temporaryBasal); + break; + case DanaRPump.EXTENDEDSTART: + log.debug("EVENT EXTENDEDSTART (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + extendedBolus.insulin = param1 / 100d; + extendedBolus.durationInMinutes = param2; + MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + break; + case DanaRPump.EXTENDEDSTOP: + log.debug("EVENT EXTENDEDSTOP (" + recordCode + ") " + datetime.toLocaleString() + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); + MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + break; + case DanaRPump.BOLUS: + log.debug("EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + detailedBolusInfo.insulin = param1 / 100d; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + break; + case DanaRPump.DUALBOLUS: + log.debug("EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + detailedBolusInfo.insulin = param1 / 100d; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + break; + case DanaRPump.DUALEXTENDEDSTART: + log.debug("EVENT DUALEXTENDEDSTART (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + extendedBolus.insulin = param1 / 100d; + extendedBolus.durationInMinutes = param2; + MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + break; + case DanaRPump.DUALEXTENDEDSTOP: + log.debug("EVENT DUALEXTENDEDSTOP (" + recordCode + ") " + datetime.toLocaleString() + " Delivered: " + (param1 / 100d) + "U RealDuration: " + param2 + "min"); + MainApp.getConfigBuilder().addToHistoryExtendedBolus(extendedBolus); + break; + case DanaRPump.SUSPENDON: + log.debug("EVENT SUSPENDON (" + recordCode + ") " + datetime.toLocaleString()); + break; + case DanaRPump.SUSPENDOFF: + log.debug("EVENT SUSPENDOFF (" + recordCode + ") " + datetime.toLocaleString()); + break; + case DanaRPump.REFILL: + log.debug("EVENT REFILL (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + break; + case DanaRPump.PRIME: + log.debug("EVENT PRIME (" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U"); + break; + case DanaRPump.PROFILECHANGE: + log.debug("EVENT PROFILECHANGE (" + recordCode + ") " + datetime.toLocaleString() + " No: " + param1 + "U CurrentRate: " + param2 + "U/h"); + break; + case DanaRPump.CARBS: + log.debug("EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g"); + detailedBolusInfo.carbs = param1; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + break; + default: + log.debug("Event: " + recordCode + " " + datetime.toLocaleString() + " Param1: " + param1 + " Param2: " + param2); + break; + } + + if (datetime.getTime() > lastEventTimeLoaded) + lastEventTimeLoaded = datetime.getTime(); + + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart_v2.java new file mode 100644 index 0000000000..da4db61362 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetAPSTempBasalStart_v2.java @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgSetAPSTempBasalStart_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSetAPSTempBasalStart_v2.class); + + public MsgSetAPSTempBasalStart_v2() { + SetCommand(0xE002); + } + + public MsgSetAPSTempBasalStart_v2(int percent) { + this(); + + //HARDCODED LIMITS + if (percent < 0) percent = 0; + if (percent > 500) percent = 500; + + AddParamInt(percent); + if (percent < 100) { + AddParamByte((byte) 0xA0); // 160 + if (Config.logDanaMessageDetail) + log.debug("APS Temp basal start percent: " + percent + " duration 30 min"); + } else { + AddParamByte((byte) 0x96); // 150 + if (Config.logDanaMessageDetail) + log.debug("APS Temp basal start percent: " + percent + " duration 15 min"); + } + + } + + public void handleMessage(byte[] bytes) { + int result = intFromBuff(bytes, 0, 1); + if (result != 1) { + failed = true; + log.debug("Set APS temp basal start result: " + result + " FAILED!!!"); + } else { + if (Config.logDanaMessageDetail) + log.debug("Set APS temp basal start result: " + result); + } + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetHistoryEntry_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetHistoryEntry_v2.java new file mode 100644 index 0000000000..abeb656f03 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgSetHistoryEntry_v2.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; +import java.util.GregorianCalendar; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgSetHistoryEntry_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgSetHistoryEntry_v2.class); + + public MsgSetHistoryEntry_v2() { + SetCommand(0xE004); + } + + public MsgSetHistoryEntry_v2(int type, long time, int param1, int param2) { + this(); + + AddParamByte((byte) type); + GregorianCalendar gtime = new GregorianCalendar(); + gtime.setTimeInMillis(time); + AddParamDateTime(gtime); + AddParamInt(param1); + AddParamInt(param2); + if (Config.logDanaMessageDetail) + log.debug("Set history entry: type: " + type + " date: " + new Date(time).toString() + " param1: " + param1 + " param2: " + param2); + } + + @Override + public void handleMessage(byte[] bytes) { + int result = intFromBuff(bytes, 0, 1); + if (result != 1) { + failed = true; + log.debug("Set history entry result: " + result + " FAILED!!!"); + } else { + if (Config.logDanaMessageDetail) + log.debug("Set history entry result: " + result); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPS_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPS_v2.java new file mode 100644 index 0000000000..c2f87ee36a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusAPS_v2.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgStatusAPS_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusAPS_v2.class); + + public MsgStatusAPS_v2() { + SetCommand(0xE001); + } + + public void handleMessage(byte[] bytes) { + double iob = intFromBuff(bytes, 0, 2) / 100d; + double deliveredSoFar = intFromBuff(bytes, 2, 2) / 100d; + + DanaRPump pump = DanaRPump.getInstance(); + pump.iob = iob; + + if (Config.logDanaMessageDetail) { + log.debug("Delivered so far: " + deliveredSoFar); + log.debug("Current pump IOB: " + iob); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended_v2.java new file mode 100644 index 0000000000..5f4ccf960f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusBolusExtended_v2.java @@ -0,0 +1,65 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import android.support.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgStatusBolusExtended_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended_v2.class); + + public MsgStatusBolusExtended_v2() { + SetCommand(0x0207); + } + + public void handleMessage(byte[] bytes) { + boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1; + int extendedBolusHalfHours = intFromBuff(bytes, 1, 1); + int extendedBolusMinutes = extendedBolusHalfHours * 30; + + double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d; + int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3); +// This is available only on korean, but not needed now +// int extendedBolusDeliveryPulse = intFromBuff(bytes, 7, 2); +// int isEasyUIUserSleep = intFromBuff(bytes, 9, 1); + + int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60; + double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d; + Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0); + int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes; + + DanaRPump pump = DanaRPump.getInstance(); + pump.isExtendedInProgress = isExtendedInProgress; + pump.extendedBolusMinutes = extendedBolusMinutes; + pump.extendedBolusAmount = extendedBolusAmount; + pump.extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes; + pump.extendedBolusAbsoluteRate = extendedBolusAbsoluteRate; + pump.extendedBolusStart = extendedBolusStart; + pump.extendedBolusRemainingMinutes = extendedBolusRemainingMinutes; + + if (Config.logDanaMessageDetail) { + log.debug("Is extended bolus running: " + isExtendedInProgress); + log.debug("Extended bolus min: " + extendedBolusMinutes); + log.debug("Extended bolus amount: " + extendedBolusAmount); + log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes); + log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate); + log.debug("Extended bolus start: " + extendedBolusStart); + log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes); + } + } + + @NonNull + private Date getDateFromSecAgo(int tempBasalAgoSecs) { + return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal_v2.java new file mode 100644 index 0000000000..5cc8068f4d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgStatusTempBasal_v2.java @@ -0,0 +1,59 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; + +import android.support.annotation.NonNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; + +public class MsgStatusTempBasal_v2 extends MessageBase { + private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal_v2.class); + + public MsgStatusTempBasal_v2() { + SetCommand(0x0205); + } + + public void handleMessage(byte[] bytes) { + boolean isTempBasalInProgress = (intFromBuff(bytes, 0, 1) & 0x01) == 0x01; + boolean isAPSTempBasalInProgress = (intFromBuff(bytes, 0, 1) & 0x02) == 0x02; + int tempBasalPercent = intFromBuff(bytes, 1, 1); + if (tempBasalPercent > 200) tempBasalPercent = (tempBasalPercent - 200) * 10; + int tempBasalTotalSec; + if (intFromBuff(bytes, 2, 1) == 150) tempBasalTotalSec = 15 * 60; + else if (intFromBuff(bytes, 2, 1) == 160) tempBasalTotalSec = 30 * 60; + else tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60; + int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3); + int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60; + Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0); + + DanaRPump pump = DanaRPump.getInstance(); + pump.isTempBasalInProgress = isTempBasalInProgress; + pump.tempBasalPercent = tempBasalPercent; + pump.tempBasalRemainingMin = tempBasalRemainingMin; + pump.tempBasalTotalSec = tempBasalTotalSec; + pump.tempBasalStart = tempBasalStart; + + if (Config.logDanaMessageDetail) { + log.debug("Is temp basal running: " + isTempBasalInProgress); + log.debug("Is APS temp basal running: " + isAPSTempBasalInProgress); + log.debug("Current temp basal percent: " + tempBasalPercent); + log.debug("Current temp basal remaining min: " + tempBasalRemainingMin); + log.debug("Current temp basal total sec: " + tempBasalTotalSec); + log.debug("Current temp basal start: " + tempBasalStart); + } + } + + @NonNull + private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) { + return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + } + +} 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 new file mode 100644 index 0000000000..57e3607504 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -0,0 +1,555 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2.services; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Binder; +import android.os.IBinder; +import android.os.PowerManager; + +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Date; +import java.util.Set; +import java.util.UUID; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventAppExit; +import info.nightscout.androidaps.events.EventInitializationChanged; +import info.nightscout.androidaps.events.EventPreferenceChange; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.*; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRBolusStart; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.SerialIOThread; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgHistoryEvents_v2; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetAPSTempBasalStart_v2; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgSetHistoryEntry_v2; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgCheckValue_v2; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusBolusExtended_v2; +import info.nightscout.androidaps.plugins.PumpDanaRv2.comm.MsgStatusTempBasal_v2; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SP; +import info.nightscout.utils.ToastUtils; + +public class DanaRv2ExecutionService extends Service { + private static Logger log = LoggerFactory.getLogger(DanaRv2ExecutionService.class); + + private String devName; + + private SerialIOThread mSerialIOThread; + private BluetoothSocket mRfcommSocket; + private BluetoothDevice mBTDevice; + + private PowerManager.WakeLock mWakeLock; + private IBinder mBinder = new LocalBinder(); + + private DanaRPump danaRPump; + private Treatment bolusingTreatment = null; + + private static Boolean connectionInProgress = false; + private static final Object connectionLock = new Object(); + + private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); + + private long lastHistoryFetched = 0; + + private BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + String action = intent.getAction(); + if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { + log.debug("Device has disconnected " + device.getName());//Device has disconnected + if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) { + if (mSerialIOThread != null) { + mSerialIOThread.disconnect("BT disconnection broadcast"); + } + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + } + } + } + }; + + public DanaRv2ExecutionService() { + registerBus(); + MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED)); + danaRPump = DanaRPump.getInstance(); + + PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaRv2ExecutionService"); + } + + public class LocalBinder extends Binder { + public DanaRv2ExecutionService getServiceInstance() { + return DanaRv2ExecutionService.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + return START_STICKY; + } + + private void registerBus() { + try { + MainApp.bus().unregister(this); + } catch (RuntimeException x) { + // Ignore + } + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(EventAppExit event) { + if (Config.logFunctionCalls) + log.debug("EventAppExit received"); + + if (mSerialIOThread != null) + mSerialIOThread.disconnect("Application exit"); + + MainApp.instance().getApplicationContext().unregisterReceiver(receiver); + + stopSelf(); + if (Config.logFunctionCalls) + log.debug("EventAppExit finished"); + } + + public boolean isConnected() { + return mRfcommSocket != null && mRfcommSocket.isConnected(); + } + + public boolean isConnecting() { + return connectionInProgress; + } + + public void disconnect(String from) { + if (mSerialIOThread != null) + mSerialIOThread.disconnect(from); + } + + public void connect(String from) { + if (danaRPump.password != -1 && danaRPump.password != SP.getInt(R.string.key_danar_password, -1)) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumppassword), R.raw.error); + return; + } + while (isConnected() || isConnecting()) { + if (Config.logDanaBTComm) + log.debug("already connected/connecting from: " + from); + waitMsec(3000); + } + final long maxConnectionTime = 5 * 60 * 1000L; // 5 min + synchronized (connectionLock) { + //log.debug("entering connection while loop"); + connectionInProgress = true; + mWakeLock.acquire(); + getBTSocketForSelectedPump(); + if (mRfcommSocket == null || mBTDevice == null) + return; // Device not found + long startTime = new Date().getTime(); + while (!isConnected() && startTime + maxConnectionTime >= new Date().getTime()) { + long secondsElapsed = (new Date().getTime() - startTime) / 1000L; + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + if (Config.logDanaBTComm) + log.debug("connect waiting " + secondsElapsed + "sec from: " + from); + try { + mRfcommSocket.connect(); + } catch (IOException e) { + //e.printStackTrace(); + if (e.getMessage().contains("socket closed")) { + e.printStackTrace(); + break; + } + } + waitMsec(1000); + + if (isConnected()) { + if (mSerialIOThread != null) { + mSerialIOThread.disconnect("Recreate SerialIOThread"); + } + mSerialIOThread = new SerialIOThread(mRfcommSocket); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED, 0)); + if (!getPumpStatus()) { + mSerialIOThread.disconnect("getPumpStatus failed"); + waitMsec(3000); + if (!MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP)) + return; + getBTSocketForSelectedPump(); + startTime = new Date().getTime(); + } + } + } + if (!isConnected()) { + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + log.error("Pump connection timed out"); + } + connectionInProgress = false; + mWakeLock.release(); + } + } + + private void getBTSocketForSelectedPump() { + devName = SP.getString(MainApp.sResources.getString(R.string.key_danar_bt_name), ""); + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (bluetoothAdapter != null) { + Set bondedDevices = bluetoothAdapter.getBondedDevices(); + + for (BluetoothDevice device : bondedDevices) { + if (devName.equals(device.getName())) { + mBTDevice = device; + try { + mRfcommSocket = mBTDevice.createRfcommSocketToServiceRecord(SPP_UUID); + } catch (IOException e) { + log.error("Error creating socket: ", e); + } + break; + } + } + } else { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter)); + } + if (mBTDevice == null) { + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound)); + } + } + + @Subscribe + public void onStatusEvent(final EventPreferenceChange pch) { + if (mSerialIOThread != null) + mSerialIOThread.disconnect("EventPreferenceChange"); + } + + private boolean getPumpStatus() { + try { + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus))); + MsgStatus statusMsg = new MsgStatus(); + MsgStatusBasic statusBasicMsg = new MsgStatusBasic(); + MsgStatusTempBasal_v2 tempStatusMsg = new MsgStatusTempBasal_v2(); + MsgStatusBolusExtended_v2 exStatusMsg = new MsgStatusBolusExtended_v2(); + MsgCheckValue_v2 checkValue = new MsgCheckValue_v2(); + + if (danaRPump.isNewPump) { + mSerialIOThread.sendMessage(checkValue); + if (!checkValue.received) { + return false; + } + } + + mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration + mSerialIOThread.sendMessage(exStatusMsg); + mSerialIOThread.sendMessage(statusMsg); + mSerialIOThread.sendMessage(statusBasicMsg); + + if (!statusMsg.received) { + mSerialIOThread.sendMessage(statusMsg); + } + if (!statusBasicMsg.received) { + mSerialIOThread.sendMessage(statusBasicMsg); + } + if (!tempStatusMsg.received) { + // Load of status of current basal rate failed, give one more try + mSerialIOThread.sendMessage(tempStatusMsg); + } + if (!exStatusMsg.received) { + // Load of status of current extended bolus failed, give one more try + mSerialIOThread.sendMessage(exStatusMsg); + } + + // Check we have really current status of pump + if (!statusMsg.received || !statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) { + waitMsec(10 * 1000); + log.debug("getPumpStatus failed"); + return false; + } + + Date now = new Date(); + if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRv2Plugin)MainApp.getSpecificPlugin(DanaRv2Plugin.class)).isInitialized()) { + mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); + mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); + mSerialIOThread.sendMessage(new MsgSettingMeal()); + mSerialIOThread.sendMessage(new MsgSettingBasal()); + //0x3201 + mSerialIOThread.sendMessage(new MsgSettingMaxValues()); + mSerialIOThread.sendMessage(new MsgSettingGlucose()); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); + mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); + mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll()); + mSerialIOThread.sendMessage(new MsgSetTime(new Date())); + danaRPump.lastSettingsRead = now; + } + + loadEvents(); + + danaRPump.lastConnection = now; + MainApp.bus().post(new EventDanaRNewStatus()); + MainApp.bus().post(new EventInitializationChanged()); + 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.sResources.getString(R.string.approachingdailylimit), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(reportFail)); + NSUpload.uploadError(MainApp.sResources.getString(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U"); + } + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + public boolean tempBasal(int percent, int durationInHours) { + connect("tempBasal"); + if (!isConnected()) return false; + if (danaRPump.isTempBasalInProgress) { + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); + waitMsec(500); + } + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetTempBasalStart(percent, durationInHours)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); + loadEvents(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean highTempBasal(int percent) { + connect("highTempBasal"); + if (!isConnected()) return false; + if (danaRPump.isTempBasalInProgress) { + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); + waitMsec(500); + } + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetAPSTempBasalStart_v2(percent)); + mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); + loadEvents(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean tempBasalStop() { + connect("tempBasalStop"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal))); + mSerialIOThread.sendMessage(new MsgSetTempBasalStop()); + mSerialIOThread.sendMessage(new MsgStatusTempBasal_v2()); + loadEvents(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean extendedBolus(double insulin, int durationInHalfHours) { + connect("extendedBolus"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingextendedbolus))); + mSerialIOThread.sendMessage(new MsgSetExtendedBolusStart(insulin, (byte) (durationInHalfHours & 0xFF))); + mSerialIOThread.sendMessage(new MsgStatusBolusExtended_v2()); + loadEvents(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean extendedBolusStop() { + connect("extendedBolusStop"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingextendedbolus))); + mSerialIOThread.sendMessage(new MsgSetExtendedBolusStop()); + mSerialIOThread.sendMessage(new MsgStatusBolusExtended_v2()); + loadEvents(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + public boolean bolus(double amount, int carbs, long carbtime, Treatment t) { + bolusingTreatment = t; + MsgBolusStart start = new MsgBolusStart(amount); + MsgBolusStop stop = new MsgBolusStop(amount, t); + + connect("bolus"); + if (!isConnected()) return false; + + if (carbs > 0) { + MsgSetCarbsEntry msg = new MsgSetCarbsEntry(carbtime, carbs); + mSerialIOThread.sendMessage(msg); + MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, carbtime, carbs, 0); + mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); + lastHistoryFetched = carbtime - 60000; + } + if (amount > 0) { + MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables + MainApp.bus().post(new EventDanaRBolusStart()); + + if (!stop.stopped) { + mSerialIOThread.sendMessage(start); + } else { + t.insulin = 0d; + return false; + } + while (!stop.stopped && !start.failed) { + waitMsec(100); + if ((new Date().getTime() - progress.lastReceive) > 5 * 1000L) { // if i didn't receive status for more than 5 sec expecting broken comm + stop.stopped = true; + stop.forced = true; + log.debug("Communication stopped"); + } + } + } + waitMsec(3000); + bolusingTreatment = null; + loadEvents(); + return true; + } + + public void bolusStop() { + if (Config.logDanaBTComm) + log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin)); + MsgBolusStop stop = new MsgBolusStop(); + stop.forced = true; + if (isConnected()) { + mSerialIOThread.sendMessage(stop); + while (!stop.stopped) { + mSerialIOThread.sendMessage(stop); + waitMsec(200); + } + } else { + stop.stopped = true; + } + } + + public boolean carbsEntry(int amount, long time) { + connect("carbsEntry"); + if (!isConnected()) return false; + MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount); + mSerialIOThread.sendMessage(msg); + MsgSetHistoryEntry_v2 msgSetHistoryEntry_v2 = new MsgSetHistoryEntry_v2(DanaRPump.CARBS, time, amount, 0); + mSerialIOThread.sendMessage(msgSetHistoryEntry_v2); + lastHistoryFetched = time - 1; + return true; + } + + public boolean loadHistory(byte type) { + connect("loadHistory"); + if (!isConnected()) return false; + MessageBase msg = null; + switch (type) { + case RecordTypes.RECORD_TYPE_ALARM: + msg = new MsgHistoryAlarm(); + break; + case RecordTypes.RECORD_TYPE_BASALHOUR: + msg = new MsgHistoryBasalHour(); + break; + case RecordTypes.RECORD_TYPE_BOLUS: + msg = new MsgHistoryBolus(); + break; + case RecordTypes.RECORD_TYPE_CARBO: + msg = new MsgHistoryCarbo(); + break; + case RecordTypes.RECORD_TYPE_DAILY: + msg = new MsgHistoryDailyInsulin(); + break; + case RecordTypes.RECORD_TYPE_ERROR: + msg = new MsgHistoryError(); + break; + case RecordTypes.RECORD_TYPE_GLUCOSE: + msg = new MsgHistoryGlucose(); + break; + case RecordTypes.RECORD_TYPE_REFILL: + msg = new MsgHistoryRefill(); + break; + case RecordTypes.RECORD_TYPE_SUSPEND: + msg = new MsgHistorySuspend(); + break; + } + MsgHistoryDone done = new MsgHistoryDone(); + mSerialIOThread.sendMessage(new MsgPCCommStart()); + waitMsec(400); + mSerialIOThread.sendMessage(msg); + while (!done.received && mRfcommSocket.isConnected()) { + waitMsec(100); + } + waitMsec(200); + mSerialIOThread.sendMessage(new MsgPCCommStop()); + return true; + } + + public boolean loadEvents() { + if (!isConnected()) return false; + MsgHistoryEvents_v2 msg; + if (lastHistoryFetched == 0) { + msg = new MsgHistoryEvents_v2(); + log.debug("Loading complete event history"); + } else { + msg = new MsgHistoryEvents_v2(lastHistoryFetched); + log.debug("Loading event history from: " + new Date(lastHistoryFetched).toLocaleString()); + } + mSerialIOThread.sendMessage(msg); + while (!msg.done && mRfcommSocket.isConnected()) { + waitMsec(100); + } + waitMsec(200); + lastHistoryFetched = MsgHistoryEvents_v2.lastEventTimeLoaded; + return true; + } + + public boolean updateBasalsInPump(final Profile profile) { + connect("updateBasalsInPump"); + if (!isConnected()) return false; + MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates))); + double[] basal = buildDanaRProfileRecord(profile); + MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal); + mSerialIOThread.sendMessage(msgSet); + MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0); + mSerialIOThread.sendMessage(msgActivate); + danaRPump.lastSettingsRead = new Date(0); // force read full settings + getPumpStatus(); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + return true; + } + + private double[] buildDanaRProfileRecord(Profile nsProfile) { + double[] record = new double[24]; + for (Integer hour = 0; hour < 24; hour++) { + double value = Math.round(100d * nsProfile.getBasal(hour * 60 * 60))/100d + 0.00001; + if (Config.logDanaMessageDetail) + log.debug("NS basal value for " + hour + ":00 is " + value); + record[hour] = value; + } + return record; + } + + private void waitMsec(long msecs) { + try { + Thread.sleep(msecs); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIFragment.java new file mode 100644 index 0000000000..f6221d627e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIFragment.java @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.plugins.PumpMDI; + + +import android.support.v4.app.Fragment; + +public class MDIFragment extends Fragment { + private static MDIPlugin mdiPlugin = new MDIPlugin(); + + public static MDIPlugin getPlugin() { + return mdiPlugin; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java similarity index 77% rename from app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java index 534a77b766..b0c55ba036 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java @@ -1,6 +1,4 @@ -package info.nightscout.androidaps.plugins.MDI; - -import android.content.Context; +package info.nightscout.androidaps.plugins.PumpMDI; import org.json.JSONException; import org.json.JSONObject; @@ -13,12 +11,12 @@ import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.DateUtil; /** @@ -37,26 +35,8 @@ public class MDIPlugin implements PluginBase, PumpInterface { pumpDescription.bolusStep = 0.5d; pumpDescription.isExtendedBolusCapable = false; - pumpDescription.extendedBolusStep = 0d; - pumpDescription.isTempBasalCapable = false; - pumpDescription.lowTempBasalStyle = PumpDescription.NONE; - pumpDescription.highTempBasalStyle = PumpDescription.NONE; - pumpDescription.maxHighTempPercent = 0; - pumpDescription.maxHighTempAbsolute = 0; - pumpDescription.lowTempPercentStep = 0; - pumpDescription.lowTempAbsoluteStep = 0; - pumpDescription.lowTempPercentDuration = 0; - pumpDescription.lowTempAbsoluteDuration = 0; - pumpDescription.highTempPercentStep = 0; - pumpDescription.highTempAbsoluteStep = 0d; - pumpDescription.highTempPercentDuration = 0; - pumpDescription.highTempAbsoluteDuration = 0; - pumpDescription.isSetBasalProfileCapable = false; - pumpDescription.basalStep = 0d; - pumpDescription.basalMinimumRate = 0d; - pumpDescription.isRefillingCapable = false; } @@ -91,6 +71,16 @@ public class MDIPlugin implements PluginBase, PumpInterface { return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PUMP) this.fragmentEnabled = fragmentEnabled; @@ -106,6 +96,11 @@ public class MDIPlugin implements PluginBase, PumpInterface { return PluginBase.PUMP; } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return false; + } + @Override public boolean isInitialized() { return true; @@ -122,23 +117,13 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public boolean isTempBasalInProgress() { - return false; - } - - @Override - public boolean isExtendedBoluslInProgress() { - return false; - } - - @Override - public int setNewBasalProfile(NSProfile profile) { + public int setNewBasalProfile(Profile profile) { // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); return SUCCESS; } @Override - public boolean isThisProfileSet(NSProfile profile) { + public boolean isThisProfileSet(Profile profile) { return false; } @@ -158,37 +143,13 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public double getTempBasalAbsoluteRate() { - return 0; - } - - @Override - public TempBasal getTempBasal() { - return null; - } - - @Override - public TempBasal getExtendedBolus() { - return null; - } - - @Override - public double getTempBasalRemainingMinutes() { - return 0d; - } - - @Override - public TempBasal getTempBasal(Date time) { - return null; - } - - @Override - public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) { + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { PumpEnactResult result = new PumpEnactResult(); result.success = true; - result.bolusDelivered = insulin; - result.carbsDelivered = carbs; + result.bolusDelivered = detailedBolusInfo.insulin; + result.carbsDelivered = detailedBolusInfo.carbs; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); return result; } @@ -255,7 +216,7 @@ public class MDIPlugin implements PluginBase, PumpInterface { status.put("status", "normal"); extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile()); + extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); } catch (Exception e) { } status.put("timestamp", DateUtil.toISOString(new Date())); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java similarity index 73% rename from app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java index 4f842fdaa3..c2a0b6780b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.VirtualPump; +package info.nightscout.androidaps.plugins.PumpVirtual; import android.app.Activity; @@ -16,20 +16,15 @@ import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Date; + import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui; +import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; -public class VirtualPumpFragment extends Fragment implements FragmentBase { +public class VirtualPumpFragment extends Fragment { private static Logger log = LoggerFactory.getLogger(VirtualPumpFragment.class); - private static VirtualPumpPlugin virtualPumpPlugin = new VirtualPumpPlugin(); - - public static VirtualPumpPlugin getPlugin() { - return virtualPumpPlugin; - } - TextView basaBasalRateView; TextView tempBasalView; TextView extendedBolusView; @@ -92,19 +87,19 @@ public class VirtualPumpFragment extends Fragment implements FragmentBase { @Override public void run() { - basaBasalRateView.setText(virtualPumpPlugin.getBaseBasalRate() + "U"); - if (virtualPumpPlugin.isTempBasalInProgress()) { - tempBasalView.setText(virtualPumpPlugin.getTempBasal().toString()); + basaBasalRateView.setText(VirtualPumpPlugin.getInstance().getBaseBasalRate() + "U"); + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + tempBasalView.setText(MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()).toStringFull()); } else { tempBasalView.setText(""); } - if (virtualPumpPlugin.isExtendedBoluslInProgress()) { - extendedBolusView.setText(virtualPumpPlugin.getExtendedBolus().toString()); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()).toString()); } else { extendedBolusView.setText(""); } - batteryView.setText(VirtualPumpPlugin.batteryPercent + "%"); - reservoirView.setText(VirtualPumpPlugin.reservoirInUnits + "U"); + batteryView.setText(VirtualPumpPlugin.getInstance().batteryPercent + "%"); + reservoirView.setText(VirtualPumpPlugin.getInstance().reservoirInUnits + "U"); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java similarity index 59% rename from app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpPlugin.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 2e3a802a7a..39dfcf7873 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -1,6 +1,5 @@ -package info.nightscout.androidaps.plugins.VirtualPump; +package info.nightscout.androidaps.plugins.PumpVirtual; -import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -9,23 +8,26 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.util.Date; import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.VirtualPump.events.EventVirtualPumpUpdateGui; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; /** * Created by mike on 05.08.2016. @@ -45,30 +47,35 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { PumpDescription pumpDescription = new PumpDescription(); + static VirtualPumpPlugin instance = null; + public static VirtualPumpPlugin getInstance() { + if (instance == null) + instance = new VirtualPumpPlugin(); + return instance; + } + public VirtualPumpPlugin() { pumpDescription.isBolusCapable = true; pumpDescription.bolusStep = 0.1d; pumpDescription.isExtendedBolusCapable = true; - pumpDescription.extendedBolusStep = 0.2d; + pumpDescription.extendedBolusStep = 0.05d; + pumpDescription.extendedBolusDurationStep = 30; + pumpDescription.extendedBolusMaxDuration = 8 * 60; pumpDescription.isTempBasalCapable = true; - pumpDescription.lowTempBasalStyle = PumpDescription.ABSOLUTE | PumpDescription.PERCENT; - pumpDescription.highTempBasalStyle = PumpDescription.ABSOLUTE | PumpDescription.PERCENT; - pumpDescription.maxHighTempPercent = 600; - pumpDescription.maxHighTempAbsolute = 10; - pumpDescription.lowTempPercentStep = 5; - pumpDescription.lowTempAbsoluteStep = 0.1; - pumpDescription.lowTempPercentDuration = 30; - pumpDescription.lowTempAbsoluteDuration = 30; - pumpDescription.highTempPercentStep = 10; - pumpDescription.highTempAbsoluteStep = 0.05d; - pumpDescription.highTempPercentDuration = 30; - pumpDescription.highTempAbsoluteDuration = 30; + pumpDescription.tempBasalStyle = PumpDescription.PERCENT | PumpDescription.ABSOLUTE; + + pumpDescription.maxTempPercent = 500; + pumpDescription.tempPercentStep = 10; + + pumpDescription.tempDurationStep = 30; + pumpDescription.tempMaxDuration = 24 * 60; + pumpDescription.isSetBasalProfileCapable = true; pumpDescription.basalStep = 0.01d; - pumpDescription.basalMinimumRate = 0.04d; + pumpDescription.basalMinimumRate = 0.01d; pumpDescription.isRefillingCapable = false; } @@ -86,7 +93,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.virtualpump_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -109,6 +116,16 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == PUMP) this.fragmentEnabled = fragmentEnabled; @@ -124,6 +141,11 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { return PluginBase.PUMP; } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return false; + } + @Override public boolean isInitialized() { return true; @@ -140,24 +162,14 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } @Override - public boolean isTempBasalInProgress() { - return getTempBasal() != null; - } - - @Override - public boolean isExtendedBoluslInProgress() { - return getExtendedBolus() != null; - } - - @Override - public int setNewBasalProfile(NSProfile profile) { + public int setNewBasalProfile(Profile profile) { // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); lastDataTime = new Date(); return SUCCESS; } @Override - public boolean isThisProfileSet(NSProfile profile) { + public boolean isThisProfileSet(Profile profile) { return false; } @@ -168,74 +180,33 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public void refreshDataFromPump(String reason) { - MainApp.getConfigBuilder().uploadDeviceStatus(); + NSUpload.uploadDeviceStatus(); lastDataTime = new Date(); } @Override public double getBaseBasalRate() { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - if (profile == null) - return defaultBasalValue; - return profile.getBasal(profile.secondsFromMidnight()); + return MainApp.getConfigBuilder().getProfile().getBasal(); } @Override - public double getTempBasalAbsoluteRate() { - if (!isTempBasalInProgress()) - return 0; - if (getTempBasal().isAbsolute) { - return getTempBasal().absolute; - } else { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - if (profile == null) - return defaultBasalValue; - Double baseRate = profile.getBasal(profile.secondsFromMidnight()); - Double tempRate = baseRate * (getTempBasal().percent / 100d); - return baseRate + tempRate; - } - } - - @Override - public TempBasal getTempBasal() { - return ConfigBuilderPlugin.getActiveTempBasals().getTempBasal(new Date()); - } - - @Override - public TempBasal getExtendedBolus() { - return ConfigBuilderPlugin.getActiveTempBasals().getExtendedBolus(new Date()); - } - - @Override - public double getTempBasalRemainingMinutes() { - if (!isTempBasalInProgress()) - return 0; - return getTempBasal().getPlannedRemainingMinutes(); - } - - @Override - public TempBasal getTempBasal(Date time) { - return ConfigBuilderPlugin.getActiveTempBasals().getTempBasal(time); - } - - @Override - public PumpEnactResult deliverTreatment(Double insulin, Integer carbs, Context context) { + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { PumpEnactResult result = new PumpEnactResult(); result.success = true; - result.bolusDelivered = insulin; - result.carbsDelivered = carbs; + result.bolusDelivered = detailedBolusInfo.insulin; + result.carbsDelivered = detailedBolusInfo.carbs; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); Double delivering = 0d; - while (delivering < insulin) { + while (delivering < detailedBolusInfo.insulin) { try { Thread.sleep(200); } catch (InterruptedException e) { } EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivering); - bolusingEvent.percent = Math.min((int) (delivering / insulin * 100), 100); + bolusingEvent.percent = Math.min((int) (delivering / detailedBolusInfo.insulin * 100), 100); MainApp.bus().post(bolusingEvent); delivering += 0.1d; } @@ -244,18 +215,18 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } catch (InterruptedException e) { } EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivered), insulin); + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivered), detailedBolusInfo.insulin); bolusingEvent.percent = 100; MainApp.bus().post(bolusingEvent); try { Thread.sleep(1000); } catch (InterruptedException e) { } - if (Config.logPumpComm) - log.debug("Delivering treatment insulin: " + insulin + "U carbs: " + carbs + "g " + result); + log.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result); MainApp.bus().post(new EventVirtualPumpUpdateGui()); lastDataTime = new Date(); + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); return result; } @@ -266,27 +237,21 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { - PumpEnactResult result = cancelTempBasal(); - if (!result.success) - return result; - TempBasal tempBasal = new TempBasal(); - tempBasal.timeStart = new Date(); + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + TemporaryBasal tempBasal = new TemporaryBasal(); + tempBasal.date = new Date().getTime(); tempBasal.isAbsolute = true; - tempBasal.absolute = absoluteRate; - tempBasal.duration = durationInMinutes; + tempBasal.absoluteRate = absoluteRate; + tempBasal.durationInMinutes = durationInMinutes; + tempBasal.source = Source.USER; + PumpEnactResult result = new PumpEnactResult(); result.success = true; result.enacted = true; result.isTempCancel = false; result.absolute = absoluteRate; result.duration = durationInMinutes; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - try { - MainApp.instance().getDbHelper().getDaoTempBasals().create(tempBasal); - } catch (SQLException e) { - e.printStackTrace(); - result.success = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_sqlerror); - } + treatmentsInterface.addToHistoryTempBasal(tempBasal); if (Config.logPumpComm) log.debug("Setting temp basal absolute: " + result); MainApp.bus().post(new EventVirtualPumpUpdateGui()); @@ -296,17 +261,19 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes) { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); PumpEnactResult result = new PumpEnactResult(); - if (isTempBasalInProgress()) { + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { result = cancelTempBasal(); if (!result.success) return result; } - TempBasal tempBasal = new TempBasal(); - tempBasal.timeStart = new Date(); + TemporaryBasal tempBasal = new TemporaryBasal(); + tempBasal.date = new Date().getTime(); tempBasal.isAbsolute = false; - tempBasal.percent = percent; - tempBasal.duration = durationInMinutes; + tempBasal.percentRate = percent; + tempBasal.durationInMinutes = durationInMinutes; + tempBasal.source = Source.USER; result.success = true; result.enacted = true; result.percent = percent; @@ -314,13 +281,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { result.isTempCancel = false; result.duration = durationInMinutes; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - try { - MainApp.instance().getDbHelper().getDaoTempBasals().create(tempBasal); - } catch (SQLException e) { - e.printStackTrace(); - result.success = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_sqlerror); - } + treatmentsInterface.addToHistoryTempBasal(tempBasal); if (Config.logPumpComm) log.debug("Settings temp basal percent: " + result); MainApp.bus().post(new EventVirtualPumpUpdateGui()); @@ -330,29 +291,22 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); PumpEnactResult result = cancelExtendedBolus(); if (!result.success) return result; - TempBasal extendedBolus = new TempBasal(); - extendedBolus.timeStart = new Date(); - extendedBolus.isExtended = true; - extendedBolus.absolute = insulin * 60d / durationInMinutes; - extendedBolus.duration = durationInMinutes; - extendedBolus.isAbsolute = true; + ExtendedBolus extendedBolus = new ExtendedBolus(); + extendedBolus.date = new Date().getTime(); + extendedBolus.insulin = insulin; + extendedBolus.durationInMinutes = durationInMinutes; + extendedBolus.source = Source.USER; result.success = true; result.enacted = true; result.bolusDelivered = insulin; result.isTempCancel = false; result.duration = durationInMinutes; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - try { - MainApp.instance().getDbHelper().getDaoTempBasals().create(extendedBolus); - } catch (SQLException e) { - e.printStackTrace(); - result.success = false; - result.enacted = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_sqlerror); - } + treatmentsInterface.addToHistoryExtendedBolus(extendedBolus); if (Config.logPumpComm) log.debug("Setting extended bolus: " + result); MainApp.bus().post(new EventVirtualPumpUpdateGui()); @@ -362,26 +316,20 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult cancelTempBasal() { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); PumpEnactResult result = new PumpEnactResult(); result.success = true; result.isTempCancel = true; result.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - if (isTempBasalInProgress()) { + if (treatmentsInterface.isTempBasalInProgress()) { result.enacted = true; - TempBasal tb = getTempBasal(); - tb.timeEnd = new Date(); - try { - MainApp.instance().getDbHelper().getDaoTempBasals().update(tb); - //tempBasal = null; - if (Config.logPumpComm) - log.debug("Canceling temp basal: " + result); - MainApp.bus().post(new EventVirtualPumpUpdateGui()); - } catch (SQLException e) { - e.printStackTrace(); - result.success = false; - result.enacted = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_sqlerror); - } + TemporaryBasal tempStop = new TemporaryBasal(new Date().getTime()); + tempStop.source = Source.USER; + treatmentsInterface.addToHistoryTempBasal(tempStop); + //tempBasal = null; + if (Config.logPumpComm) + log.debug("Canceling temp basal: " + result); + MainApp.bus().post(new EventVirtualPumpUpdateGui()); } lastDataTime = new Date(); return result; @@ -389,17 +337,12 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult cancelExtendedBolus() { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); PumpEnactResult result = new PumpEnactResult(); - if (isExtendedBoluslInProgress()) { - TempBasal extendedBolus = getExtendedBolus(); - extendedBolus.timeEnd = new Date(); - try { - MainApp.instance().getDbHelper().getDaoTempBasals().update(extendedBolus); - } catch (SQLException e) { - e.printStackTrace(); - result.success = false; - result.comment = MainApp.instance().getString(R.string.virtualpump_sqlerror); - } + if (treatmentsInterface.isInHistoryExtendedBoluslInProgress()) { + ExtendedBolus exStop = new ExtendedBolus(new Date().getTime()); + exStop.source = Source.USER; + treatmentsInterface.addToHistoryExtendedBolus(exStop); } result.success = true; result.enacted = true; @@ -427,13 +370,20 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { status.put("status", "normal"); extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getActiveProfile().getProfile().getActiveProfile()); - } catch (Exception e) {} - TempBasal tb; - if ((tb = getTempBasal()) != null) { - status.put("tempbasalpct", tb.percent); - status.put("tempbasalstart", DateUtil.toISOString(tb.timeStart)); - status.put("tempbasalremainmin", tb.getPlannedRemainingMinutes()); + extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); + } catch (Exception e) { + } + TemporaryBasal tb = MainApp.getConfigBuilder().getTempBasalFromHistory(new Date().getTime()); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(new Date().getTime())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(new Date().getTime()); + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); + extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date)); + extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes()); } status.put("timestamp", DateUtil.toISOString(new Date())); @@ -443,6 +393,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { pump.put("reservoir", reservoirInUnits); pump.put("clock", DateUtil.toISOString(new Date())); } catch (JSONException e) { + e.printStackTrace(); } return pump; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/events/EventVirtualPumpUpdateGui.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java similarity index 57% rename from app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/events/EventVirtualPumpUpdateGui.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java index 4892ae33eb..110e0f4a56 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/VirtualPump/events/EventVirtualPumpUpdateGui.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/events/EventVirtualPumpUpdateGui.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.VirtualPump.events; +package info.nightscout.androidaps.plugins.PumpVirtual.events; /** * Created by mike on 05.08.2016. 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 fcaf379af2..4e81aa49d9 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 @@ -1,9 +1,7 @@ package info.nightscout.androidaps.plugins.SmsCommunicator; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.ResolveInfo; -import android.preference.PreferenceManager; import android.telephony.SmsManager; import android.telephony.SmsMessage; @@ -23,23 +21,28 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.DanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.XdripCalibrations; @@ -53,11 +56,11 @@ public class SmsCommunicatorPlugin implements PluginBase { private static boolean fragmentEnabled = false; private static boolean fragmentVisible = true; - final long CONFIRM_TIMEOUT = 5 * 60 * 1000L; + private final long CONFIRM_TIMEOUT = 5 * 60 * 1000L; - List allowedNumbers = new ArrayList(); + private List allowedNumbers = new ArrayList(); - public class Sms { + class Sms { String phoneNumber; String text; Date date; @@ -71,21 +74,21 @@ public class SmsCommunicatorPlugin implements PluginBase { double calibrationRequested = 0d; int duration = 0; - public Sms(SmsMessage message) { + Sms(SmsMessage message) { phoneNumber = message.getOriginatingAddress(); text = message.getMessageBody(); date = new Date(message.getTimestampMillis()); received = true; } - public Sms(String phoneNumber, String text, Date date) { + Sms(String phoneNumber, String text, Date date) { this.phoneNumber = phoneNumber; this.text = text; this.date = date; sent = true; } - public Sms(String phoneNumber, String text, Date date, String confirmCode) { + Sms(String phoneNumber, String text, Date date, String confirmCode) { this.phoneNumber = phoneNumber; this.text = text; this.date = date; @@ -98,12 +101,12 @@ public class SmsCommunicatorPlugin implements PluginBase { } } - Sms cancelTempBasalWaitingForConfirmation = null; - Sms tempBasalWaitingForConfirmation = null; - Sms bolusWaitingForConfirmation = null; - Sms calibrationWaitingForConfirmation = null; - Sms suspendWaitingForConfirmation = null; - Date lastRemoteBolusTime = new Date(0); + private Sms cancelTempBasalWaitingForConfirmation = null; + private Sms tempBasalWaitingForConfirmation = null; + private Sms bolusWaitingForConfirmation = null; + private Sms calibrationWaitingForConfirmation = null; + private Sms suspendWaitingForConfirmation = null; + private Date lastRemoteBolusTime = new Date(0); ArrayList messages = new ArrayList<>(); @@ -153,6 +156,16 @@ public class SmsCommunicatorPlugin implements PluginBase { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) this.fragmentEnabled = fragmentEnabled; @@ -179,7 +192,7 @@ public class SmsCommunicatorPlugin implements PluginBase { } } - boolean isAllowedNumber(String number) { + private boolean isAllowedNumber(String number) { for (String num : allowedNumbers) { if (num.equals(number)) return true; } @@ -191,8 +204,8 @@ public class SmsCommunicatorPlugin implements PluginBase { Object[] pdus = (Object[]) ev.bundle.get("pdus"); // For every SMS message received - for (int i = 0; i < pdus.length; i++) { - SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]); + for (Object pdu : pdus) { + SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu); processSms(new Sms(message)); } } @@ -222,28 +235,27 @@ public class SmsCommunicatorPlugin implements PluginBase { if (splited.length > 0) { switch (splited[0].toUpperCase()) { case "BG": - BgReading actualBG = GlucoseStatus.actualBg(); - BgReading lastBG = GlucoseStatus.lastBg(); + BgReading actualBG = DatabaseHelper.actualBg(); + BgReading lastBG = DatabaseHelper.lastBg(); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); String units = profile.getUnits(); - Long agoMsec = new Date().getTime() - lastBG.timeIndex; - int agoMin = (int) (agoMsec / 60d / 1000d); - if (actualBG != null) { reply = MainApp.sResources.getString(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", "; } else if (lastBG != null) { + Long agoMsec = new Date().getTime() - lastBG.date; + int agoMin = (int) (agoMsec / 60d / 1000d); reply = MainApp.sResources.getString(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.sResources.getString(R.string.sms_minago), agoMin) + ", "; } GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); if (glucoseStatus != null) - reply += MainApp.sResources.getString(R.string.sms_delta) + " " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "; + reply += MainApp.sResources.getString(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "; - MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB(); - IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round(); - MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB(); - IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round(); + MainApp.getConfigBuilder().updateTotalIOBTreatments(); + IobTotal bolusIob = MainApp.getConfigBuilder().getLastCalculationTreatments().round(); + MainApp.getConfigBuilder().updateTotalIOBTempBasals(); + IobTotal basalIob = MainApp.getConfigBuilder().getLastCalculationTempBasals().round(); reply += MainApp.sResources.getString(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + MainApp.sResources.getString(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " @@ -254,102 +266,109 @@ public class SmsCommunicatorPlugin implements PluginBase { Answers.getInstance().logCustom(new CustomEvent("SMS_Bg")); break; case "LOOP": - switch (splited[1].toUpperCase()) { - case "DISABLE": - case "STOP": - LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) { - loopPlugin.setFragmentEnabled(PluginBase.LOOP, false); - reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Stop")); - break; - case "ENABLE": - case "START": - loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null && !loopPlugin.isEnabled(PluginBase.LOOP)) { - loopPlugin.setFragmentEnabled(PluginBase.LOOP, true); - reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeenenabled); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Start")); - break; - case "STATUS": - loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - if (loopPlugin != null) { - if (loopPlugin.isEnabled(PluginBase.LOOP)) { - if (loopPlugin.isSuspended()) - reply = String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()); - else - reply = MainApp.sResources.getString(R.string.smscommunicator_loopisenabled); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_loopisdisabled); + if (splited.length > 1) + switch (splited[1].toUpperCase()) { + case "DISABLE": + case "STOP": + LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + if (loopPlugin != null && loopPlugin.isEnabled(PluginBase.LOOP)) { + loopPlugin.setFragmentEnabled(PluginBase.LOOP, false); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + MainApp.bus().post(new EventRefreshGui(false)); + reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled)+ " " + + MainApp.sResources.getString(result.success?R.string.smscommunicator_tempbasalcanceled:R.string.smscommunicator_tempbasalcancelfailed); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); - break; - case "RESUME": - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - activeloop.suspendTo(0); - MainApp.bus().post(new EventRefreshGui(false)); - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_loopresumed)); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Resume")); - break; - case "SUSPEND": - if (splited.length >= 3) - duration = SafeParse.stringToInt(splited[2]); - duration = Math.max(0, duration); - duration = Math.min(180, duration); - if (duration == 0) { - reply = MainApp.sResources.getString(R.string.smscommunicator_wrongduration); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } else if (remoteCommandsAllowed) { - passCode = generatePasscode(); - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_suspendreplywithcode), duration, passCode); receivedSms.processed = true; - resetWaitingMessages(); - sendSMS(suspendWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode)); - suspendWaitingForConfirmation.duration = duration; - Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Suspend")); - } else { - reply = MainApp.sResources.getString(R.string.smscommunicator_remotecommandnotallowed); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - } - break; - } + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Stop")); + break; + case "ENABLE": + case "START": + loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + if (loopPlugin != null && !loopPlugin.isEnabled(PluginBase.LOOP)) { + loopPlugin.setFragmentEnabled(PluginBase.LOOP, true); + reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeenenabled); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Start")); + break; + case "STATUS": + loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + if (loopPlugin != null) { + if (loopPlugin.isEnabled(PluginBase.LOOP)) { + if (loopPlugin.isSuspended()) + reply = String.format(MainApp.sResources.getString(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()); + else + reply = MainApp.sResources.getString(R.string.smscommunicator_loopisenabled); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_loopisdisabled); + } + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); + break; + case "RESUME": + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); + activeloop.suspendTo(0); + MainApp.bus().post(new EventRefreshGui(false)); + NSUpload.uploadOpenAPSOffline(0); + reply = MainApp.sResources.getString(R.string.smscommunicator_loopresumed); + sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Resume")); + break; + case "SUSPEND": + if (splited.length >= 3) + duration = SafeParse.stringToInt(splited[2]); + duration = Math.max(0, duration); + duration = Math.min(180, duration); + if (duration == 0) { + reply = MainApp.sResources.getString(R.string.smscommunicator_wrongduration); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else if (remoteCommandsAllowed) { + passCode = generatePasscode(); + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_suspendreplywithcode), duration, passCode); + receivedSms.processed = true; + resetWaitingMessages(); + sendSMS(suspendWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode)); + suspendWaitingForConfirmation.duration = duration; + Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Suspend")); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_remotecommandnotallowed); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } + break; + } break; case "TREATMENTS": - switch (splited[1].toUpperCase()) { - case "REFRESH": - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.getDbHelper().resetTreatments(); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); - reply = "TERATMENTS REFRESH " + q.size() + " receivers"; - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Treatments_Refresh")); - break; - } + if (splited.length > 1) + switch (splited[1].toUpperCase()) { + case "REFRESH": + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.getDbHelper().resetTreatments(); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); + reply = "TERATMENTS REFRESH " + q.size() + " receivers"; + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Treatments_Refresh")); + break; + } break; case "NSCLIENT": - switch (splited[1].toUpperCase()) { - case "RESTART": - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); - reply = "NSCLIENT RESTART " + q.size() + " receivers"; - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - receivedSms.processed = true; - Answers.getInstance().logCustom(new CustomEvent("SMS_Nsclient_Restart")); - break; - } + if (splited.length > 1) + switch (splited[1].toUpperCase()) { + case "RESTART": + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); + reply = "NSCLIENT RESTART " + q.size() + " receivers"; + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + receivedSms.processed = true; + Answers.getInstance().logCustom(new CustomEvent("SMS_Nsclient_Restart")); + break; + } break; case "DANAR": DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); @@ -401,6 +420,9 @@ public class SmsCommunicatorPlugin implements PluginBase { if (new Date().getTime() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) { reply = MainApp.sResources.getString(R.string.smscommunicator_remotebolusnotallowed); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else if (MainApp.getConfigBuilder().isSuspended()) { + reply = MainApp.sResources.getString(R.string.pumpsuspended); + sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } else if (splited.length > 1) { amount = SafeParse.stringToDouble(splited[1]); amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); @@ -442,7 +464,10 @@ public class SmsCommunicatorPlugin implements PluginBase { PumpInterface pumpInterface = MainApp.getConfigBuilder(); if (pumpInterface != null) { danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.deliverTreatment(bolusWaitingForConfirmation.bolusRequested, 0, null); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = bolusWaitingForConfirmation.bolusRequested; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = pumpInterface.deliverTreatment(detailedBolusInfo); if (result.success) { reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered); if (danaRPlugin != null) @@ -483,7 +508,7 @@ public class SmsCommunicatorPlugin implements PluginBase { danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); PumpEnactResult result = pumpInterface.cancelTempBasal(); if (result.success) { - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled)); + reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled); if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(true); sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); @@ -499,7 +524,7 @@ public class SmsCommunicatorPlugin implements PluginBase { calibrationWaitingForConfirmation.processed = true; boolean result = XdripCalibrations.sendIntent(calibrationWaitingForConfirmation.calibrationRequested); if (result) { - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_calibrationsent)); + reply = MainApp.sResources.getString(R.string.smscommunicator_calibrationsent); sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); } else { reply = MainApp.sResources.getString(R.string.smscommunicator_calibrationfailed); @@ -508,10 +533,13 @@ public class SmsCommunicatorPlugin implements PluginBase { } else if (suspendWaitingForConfirmation != null && !suspendWaitingForConfirmation.processed && suspendWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - suspendWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { suspendWaitingForConfirmation.processed = true; - final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); activeloop.suspendTo(new Date().getTime() + suspendWaitingForConfirmation.duration * 60L * 1000); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); MainApp.bus().post(new EventRefreshGui(false)); - reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_loopsuspended)); + reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " + + MainApp.sResources.getString(result.success?R.string.smscommunicator_tempbasalcanceled:R.string.smscommunicator_tempbasalcancelfailed); sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); } else { sendSMS(new Sms(receivedSms.phoneNumber, MainApp.sResources.getString(R.string.smscommunicator_unknowncommand), new Date())); @@ -531,14 +559,14 @@ public class SmsCommunicatorPlugin implements PluginBase { } } - public void sendSMSToAllNumbers(Sms sms) { + private void sendSMSToAllNumbers(Sms sms) { for (String number : allowedNumbers) { sms.phoneNumber = number; sendSMS(sms); } } - public void sendSMS(Sms sms) { + private void sendSMS(Sms sms) { SmsManager smsManager = SmsManager.getDefault(); sms.text = stripAccents(sms.text); if (sms.text.length() > 140) sms.text = sms.text.substring(0, 139); @@ -549,6 +577,9 @@ public class SmsCommunicatorPlugin implements PluginBase { } catch (IllegalArgumentException e) { Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.sResources.getString(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL); MainApp.bus().post(new EventNewNotification(notification)); + } catch (java.lang.SecurityException e) { + Notification notification = new Notification(Notification.MISSING_SMS_PERMISSION, MainApp.sResources.getString(R.string.smscommunicator_missingsmspermission), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); } } @@ -570,7 +601,7 @@ public class SmsCommunicatorPlugin implements PluginBase { suspendWaitingForConfirmation = null; } - public static String stripAccents(String s) { + private static String stripAccents(String s) { s = Normalizer.normalize(s, Normalizer.Form.NFD); s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); return s; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpFragment.java index 85a4ee9646..63ab27deee 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpFragment.java @@ -3,9 +3,7 @@ package info.nightscout.androidaps.plugins.SourceGlimp; import android.support.v4.app.Fragment; -import info.nightscout.androidaps.interfaces.FragmentBase; - -public class SourceGlimpFragment extends Fragment implements FragmentBase { +public class SourceGlimpFragment extends Fragment { private static SourceGlimpPlugin sourceGlimpPlugin = new SourceGlimpPlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java index 7a5965e3df..3c1248c4de 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java @@ -48,6 +48,16 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gFragment.java index f43dc6ada7..28bfabf813 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gFragment.java @@ -3,9 +3,7 @@ package info.nightscout.androidaps.plugins.SourceMM640g; import android.support.v4.app.Fragment; -import info.nightscout.androidaps.interfaces.FragmentBase; - -public class SourceMM640gFragment extends Fragment implements FragmentBase { +public class SourceMM640gFragment extends Fragment { private static SourceMM640gPlugin sourceMM640gPlugin = new SourceMM640gPlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java index b1d7a52cd0..df8111b5cd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java @@ -10,7 +10,7 @@ import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; * Created by mike on 05.08.2016. */ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { - boolean fragmentEnabled = true; + boolean fragmentEnabled = false; @Override public String getFragmentClass() { @@ -48,6 +48,16 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientFragment.java index c119952112..b2eddc09fc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientFragment.java @@ -3,9 +3,7 @@ package info.nightscout.androidaps.plugins.SourceNSClient; import android.support.v4.app.Fragment; -import info.nightscout.androidaps.interfaces.FragmentBase; - -public class SourceNSClientFragment extends Fragment implements FragmentBase { +public class SourceNSClientFragment extends Fragment { private static SourceNSClientPlugin sourceNSClientPlugin = new SourceNSClientPlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java index 7e38e6dc47..62ae6b93da 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.plugins.SourceNSClient; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; @@ -35,7 +36,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public boolean isEnabled(int type) { - return type == BGSOURCE && fragmentEnabled; + return Config.NSCLIENT || type == BGSOURCE && fragmentEnabled; } @Override @@ -48,6 +49,16 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return !Config.NSCLIENT; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripFragment.java index e3c58f4bf8..c9be1298d2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripFragment.java @@ -3,9 +3,7 @@ package info.nightscout.androidaps.plugins.SourceXdrip; import android.support.v4.app.Fragment; -import info.nightscout.androidaps.interfaces.FragmentBase; - -public class SourceXdripFragment extends Fragment implements FragmentBase { +public class SourceXdripFragment extends Fragment { private static SourceXdripPlugin sourceXdripPlugin = new SourceXdripPlugin(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java index a1a4f01b86..b32040a2e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java @@ -16,7 +16,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { return SourceNSClientFragment.class.getName(); } - private static boolean fragmentEnabled = true; + private static boolean fragmentEnabled = false; @Override public int getType() { @@ -49,6 +49,16 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { return true; } + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == BGSOURCE) this.fragmentEnabled = fragmentEnabled; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java deleted file mode 100644 index 8317623fd2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java +++ /dev/null @@ -1,185 +0,0 @@ -package info.nightscout.androidaps.plugins.TempBasals; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.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.data.IobTotal; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; - - -public class TempBasalsFragment extends Fragment implements FragmentBase { - private static Logger log = LoggerFactory.getLogger(TempBasalsFragment.class); - - private static TempBasalsPlugin tempBasalsPlugin = new TempBasalsPlugin(); - - public static TempBasalsPlugin getPlugin() { - return tempBasalsPlugin; - } - - RecyclerView recyclerView; - LinearLayoutManager llm; - - TextView tempBasalTotalView; - - public static class RecyclerViewAdapter extends RecyclerView.Adapter { - - List tempBasalList; - - RecyclerViewAdapter(List tempBasalList) { - this.tempBasalList = tempBasalList; - } - - @Override - public TempBasalsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.tempbasals_item, viewGroup, false); - TempBasalsViewHolder tempBasalsViewHolder = new TempBasalsViewHolder(v); - return tempBasalsViewHolder; - } - - @Override - public void onBindViewHolder(TempBasalsViewHolder holder, int position) { - TempBasal tempBasal = tempBasalList.get(position); - if (tempBasal.timeEnd != null) { - holder.date.setText(DateUtil.dateAndTimeString(tempBasal.timeStart) + " - " + DateUtil.timeString(tempBasalList.get(position).timeEnd)); - } else { - holder.date.setText(DateUtil.dateAndTimeString(tempBasal.timeStart)); - } - holder.duration.setText(DecimalFormatter.to0Decimal(tempBasal.duration) + " min"); - if (tempBasal.isAbsolute) { - holder.absolute.setText(DecimalFormatter.to0Decimal(tempBasal.absolute) + " U/h"); - holder.percent.setText(""); - } else { - holder.absolute.setText(""); - holder.percent.setText(DecimalFormatter.to0Decimal(tempBasal.percent) + "%"); - } - holder.realDuration.setText(DecimalFormatter.to0Decimal(tempBasal.getRealDuration()) + " min"); - IobTotal iob = tempBasal.iobCalc(new Date()); - holder.iob.setText(DecimalFormatter.to2Decimal(iob.basaliob) + " U"); - holder.netInsulin.setText(DecimalFormatter.to2Decimal(iob.netInsulin) + " U"); - holder.netRatio.setText(DecimalFormatter.to2Decimal(iob.netRatio) + " U/h"); - holder.extendedFlag.setVisibility(tempBasal.isExtended ? View.VISIBLE : View.GONE); - if (tempBasal.isInProgress()) - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress)); - else if (tempBasal.timeEnd == null) - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.colorNotEnded)); - else if (tempBasal.iobCalc(new Date()).basaliob != 0) - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.colorAffectingIOB)); - else - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.cardColorBackground)); - } - - @Override - public int getItemCount() { - return tempBasalList.size(); - } - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - } - - public static class TempBasalsViewHolder extends RecyclerView.ViewHolder { - CardView cv; - TextView date; - TextView duration; - TextView absolute; - TextView percent; - TextView realDuration; - TextView netRatio; - TextView netInsulin; - TextView iob; - TextView extendedFlag; - LinearLayout dateLinearLayout; - - TempBasalsViewHolder(View itemView) { - super(itemView); - cv = (CardView) itemView.findViewById(R.id.tempbasals_cardview); - date = (TextView) itemView.findViewById(R.id.tempbasals_date); - duration = (TextView) itemView.findViewById(R.id.tempbasals_duration); - absolute = (TextView) itemView.findViewById(R.id.tempbasals_absolute); - percent = (TextView) itemView.findViewById(R.id.tempbasals_percent); - realDuration = (TextView) itemView.findViewById(R.id.tempbasals_realduration); - netRatio = (TextView) itemView.findViewById(R.id.tempbasals_netratio); - netInsulin = (TextView) itemView.findViewById(R.id.tempbasals_netinsulin); - iob = (TextView) itemView.findViewById(R.id.tempbasals_iob); - extendedFlag = (TextView) itemView.findViewById(R.id.tempbasals_extendedflag); - dateLinearLayout = (LinearLayout) itemView.findViewById(R.id.tempbasals_datelinearlayout); - } - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.tempbasals_fragment, container, false); - - recyclerView = (RecyclerView) view.findViewById(R.id.tempbasals_recyclerview); - recyclerView.setHasFixedSize(true); - llm = new LinearLayoutManager(view.getContext()); - recyclerView.setLayoutManager(llm); - - RecyclerViewAdapter adapter = new RecyclerViewAdapter(tempBasalsPlugin.getMergedList()); - recyclerView.setAdapter(adapter); - - tempBasalTotalView = (TextView) view.findViewById(R.id.tempbasals_totaltempiob); - updateGUI(); - return view; - } - - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - } - - @Subscribe - public void onStatusEvent(final EventTempBasalChange ev) { - updateGUI(); - } - - public void updateGUI() { - Activity activity = getActivity(); - if (activity != null && recyclerView != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(tempBasalsPlugin.getMergedList()), false); - if (tempBasalsPlugin.lastCalculation != null) { - String totalText = DecimalFormatter.to2Decimal(tempBasalsPlugin.lastCalculation.basaliob) + " U"; - tempBasalTotalView.setText(totalText); - } - } - }); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsPlugin.java deleted file mode 100644 index 058d5a7e0b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsPlugin.java +++ /dev/null @@ -1,270 +0,0 @@ -package info.nightscout.androidaps.plugins.TempBasals; - -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.support.annotation.Nullable; - -import com.j256.ormlite.dao.Dao; -import com.squareup.otto.Subscribe; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -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.TempBasal; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.TempBasalsInterface; -import info.nightscout.androidaps.data.IobTotal; - -/** - * Created by mike on 05.08.2016. - */ -public class TempBasalsPlugin implements PluginBase, TempBasalsInterface { - private static Logger log = LoggerFactory.getLogger(TempBasalsPlugin.class); - - public static long lastCalculationTimestamp = 0; - public static IobTotal lastCalculation; - - private static List tempBasals; - private static List extendedBoluses; - - private static boolean useExtendedBoluses = false; - - private static boolean fragmentEnabled = true; - private static boolean fragmentVisible = true; - - public TempBasalsPlugin() { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); - initializeData(); - MainApp.bus().register(this); - } - - @Override - public String getFragmentClass() { - return TempBasalsFragment.class.getName(); - } - - @Override - public String getName() { - return MainApp.instance().getString(R.string.tempbasals); - } - - @Override - public String getNameShort() { - String name = MainApp.sResources.getString(R.string.tempbasals_shortname); - if (!name.trim().isEmpty()){ - //only if translation exists - return name; - } - // use long name as fallback - return getName(); - } - - @Override - public boolean isEnabled(int type) { - return type == TEMPBASAL && fragmentEnabled && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; - } - - @Override - public boolean isVisibleInTabs(int type) { - return type == TEMPBASAL && fragmentVisible && MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable; - } - - @Override - public boolean canBeHidden(int type) { - return true; - } - - @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == TEMPBASAL) this.fragmentEnabled = fragmentEnabled; - } - - @Override - public void setFragmentVisible(int type, boolean fragmentVisible) { - if (type == TEMPBASAL) this.fragmentVisible = fragmentVisible; - } - - @Override - public int getType() { - return PluginBase.TEMPBASAL; - } - - private void initializeData() { - double dia = 3; - if (MainApp.getConfigBuilder().getActiveProfile() != null && MainApp.getConfigBuilder().getActiveProfile().getProfile() != null) - dia = MainApp.getConfigBuilder().getActiveProfile().getProfile().getDia(); - long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)); - tempBasals = MainApp.getDbHelper().getTempbasalsDataFromTime(fromMills, false, false); - extendedBoluses = MainApp.getDbHelper().getTempbasalsDataFromTime(fromMills, false, true); - - // Update ended - checkForExpiredExtended(); - checkForExpiredTemps(); - } - - public void checkForExpiredTemps() { - checkForExpired(tempBasals); - } - - public void checkForExpiredExtended() { - checkForExpired(extendedBoluses); - } - - private void checkForExpired(List list) { - long now = new Date().getTime(); - for (int position = list.size() - 1; position >= 0; position--) { - TempBasal t = list.get(position); - boolean update = false; - if (t.timeEnd == null && t.getPlannedTimeEnd().getTime() < now) { - t.timeEnd = new Date(t.getPlannedTimeEnd().getTime()); - if (Config.logTempBasalsCut) - log.debug("Add timeEnd to old record"); - update = true; - } - if (position > 0) { - Date startofnewer = list.get(position - 1).timeStart; - if (t.timeEnd == null) { - t.timeEnd = new Date(Math.min(startofnewer.getTime(), t.getPlannedTimeEnd().getTime())); - if (Config.logTempBasalsCut) - log.debug("Add timeEnd to old record"); - update = true; - } else if (t.timeEnd.getTime() > startofnewer.getTime()) { - t.timeEnd = startofnewer; - update = true; - } - } - if (update) { - try { - Dao dao = MainApp.getDbHelper().getDaoTempBasals(); - dao.update(t); - } catch (SQLException e) { - e.printStackTrace(); - } - if (Config.logTempBasalsCut) { - log.debug("Fixing unfinished temp end: " + t.log()); - if (position > 0) - log.debug("Previous: " + list.get(position - 1).log()); - } - } - } - } - - /* - * Recalculate IOB if value is older than 1 minute - */ - public void updateTotalIOBIfNeeded() { - if (lastCalculationTimestamp > new Date().getTime() - 60 * 1000) - return; - updateTotalIOB(); - } - - @Override - public IobTotal getLastCalculation() { - return lastCalculation; - } - - @Override - public IobTotal getCalculationToTime(long time) { - checkForExpired(tempBasals); - checkForExpired(extendedBoluses); - Date now = new Date(time); - IobTotal total = new IobTotal(time); - for (Integer pos = 0; pos < tempBasals.size(); pos++) { - TempBasal t = tempBasals.get(pos); - if (t.timeStart.getTime() > time) continue; - IobTotal calc = t.iobCalc(now); - total.plus(calc); - } - if (useExtendedBoluses) { - for (Integer pos = 0; pos < extendedBoluses.size(); pos++) { - TempBasal t = extendedBoluses.get(pos); - if (t.timeStart.getTime() > time) continue; - IobTotal calc = t.iobCalc(now); - total.plus(calc); - } - } - return total; - } - - @Override - public void updateTotalIOB() { - IobTotal total = getCalculationToTime(new Date().getTime()); - - lastCalculationTimestamp = new Date().getTime(); - lastCalculation = total; - } - - @Nullable - @Override - public TempBasal getTempBasal(Date time) { - checkForExpired(tempBasals); - for (TempBasal t : tempBasals) { - if (t.isInProgress(time)) return t; - } - return null; - } - - @Override - public TempBasal getExtendedBolus(Date time) { - checkForExpired(extendedBoluses); - for (TempBasal t : extendedBoluses) { - if (t.isInProgress(time)) return t; - } - return null; - } - - @Override - public long oldestDataAvaialable() { - long oldestTemp = new Date().getTime(); - if (tempBasals.size() > 0) - oldestTemp = Math.min(oldestTemp, tempBasals.get(tempBasals.size() - 1).timeStart.getTime()); - if (extendedBoluses.size() > 0) - oldestTemp = Math.min(oldestTemp, extendedBoluses.get(extendedBoluses.size() - 1).timeStart.getTime()); - oldestTemp -= 15 * 60 * 1000L; // allow 15 min before - return oldestTemp; - } - - List getMergedList() { - if (useExtendedBoluses) { - List merged = new ArrayList(); - merged.addAll(tempBasals); - merged.addAll(extendedBoluses); - - class CustomComparator implements Comparator { - public int compare(TempBasal object1, TempBasal object2) { - return (int) (object2.timeIndex - object1.timeIndex); - } - } - Collections.sort(merged, new CustomComparator()); - return merged; - } else { - return tempBasals; - } - } - - @Subscribe - public void onStatusEvent(final EventTempBasalChange ev) { - initializeData(); - } - - public void onStatusEvent(final EventPreferenceChange s) { - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); - useExtendedBoluses = sharedPreferences.getBoolean("danar_useextended", false); - initializeData(); - } - - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java deleted file mode 100644 index 08a09aa644..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java +++ /dev/null @@ -1,114 +0,0 @@ -package info.nightscout.androidaps.plugins.TempTargetRange; - -import android.support.annotation.Nullable; - -import com.squareup.otto.Subscribe; - -import java.util.Date; -import java.util.List; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; - -/** - * Created by mike on 13/01/17. - */ - -public class TempTargetRangePlugin implements PluginBase { - - static boolean fragmentEnabled = true; - static boolean fragmentVisible = true; - - private static List tempTargets; - - TempTargetRangePlugin() { - initializeData(); - MainApp.bus().register(this); - } - - @Override - public int getType() { - return PluginBase.GENERAL; - } - - @Override - public String getFragmentClass() { - return TempTargetRangeFragment.class.getName(); - } - - @Override - public String getName() { - return MainApp.sResources.getString(R.string.temptargetrange); - } - - @Override - public String getNameShort() { - String name = MainApp.sResources.getString(R.string.temptargetrange_shortname); - if (!name.trim().isEmpty()){ - //only if translation exists - return name; - } - // use long name as fallback - return getName(); - } - - @Override - public boolean isEnabled(int type) { - return type == GENERAL && fragmentEnabled; - } - - @Override - public boolean isVisibleInTabs(int type) { - return type == GENERAL && fragmentVisible; - } - - @Override - public boolean canBeHidden(int type) { - return true; - } - - @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == GENERAL) { - this.fragmentEnabled = fragmentEnabled; - } - } - - @Override - public void setFragmentVisible(int type, boolean fragmentVisible) { - if (type == GENERAL) this.fragmentVisible = fragmentVisible; - } - - public static boolean isEnabled() { - return fragmentEnabled; - } - - @Subscribe - public void onStatusEvent(final EventTempTargetRangeChange ev) { - initializeData(); - } - - public void initializeData() { - long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * 24); - tempTargets = MainApp.getDbHelper().getTemptargetsDataFromTime(fromMills, false); - } - - public List getList() { - return tempTargets; - } - - @Nullable - public TempTarget getTempTargetInProgress(long time) { - for (int i = 0; i < tempTargets.size(); i++) { - // a zero-duration temp target will cancel all prior targets - if (tempTargets.get(i).duration == 0) return null; - - if (tempTargets.get(i).timeStart.getTime() > time) continue; - if (tempTargets.get(i).getPlannedTimeEnd().getTime() >= time) return tempTargets.get(i); - } - return null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/events/EventTempTargetRangeChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/events/EventTempTargetRangeChange.java deleted file mode 100644 index 8d5f537fec..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/events/EventTempTargetRangeChange.java +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.plugins.TempTargetRange.events; - -/** - * Created by mike on 13.01.2017. - */ - -public class EventTempTargetRangeChange { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java index 320aba3956..1bf66ca5ec 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java @@ -1,49 +1,26 @@ package info.nightscout.androidaps.plugins.Treatments; -import android.app.Activity; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.graphics.Paint; import android.os.Bundle; -import android.preference.PreferenceManager; import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AlertDialog; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; +import android.support.v4.app.FragmentTransaction; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.LinearLayout; import android.widget.TextView; -import com.crashlytics.android.answers.Answers; -import com.crashlytics.android.answers.CustomEvent; -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.Services.Intents; -import info.nightscout.androidaps.data.Iob; -import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.ToastUtils; +import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsBolusFragment; +import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsExtendedBolusesFragment; +import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsProfileSwitchFragment; +import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTempTargetFragment; +import info.nightscout.androidaps.plugins.Treatments.fragments.TreatmentsTemporaryBasalsFragment; -public class TreatmentsFragment extends Fragment implements View.OnClickListener, FragmentBase { +public class TreatmentsFragment extends Fragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(TreatmentsFragment.class); private static TreatmentsPlugin treatmentsPlugin = new TreatmentsPlugin(); @@ -52,203 +29,75 @@ public class TreatmentsFragment extends Fragment implements View.OnClickListener return treatmentsPlugin; } - RecyclerView recyclerView; - LinearLayoutManager llm; - - TextView iobTotal; - TextView activityTotal; - Button refreshFromNS; - - Context context; - - public class RecyclerViewAdapter extends RecyclerView.Adapter { - - List treatments; - - RecyclerViewAdapter(List treatments) { - this.treatments = treatments; - } - - @Override - public TreatmentsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_item, viewGroup, false); - TreatmentsViewHolder treatmentsViewHolder = new TreatmentsViewHolder(v); - return treatmentsViewHolder; - } - - @Override - public void onBindViewHolder(TreatmentsViewHolder holder, int position) { - if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null) // app not initialized yet - return; - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile == null) - return; - holder.date.setText(DateUtil.dateAndTimeString(treatments.get(position).created_at)); - holder.insulin.setText(DecimalFormatter.to2Decimal(treatments.get(position).insulin) + " U"); - holder.carbs.setText(DecimalFormatter.to0Decimal(treatments.get(position).carbs) + " g"); - Iob iob = treatments.get(position).iobCalc(new Date(), profile.getDia()); - holder.iob.setText(DecimalFormatter.to2Decimal(iob.iobContrib) + " U"); - holder.activity.setText(DecimalFormatter.to3Decimal(iob.activityContrib) + " U"); - holder.mealOrCorrection.setText(treatments.get(position).mealBolus ? MainApp.sResources.getString(R.string.mealbolus) : MainApp.sResources.getString(R.string.correctionbous)); - if (iob.iobContrib != 0) - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.colorAffectingIOB)); - else - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.cardColorBackground)); - holder.remove.setTag(treatments.get(position)); - } - - @Override - public int getItemCount() { - return treatments.size(); - } - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - } - - public class TreatmentsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - CardView cv; - TextView date; - TextView insulin; - TextView carbs; - TextView iob; - TextView activity; - TextView mealOrCorrection; - LinearLayout dateLinearLayout; - TextView remove; - - TreatmentsViewHolder(View itemView) { - super(itemView); - cv = (CardView) itemView.findViewById(R.id.treatments_cardview); - date = (TextView) itemView.findViewById(R.id.treatments_date); - insulin = (TextView) itemView.findViewById(R.id.treatments_insulin); - carbs = (TextView) itemView.findViewById(R.id.treatments_carbs); - iob = (TextView) itemView.findViewById(R.id.treatments_iob); - activity = (TextView) itemView.findViewById(R.id.treatments_activity); - mealOrCorrection = (TextView) itemView.findViewById(R.id.treatments_mealorcorrection); - dateLinearLayout = (LinearLayout) itemView.findViewById(R.id.treatments_datelinearlayout); - remove = (TextView) itemView.findViewById(R.id.treatments_remove); - remove.setOnClickListener(this); - remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - } - - @Override - public void onClick(View v) { - final Treatment treatment = (Treatment) v.getTag(); - final Context finalContext = context; - switch (v.getId()) { - case R.id.treatments_remove: - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); - builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(treatment.created_at)); - builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - final String _id = treatment._id; - if (_id != null && !_id.equals("")) { - MainApp.getConfigBuilder().removeCareportalEntryFromNS(_id); - } - MainApp.getDbHelper().delete(treatment); - treatmentsPlugin.initializeData(); - updateGUI(); - Answers.getInstance().logCustom(new CustomEvent("RefreshTreatments")); - } - }); - builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); - builder.show(); - break; - } - } - } - } + TextView treatmentsTab; + TextView extendedBolusesTab; + TextView tempBasalsTab; + TextView tempTargetTab; + TextView profileSwitchTab; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.treatments_fragment, container, false); - recyclerView = (RecyclerView) view.findViewById(R.id.treatments_recyclerview); - recyclerView.setHasFixedSize(true); - llm = new LinearLayoutManager(view.getContext()); - recyclerView.setLayoutManager(llm); + treatmentsTab = (TextView) view.findViewById(R.id.treatments_treatments); + extendedBolusesTab = (TextView) view.findViewById(R.id.treatments_extendedboluses); + tempBasalsTab = (TextView) view.findViewById(R.id.treatments_tempbasals); + tempTargetTab = (TextView) view.findViewById(R.id.treatments_temptargets); + profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches); + treatmentsTab.setOnClickListener(this); + extendedBolusesTab.setOnClickListener(this); + tempBasalsTab.setOnClickListener(this); + tempTargetTab.setOnClickListener(this); + profileSwitchTab.setOnClickListener(this); - RecyclerViewAdapter adapter = new RecyclerViewAdapter(TreatmentsPlugin.treatments); - recyclerView.setAdapter(adapter); + setFragment(new TreatmentsBolusFragment()); + setBackgroundColorOnSelected(treatmentsTab); - iobTotal = (TextView) view.findViewById(R.id.treatments_iobtotal); - activityTotal = (TextView) view.findViewById(R.id.treatments_iobactivitytotal); - - refreshFromNS = (Button) view.findViewById(R.id.treatments_reshreshfromnightscout); - refreshFromNS.setOnClickListener(this); - - context = getContext(); - - updateGUI(); return view; } @Override - public void onClick(View view) { - switch (view.getId()) { - case R.id.treatments_reshreshfromnightscout: - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getContext()); - boolean nsUploadOnly = SP.getBoolean("ns_upload_only", false); - if (nsUploadOnly) { - ToastUtils.showToastInUiThread(getContext(), this.getContext().getString(R.string.ns_upload_only_enabled)); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); - builder.setTitle(this.getContext().getString(R.string.confirmation)); - builder.setMessage(this.getContext().getString(R.string.refreshtreatmentsfromnightscout)); - builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - MainApp.getDbHelper().resetTreatments(); - treatmentsPlugin.initializeData(); - updateGUI(); - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - } - }); - builder.setNegativeButton(this.getContext().getString(R.string.cancel), null); - builder.show(); - } + public void onClick(View v) { + + switch (v.getId()) { + case R.id.treatments_treatments: + setFragment(new TreatmentsBolusFragment()); + setBackgroundColorOnSelected(treatmentsTab); + break; + case R.id.treatments_extendedboluses: + setFragment(new TreatmentsExtendedBolusesFragment()); + setBackgroundColorOnSelected(extendedBolusesTab); + break; + case R.id.treatments_tempbasals: + setFragment(new TreatmentsTemporaryBasalsFragment()); + setBackgroundColorOnSelected(tempBasalsTab); + break; + case R.id.treatments_temptargets: + setFragment(new TreatmentsTempTargetFragment()); + setBackgroundColorOnSelected(tempTargetTab); + break; + case R.id.treatments_profileswitches: + setFragment(new TreatmentsProfileSwitchFragment()); + setBackgroundColorOnSelected(profileSwitchTab); break; } } - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); + private void setFragment(Fragment selectedFragment) { + FragmentTransaction ft = getChildFragmentManager().beginTransaction(); + ft.replace(R.id.treatments_fragment_container, selectedFragment); // f2_container is your FrameLayout container + ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); + ft.addToBackStack(null); + ft.commit(); } - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - updateGUI(); + private void setBackgroundColorOnSelected(TextView selected) { + treatmentsTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); + extendedBolusesTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); + tempBasalsTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); + tempTargetTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); + profileSwitchTab.setBackgroundColor(MainApp.sResources.getColor(R.color.defaultbackground)); + selected.setBackgroundColor(MainApp.sResources.getColor(R.color.tabBgColorSelected)); } - - @Subscribe - public void onStatusEvent(final EventTreatmentChange ev) { - updateGUI(); - } - - public void updateGUI() { - Activity activity = getActivity(); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile == null) - return; - if (activity != null && recyclerView != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.treatments), false); - if (TreatmentsPlugin.lastCalculation != null) - iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.lastCalculation.iob) + " U"); - if (TreatmentsPlugin.lastCalculation != null) - activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.lastCalculation.activity) + " U"); - } - }); - } - -} +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java index c49e26553e..50bb0c7892 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,24 +1,42 @@ package info.nightscout.androidaps.plugins.Treatments; +import android.support.annotation.Nullable; + import com.squareup.otto.Subscribe; 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.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.MealData; +import info.nightscout.androidaps.data.OverlappingIntervals; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileIntervals; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventReloadTempBasalData; +import info.nightscout.androidaps.events.EventReloadTreatmentData; +import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.utils.SP; /** @@ -27,10 +45,14 @@ import info.nightscout.utils.SP; public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { private static Logger log = LoggerFactory.getLogger(TreatmentsPlugin.class); - public static long lastCalculationTimestamp = 0; - public static IobTotal lastCalculation; + public static IobTotal lastTreatmentCalculation; + public static IobTotal lastTempBasalsCalculation; public static List treatments; + private static OverlappingIntervals tempBasals = new OverlappingIntervals<>(); + private static OverlappingIntervals extendedBoluses = new OverlappingIntervals<>(); + private static OverlappingIntervals tempTargets = new OverlappingIntervals<>(); + private static ProfileIntervals profiles = new ProfileIntervals<>(); private static boolean fragmentEnabled = true; private static boolean fragmentVisible = true; @@ -48,7 +70,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { @Override public String getNameShort() { String name = MainApp.sResources.getString(R.string.treatments_shortname); - if (!name.trim().isEmpty()){ + if (!name.trim().isEmpty()) { //only if translation exists return name; } @@ -71,6 +93,16 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return !Config.NSCLIENT; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == TREATMENT) this.fragmentEnabled = fragmentEnabled; @@ -88,83 +120,350 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { public TreatmentsPlugin() { MainApp.bus().register(this); - initializeData(); + initializeTempBasalData(); + initializeTreatmentData(); + initializeExtendedBolusData(); + initializeTempTargetData(); + initializeProfileSwitchData(); } - public void initializeData() { - double dia = 3; - if (MainApp.getConfigBuilder().getActiveProfile() != null && MainApp.getConfigBuilder().getActiveProfile().getProfile() != null) - dia = MainApp.getConfigBuilder().getActiveProfile().getProfile().getDia(); + public static void initializeTreatmentData() { + // Treatments + double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia(); long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)); + treatments = MainApp.getDbHelper().getTreatmentDataFromTime(fromMills, false); } - /* - * Recalculate IOB if value is older than 1 minute - */ - public void updateTotalIOBIfNeeded() { - if (lastCalculationTimestamp > new Date().getTime() - 60 * 1000) - return; - updateTotalIOB(); + public static void initializeTempBasalData() { + // Treatments + double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia(); + long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)); + + tempBasals.reset().add(MainApp.getDbHelper().getTemporaryBasalsDataFromTime(fromMills, false)); + + } + + public static void initializeExtendedBolusData() { + // Treatments + double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia(); + long fromMills = (long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)); + + extendedBoluses.reset().add(MainApp.getDbHelper().getExtendedBolusDataFromTime(fromMills, false)); + + } + + public void initializeTempTargetData() { + long fromMills = new Date().getTime() - 60 * 60 * 1000L * 24; + tempTargets.reset().add(MainApp.getDbHelper().getTemptargetsDataFromTime(fromMills, false)); + } + + public void initializeProfileSwitchData() { + profiles.reset().add(MainApp.getDbHelper().getProfileSwitchData(false)); } @Override - public IobTotal getLastCalculation() { - return lastCalculation; + public IobTotal getLastCalculationTreatments() { + return lastTreatmentCalculation; } @Override - public IobTotal getCalculationToTime(long time) { + public IobTotal getCalculationToTimeTreatments(long time) { IobTotal total = new IobTotal(time); - if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet - return total; - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return total; Double dia = profile.getDia(); - Date now = new Date(time); for (Integer pos = 0; pos < treatments.size(); pos++) { Treatment t = treatments.get(pos); - if (t.created_at.getTime() > time) continue; - Iob tIOB = t.iobCalc(now, dia); + if (t.date > time) continue; + Iob tIOB = t.iobCalc(time, dia); total.iob += tIOB.iobContrib; total.activity += tIOB.activityContrib; - Iob bIOB = t.iobCalc(now, dia / SP.getInt("openapsama_bolussnooze_dia_divisor", 2)); + Iob bIOB = t.iobCalc(time, dia / SP.getInt("openapsama_bolussnooze_dia_divisor", 2)); total.bolussnooze += bIOB.iobContrib; } + + if (!MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) + for (Integer pos = 0; pos < extendedBoluses.size(); pos++) { + ExtendedBolus e = extendedBoluses.get(pos); + if (e.date > time) continue; + IobTotal calc = e.iobCalc(time); + total.plus(calc); + } return total; } @Override - public void updateTotalIOB() { - IobTotal total = getCalculationToTime(new Date().getTime()); + public void updateTotalIOBTreatments() { + IobTotal total = getCalculationToTimeTreatments(new Date().getTime()); - lastCalculationTimestamp = new Date().getTime(); - lastCalculation = total; + lastTreatmentCalculation = total; } @Override public MealData getMealData() { MealData result = new MealData(); + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) return result; + + long now = new Date().getTime(); + long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue(); + for (Treatment treatment : treatments) { - result.addTreatment(treatment); + long t = treatment.date; + if (t > dia_ago && t <= now) { + if (treatment.carbs >= 1) { + result.carbs += treatment.carbs; + } + if (treatment.insulin > 0 && treatment.mealBolus) { + result.boluses += treatment.insulin; + } + } + } + + AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData(); + if (autosensData != null) { + result.mealCOB = autosensData.cob; } return result; } @Override - public List getTreatments() { + public List getTreatmentsFromHistory() { return treatments; } - @Subscribe - public void onStatusEvent(final EventTreatmentChange ev) { - initializeData(); - updateTotalIOB(); + @Override + public List getTreatments5MinBackFromHistory(long time) { + List in5minback = new ArrayList<>(); + for (Integer pos = 0; pos < treatments.size(); pos++) { + Treatment t = treatments.get(pos); + if (t.date <= time && t.date > time - 5 * 60 * 1000) + in5minback.add(t); + } + return in5minback; } + @Override + public boolean isInHistoryRealTempBasalInProgress() { + return getRealTempBasalFromHistory(new Date().getTime()) != null; + } + + @Override + public TemporaryBasal getRealTempBasalFromHistory(long time) { + return (TemporaryBasal) tempBasals.getValueByInterval(time); + } + + @Override + public boolean isTempBasalInProgress() { + return getTempBasalFromHistory(new Date().getTime()) != null; + } + + @Override + public boolean isInHistoryExtendedBoluslInProgress() { + return getExtendedBolusFromHistory(new Date().getTime()) != null; //TODO: crosscheck here + } + + @Subscribe + public void onStatusEvent(final EventReloadTreatmentData ev) { + log.debug("EventReloadTreatmentData"); + initializeTreatmentData(); + initializeExtendedBolusData(); + updateTotalIOBTreatments(); + } + + @Subscribe + public void onStatusEvent(final EventReloadTempBasalData ev) { + log.debug("EventReloadTempBasalData"); + initializeTempBasalData(); + updateTotalIOBTempBasals(); + } + + @Override + public IobTotal getLastCalculationTempBasals() { + return lastTempBasalsCalculation; + } + + @Override + public IobTotal getCalculationToTimeTempBasals(long time) { + IobTotal total = new IobTotal(time); + for (Integer pos = 0; pos < tempBasals.size(); pos++) { + TemporaryBasal t = tempBasals.get(pos); + if (t.date > time) continue; + IobTotal calc = t.iobCalc(time); + //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); + total.plus(calc); + } + if (MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) { + IobTotal totalExt = new IobTotal(time); + for (Integer pos = 0; pos < extendedBoluses.size(); pos++) { + ExtendedBolus e = extendedBoluses.get(pos); + if (e.date > time) continue; + IobTotal calc = e.iobCalc(time); + totalExt.plus(calc); + } + // Convert to basal iob + totalExt.basaliob = totalExt.iob; + totalExt.iob = 0d; + totalExt.netbasalinsulin = totalExt.extendedBolusInsulin; + totalExt.hightempinsulin = totalExt.extendedBolusInsulin; + total.plus(totalExt); + } + return total; + } + + @Override + public void updateTotalIOBTempBasals() { + IobTotal total = getCalculationToTimeTempBasals(new Date().getTime()); + + lastTempBasalsCalculation = total; + } + + @Nullable + @Override + public TemporaryBasal getTempBasalFromHistory(long time) { + TemporaryBasal tb = getRealTempBasalFromHistory(time); + if (tb != null) + return tb; + ExtendedBolus eb = getExtendedBolusFromHistory(time); + if (eb != null && MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) + return new TemporaryBasal(eb); + return null; + } + + @Override + public ExtendedBolus getExtendedBolusFromHistory(long time) { + return (ExtendedBolus) extendedBoluses.getValueByInterval(time); + } + + @Override + public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) { + //log.debug("Adding new ExtentedBolus record" + extendedBolus.log()); + return MainApp.getDbHelper().createOrUpdate(extendedBolus); + } + + @Override + public OverlappingIntervals getExtendedBolusesFromHistory() { + return extendedBoluses; + } + + @Override + public double getTempBasalAbsoluteRateHistory() { + PumpInterface pump = MainApp.getConfigBuilder(); + + TemporaryBasal tb = getTempBasalFromHistory(new Date().getTime()); + if (tb != null) { + if (tb.isAbsolute) { + return tb.absoluteRate; + } else { + Double baseRate = pump.getBaseBasalRate(); + Double tempRate = baseRate * (tb.percentRate / 100d); + return tempRate; + } + } + return 0; + } + + @Override + public double getTempBasalRemainingMinutesFromHistory() { + if (isTempBasalInProgress()) + return getTempBasalFromHistory(new Date().getTime()).getPlannedRemainingMinutes(); + return 0; + } + + @Override + public OverlappingIntervals getTemporaryBasalsFromHistory() { + return tempBasals; + } + + @Override + public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { + //log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); + return MainApp.getDbHelper().createOrUpdate(tempBasal); + } + + @Override + public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo) { + Treatment treatment = new Treatment(detailedBolusInfo.insulinInterface); + treatment.date = detailedBolusInfo.date; + treatment.source = detailedBolusInfo.source; + treatment.pumpId = detailedBolusInfo.pumpId; + treatment.insulin = detailedBolusInfo.insulin; + if (detailedBolusInfo.carbTime == 0) + treatment.carbs = detailedBolusInfo.carbs; + treatment.source = detailedBolusInfo.source; + treatment.mealBolus = treatment.carbs > 0; + boolean newRecordCreated = MainApp.getDbHelper().createOrUpdate(treatment); + //log.debug("Adding new Treatment record" + treatment.toString()); + if (detailedBolusInfo.carbTime != 0) { + Treatment carbsTreatment = new Treatment(detailedBolusInfo.insulinInterface); + carbsTreatment.source = detailedBolusInfo.source; + carbsTreatment.pumpId = detailedBolusInfo.pumpId; // but this should never happen + carbsTreatment.date = detailedBolusInfo.date + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records + carbsTreatment.carbs = detailedBolusInfo.carbs; + carbsTreatment.source = detailedBolusInfo.source; + MainApp.getDbHelper().createOrUpdate(carbsTreatment); + //log.debug("Adding new Treatment record" + carbsTreatment); + } + return newRecordCreated; + } + + @Override + public long oldestDataAvailable() { + long oldestTime = new Date().getTime(); + if (tempBasals.size() > 0) + oldestTime = Math.min(oldestTime, tempBasals.get(0).date); + if (extendedBoluses.size() > 0) + oldestTime = Math.min(oldestTime, extendedBoluses.get(0).date); + if (treatments.size() > 0) + oldestTime = Math.min(oldestTime, treatments.get(treatments.size() - 1).date); + oldestTime -= 15 * 60 * 1000L; // allow 15 min before + return oldestTime; + } + + // TempTargets + @Subscribe + public void onStatusEvent(final EventTempTargetChange ev) { + initializeTempTargetData(); + } + + @Nullable + @Override + public TempTarget getTempTargetFromHistory(long time) { + return (TempTarget) tempTargets.getValueByInterval(time); + } + + @Override + public OverlappingIntervals getTempTargetsFromHistory() { + return tempTargets; + } + + // Profile Switch + @Subscribe + public void onStatusEvent(final EventProfileSwitchChange ev) { + initializeProfileSwitchData(); + } + + @Override + public ProfileSwitch getProfileSwitchFromHistory(long time) { + return (ProfileSwitch) profiles.getValueToTime(time); + } + + @Override + public ProfileIntervals getProfileSwitchesFromHistory() { + return profiles; + } + + @Override + public void addToHistoryProfileSwitch(ProfileSwitch profileSwitch) { + //log.debug("Adding new TemporaryBasal record" + profileSwitch.log()); + MainApp.getDbHelper().createOrUpdate(profileSwitch); + } + + } 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 new file mode 100644 index 0000000000..5f6ff02950 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java @@ -0,0 +1,246 @@ +package info.nightscout.androidaps.plugins.Treatments.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.crashlytics.android.answers.Answers; +import com.crashlytics.android.answers.CustomEvent; +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.Services.Intents; +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SP; + +public class TreatmentsBolusFragment extends Fragment implements View.OnClickListener { + private static Logger log = LoggerFactory.getLogger(TreatmentsBolusFragment.class); + + RecyclerView recyclerView; + LinearLayoutManager llm; + + TextView iobTotal; + TextView activityTotal; + Button refreshFromNS; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List treatments; + + RecyclerViewAdapter(List treatments) { + this.treatments = treatments; + } + + @Override + public TreatmentsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_bolus_item, viewGroup, false); + return new TreatmentsViewHolder(v); + } + + @Override + public void onBindViewHolder(TreatmentsViewHolder holder, int position) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) + return; + Treatment t = treatments.get(position); + holder.date.setText(DateUtil.dateAndTimeString(t.date)); + holder.insulin.setText(DecimalFormatter.to2Decimal(t.insulin) + " U"); + holder.carbs.setText(DecimalFormatter.to0Decimal(t.carbs) + " g"); + Iob iob = t.iobCalc(new Date().getTime(), profile.getDia()); + holder.iob.setText(DecimalFormatter.to2Decimal(iob.iobContrib) + " U"); + holder.activity.setText(DecimalFormatter.to3Decimal(iob.activityContrib) + " U"); + holder.mealOrCorrection.setText(t.mealBolus ? MainApp.sResources.getString(R.string.mealbolus) : MainApp.sResources.getString(R.string.correctionbous)); + holder.ph.setVisibility(t.source == Source.PUMP ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(t._id != null ? View.VISIBLE : View.GONE); + if (iob.iobContrib != 0) + holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.iob.setTextColor(holder.carbs.getCurrentTextColor()); + holder.remove.setTag(t); + } + + @Override + public int getItemCount() { + return treatments.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public class TreatmentsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView date; + TextView insulin; + TextView carbs; + TextView iob; + TextView activity; + TextView mealOrCorrection; + TextView remove; + TextView ph; + TextView ns; + + TreatmentsViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.treatments_cardview); + date = (TextView) itemView.findViewById(R.id.treatments_date); + insulin = (TextView) itemView.findViewById(R.id.treatments_insulin); + carbs = (TextView) itemView.findViewById(R.id.treatments_carbs); + iob = (TextView) itemView.findViewById(R.id.treatments_iob); + activity = (TextView) itemView.findViewById(R.id.treatments_activity); + mealOrCorrection = (TextView) itemView.findViewById(R.id.treatments_mealorcorrection); + ph = (TextView) itemView.findViewById(R.id.pump_sign); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.treatments_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final Treatment treatment = (Treatment) v.getTag(); + switch (v.getId()) { + case R.id.treatments_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(treatment.date)); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = treatment._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeCareportalEntryFromNS(_id); + } + MainApp.getDbHelper().delete(treatment); + updateGUI(); + Answers.getInstance().logCustom(new CustomEvent("RemoveTreatment")); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + } + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.treatments_bolus_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.treatments_recyclerview); + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(TreatmentsPlugin.treatments); + recyclerView.setAdapter(adapter); + + iobTotal = (TextView) view.findViewById(R.id.treatments_iobtotal); + activityTotal = (TextView) view.findViewById(R.id.treatments_iobactivitytotal); + + refreshFromNS = (Button) view.findViewById(R.id.treatments_reshreshfromnightscout); + refreshFromNS.setOnClickListener(this); + + boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); + if (nsUploadOnly) + refreshFromNS.setVisibility(View.GONE); + + context = getContext(); + + updateGUI(); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.treatments_reshreshfromnightscout: + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(this.getContext().getString(R.string.refresheventsfromnightscout) + "?"); + builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + MainApp.getDbHelper().resetTreatments(); + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + } + }); + builder.setNegativeButton(this.getContext().getString(R.string.cancel), null); + builder.show(); + break; + } + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventTreatmentChange ev) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + public void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(TreatmentsPlugin.treatments), false); + if (TreatmentsPlugin.lastTreatmentCalculation != null) + iobTotal.setText(DecimalFormatter.to2Decimal(TreatmentsPlugin.lastTreatmentCalculation.iob) + " U"); + if (TreatmentsPlugin.lastTreatmentCalculation != null) + activityTotal.setText(DecimalFormatter.to3Decimal(TreatmentsPlugin.lastTreatmentCalculation.activity) + " U"); + } + }); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java new file mode 100644 index 0000000000..fcd691cf68 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java @@ -0,0 +1,219 @@ +package info.nightscout.androidaps.plugins.Treatments.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.crashlytics.android.answers.Answers; +import com.crashlytics.android.answers.CustomEvent; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.events.EventExtendedBolusChange; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.androidaps.data.OverlappingIntervals; + + +public class TreatmentsExtendedBolusesFragment extends Fragment { + private static Logger log = LoggerFactory.getLogger(TreatmentsExtendedBolusesFragment.class); + + RecyclerView recyclerView; + LinearLayoutManager llm; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + OverlappingIntervals extendedBolusList; + + RecyclerViewAdapter(OverlappingIntervals extendedBolusList) { + this.extendedBolusList = extendedBolusList; + } + + @Override + public ExtendedBolusesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_extendedbolus_item, viewGroup, false); + return new ExtendedBolusesViewHolder(v); + } + + @Override + public void onBindViewHolder(ExtendedBolusesViewHolder holder, int position) { + ExtendedBolus extendedBolus = extendedBolusList.getReversed(position); + holder.ph.setVisibility(extendedBolus.source == Source.PUMP ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(extendedBolus._id != null ? View.VISIBLE : View.GONE); + if (extendedBolus.isEndingEvent()) { + holder.date.setText(DateUtil.dateAndTimeString(extendedBolus.date)); + holder.duration.setText(MainApp.sResources.getString(R.string.cancel)); + holder.insulin.setText(""); + holder.realDuration.setText(""); + holder.iob.setText(""); + holder.insulinSoFar.setText(""); + holder.ratio.setText(""); + } else { + if (extendedBolus.isInProgress()) { + holder.date.setText(DateUtil.dateAndTimeString(extendedBolus.date)); + } else { + holder.date.setText(DateUtil.dateAndTimeString(extendedBolus.date) + " - " + DateUtil.timeString(extendedBolus.end())); + } + holder.duration.setText(DecimalFormatter.to0Decimal(extendedBolus.durationInMinutes) + " min"); + holder.insulin.setText(DecimalFormatter.to2Decimal(extendedBolus.insulin) + " U"); + holder.realDuration.setText(DecimalFormatter.to0Decimal(extendedBolus.getRealDuration()) + " min"); + IobTotal iob = extendedBolus.iobCalc(new Date().getTime()); + holder.iob.setText(DecimalFormatter.to2Decimal(iob.iob) + " U"); + holder.insulinSoFar.setText(DecimalFormatter.to2Decimal(extendedBolus.insulinSoFar()) + " U"); + holder.ratio.setText(DecimalFormatter.to2Decimal(extendedBolus.absoluteRate()) + " U/h"); + if (extendedBolus.isInProgress()) + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.date.setTextColor(holder.insulin.getCurrentTextColor()); + if (extendedBolus.iobCalc(new Date().getTime()).iob != 0) + holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.iob.setTextColor(holder.insulin.getCurrentTextColor()); + } + holder.remove.setTag(extendedBolus); + } + + @Override + public int getItemCount() { + return extendedBolusList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public class ExtendedBolusesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView date; + TextView duration; + TextView insulin; + TextView realDuration; + TextView ratio; + TextView insulinSoFar; + TextView iob; + TextView remove; + TextView ph; + TextView ns; + + ExtendedBolusesViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.extendedboluses_cardview); + date = (TextView) itemView.findViewById(R.id.extendedboluses_date); + duration = (TextView) itemView.findViewById(R.id.extendedboluses_duration); + insulin = (TextView) itemView.findViewById(R.id.extendedboluses_insulin); + realDuration = (TextView) itemView.findViewById(R.id.extendedboluses_realduration); + ratio = (TextView) itemView.findViewById(R.id.extendedboluses_ratio); + insulinSoFar = (TextView) itemView.findViewById(R.id.extendedboluses_netinsulin); + iob = (TextView) itemView.findViewById(R.id.extendedboluses_iob); + ph = (TextView) itemView.findViewById(R.id.pump_sign); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.extendedboluses_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final ExtendedBolus extendedBolus = (ExtendedBolus) v.getTag(); + switch (v.getId()) { + case R.id.extendedboluses_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(extendedBolus.date)); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = extendedBolus._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeCareportalEntryFromNS(_id); + } + MainApp.getDbHelper().delete(extendedBolus); + Answers.getInstance().logCustom(new CustomEvent("RemoveExtendedBolus")); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + } + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.treatments_extendedbolus_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.extendedboluses_recyclerview); + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getConfigBuilder().getExtendedBolusesFromHistory()); + recyclerView.setAdapter(adapter); + + context = getContext(); + + updateGUI(); + return view; + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + public void updateGUI() { + Activity activity = getActivity(); + if (activity != null && recyclerView != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getConfigBuilder().getExtendedBolusesFromHistory()), false); + } + }); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java new file mode 100644 index 0000000000..344abd8346 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java @@ -0,0 +1,210 @@ +package info.nightscout.androidaps.plugins.Treatments.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import com.squareup.otto.Subscribe; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileIntervals; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TempTarget; +import info.nightscout.androidaps.events.EventProfileSwitchChange; +import info.nightscout.androidaps.events.EventTempTargetChange; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.OKDialog; +import info.nightscout.utils.SP; + +/** + * Created by mike on 13/01/17. + */ + +public class TreatmentsProfileSwitchFragment extends Fragment implements View.OnClickListener { + + RecyclerView recyclerView; + LinearLayoutManager llm; + Button refreshFromNS; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + ProfileIntervals profileSwitchList; + + RecyclerViewAdapter(ProfileIntervals profileSwitchList) { + this.profileSwitchList = profileSwitchList; + } + + @Override + public ProfileSwitchViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_profileswitch_item, viewGroup, false); + ProfileSwitchViewHolder ProfileSwitchViewHolder = new ProfileSwitchViewHolder(v); + return ProfileSwitchViewHolder; + } + + @Override + public void onBindViewHolder(ProfileSwitchViewHolder holder, int position) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) return; + ProfileSwitch profileSwitch = profileSwitchList.getReversed(position); + holder.ph.setVisibility(profileSwitch.source == Source.PUMP ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(profileSwitch._id != null ? View.VISIBLE : View.GONE); + + holder.date.setText(DateUtil.dateAndTimeString(profileSwitch.date)); + if (!profileSwitch.isEndingEvent()) { + holder.duration.setText(DecimalFormatter.to0Decimal(profileSwitch.durationInMinutes) + " min"); + } else { + holder.duration.setText(""); + } + holder.name.setText(profileSwitch.profileName); + if (profileSwitch.isInProgress()) + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.date.setTextColor(holder.duration.getCurrentTextColor()); + holder.remove.setTag(profileSwitch); + } + + @Override + public int getItemCount() { + return profileSwitchList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public class ProfileSwitchViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView date; + TextView duration; + TextView name; + TextView remove; + TextView ph; + TextView ns; + + ProfileSwitchViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.profileswitch_cardview); + date = (TextView) itemView.findViewById(R.id.profileswitch_date); + duration = (TextView) itemView.findViewById(R.id.profileswitch_duration); + name = (TextView) itemView.findViewById(R.id.profileswitch_name); + ph = (TextView) itemView.findViewById(R.id.pump_sign); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.profileswitch_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final ProfileSwitch profileSwitch = (ProfileSwitch) v.getTag(); + switch (v.getId()) { + case R.id.profileswitch_remove: + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.confirmation), MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(profileSwitch.date), new Runnable() { + @Override + public void run() { + final String _id = profileSwitch._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeCareportalEntryFromNS(_id); + } + MainApp.getDbHelper().delete(profileSwitch); + } + }); + break; + } + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.treatments_profileswitch_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.profileswitch_recyclerview); + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getConfigBuilder().getProfileSwitchesFromHistory()); + recyclerView.setAdapter(adapter); + + refreshFromNS = (Button) view.findViewById(R.id.profileswitch_refreshfromnightscout); + refreshFromNS.setOnClickListener(this); + + context = getContext(); + + boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); + if (nsUploadOnly) + refreshFromNS.setVisibility(View.GONE); + + updateGUI(); + return view; + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.profileswitch_refreshfromnightscout: + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.confirmation), MainApp.sResources.getString(R.string.refresheventsfromnightscout) + "?", new Runnable() { + @Override + public void run() { + MainApp.getDbHelper().resetProfileSwitch(); + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + } + }); + break; + } + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventProfileSwitchChange ev) { + updateGUI(); + } + + void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getConfigBuilder().getProfileSwitchesFromHistory()), false); + } + }); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangeFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java similarity index 62% rename from app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangeFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java index f9e979ae45..9b2603ef4f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangeFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java @@ -1,13 +1,11 @@ -package info.nightscout.androidaps.plugins.TempTargetRange; +package info.nightscout.androidaps.plugins.Treatments.fragments; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.SharedPreferences; import android.graphics.Paint; import android.os.Bundle; -import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; @@ -18,38 +16,28 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.LinearLayout; import android.widget.TextView; -import com.j256.ormlite.dao.Dao; import com.squareup.otto.Subscribe; -import java.sql.SQLException; -import java.util.List; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.interfaces.FragmentBase; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.events.EventTempTargetChange; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.ToastUtils; +import info.nightscout.utils.NSUpload; +import info.nightscout.androidaps.data.OverlappingIntervals; +import info.nightscout.utils.SP; /** * Created by mike on 13/01/17. */ -public class TempTargetRangeFragment extends Fragment implements View.OnClickListener, FragmentBase { - - private static TempTargetRangePlugin tempTargetRangePlugin = new TempTargetRangePlugin(); - - public static TempTargetRangePlugin getPlugin() { - return tempTargetRangePlugin; - } +public class TreatmentsTempTargetFragment extends Fragment implements View.OnClickListener { RecyclerView recyclerView; LinearLayoutManager llm; @@ -59,32 +47,34 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis public class RecyclerViewAdapter extends RecyclerView.Adapter { - List tempTargetList; + OverlappingIntervals tempTargetList; - RecyclerViewAdapter(List TempTargetList) { + RecyclerViewAdapter(OverlappingIntervals TempTargetList) { this.tempTargetList = TempTargetList; } @Override public TempTargetsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.temptargetrange_item, viewGroup, false); + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_temptarget_item, viewGroup, false); TempTargetsViewHolder TempTargetsViewHolder = new TempTargetsViewHolder(v); return TempTargetsViewHolder; } @Override public void onBindViewHolder(TempTargetsViewHolder holder, int position) { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return; - TempTarget tempTarget = tempTargetList.get(position); - if (tempTarget.duration != 0) { - holder.date.setText(DateUtil.dateAndTimeString(tempTarget.timeStart) + " - " + DateUtil.timeString(tempTargetList.get(position).getPlannedTimeEnd())); - holder.duration.setText(DecimalFormatter.to0Decimal(tempTarget.duration) + " min"); + TempTarget tempTarget = tempTargetList.getReversed(position); + holder.ph.setVisibility(tempTarget.source == Source.PUMP ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(tempTarget._id != null ? View.VISIBLE : View.GONE); + if (!tempTarget.isEndingEvent()) { + holder.date.setText(DateUtil.dateAndTimeString(tempTarget.date) + " - " + DateUtil.timeString(tempTarget.originalEnd())); + holder.duration.setText(DecimalFormatter.to0Decimal(tempTarget.durationInMinutes) + " min"); holder.low.setText(tempTarget.lowValueToUnitsToString(profile.getUnits())); holder.high.setText(tempTarget.highValueToUnitsToString(profile.getUnits())); holder.reason.setText(tempTarget.reason); } else { - holder.date.setText(DateUtil.dateAndTimeString(tempTarget.timeStart)); + holder.date.setText(DateUtil.dateAndTimeString(tempTarget.date)); holder.duration.setText(R.string.cancel); holder.low.setText(""); holder.high.setText(""); @@ -93,9 +83,9 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis holder.reasonColon.setText(""); } if (tempTarget.isInProgress()) - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress)); + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); else - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.cardColorBackground)); + holder.date.setTextColor(holder.reasonColon.getCurrentTextColor()); holder.remove.setTag(tempTarget); } @@ -119,7 +109,8 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis TextView reasonLabel; TextView reasonColon; TextView remove; - LinearLayout dateLinearLayout; + TextView ph; + TextView ns; TempTargetsViewHolder(View itemView) { super(itemView); @@ -131,10 +122,11 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis reason = (TextView) itemView.findViewById(R.id.temptargetrange_reason); reasonLabel = (TextView) itemView.findViewById(R.id.temptargetrange_reason_label); reasonColon = (TextView) itemView.findViewById(R.id.temptargetrange_reason_colon); + ph = (TextView) itemView.findViewById(R.id.pump_sign); + ns = (TextView) itemView.findViewById(R.id.ns_sign); remove = (TextView) itemView.findViewById(R.id.temptargetrange_remove); remove.setOnClickListener(this); remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); - dateLinearLayout = (LinearLayout) itemView.findViewById(R.id.temptargetrange_datelinearlayout); } @Override @@ -145,20 +137,14 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis case R.id.temptargetrange_remove: AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); - builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(tempTarget.timeStart)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(tempTarget.date)); builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { final String _id = tempTarget._id; if (_id != null && !_id.equals("")) { - MainApp.getConfigBuilder().removeCareportalEntryFromNS(_id); - } - try { - Dao daoTempTargets = MainApp.getDbHelper().getDaoTempTargets(); - daoTempTargets.delete(tempTarget); - MainApp.bus().post(new EventTempTargetRangeChange()); - } catch (SQLException e) { - e.printStackTrace(); + NSUpload.removeCareportalEntryFromNS(_id); } + MainApp.getDbHelper().delete(tempTarget); } }); builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); @@ -172,14 +158,14 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.temptargetrange_fragment, container, false); + View view = inflater.inflate(R.layout.treatments_temptarget_fragment, container, false); recyclerView = (RecyclerView) view.findViewById(R.id.temptargetrange_recyclerview); recyclerView.setHasFixedSize(true); llm = new LinearLayoutManager(view.getContext()); recyclerView.setLayoutManager(llm); - RecyclerViewAdapter adapter = new RecyclerViewAdapter(tempTargetRangePlugin.getList()); + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getConfigBuilder().getTempTargetsFromHistory()); recyclerView.setAdapter(adapter); refreshFromNS = (Button) view.findViewById(R.id.temptargetrange_refreshfromnightscout); @@ -187,6 +173,10 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis context = getContext(); + boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); + if (nsUploadOnly) + refreshFromNS.setVisibility(View.GONE); + updateGUI(); return view; } @@ -195,28 +185,21 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis public void onClick(View view) { switch (view.getId()) { case R.id.temptargetrange_refreshfromnightscout: - SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getContext()); - boolean nsUploadOnly = SP.getBoolean("ns_upload_only", false); - if (nsUploadOnly) { - ToastUtils.showToastInUiThread(getContext(), this.getContext().getString(R.string.ns_upload_only_enabled)); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); - builder.setTitle(this.getContext().getString(R.string.confirmation)); - builder.setMessage(this.getContext().getString(R.string.refreshtemptargetsfromnightscout)); - builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - MainApp.getDbHelper().resetTempTargets(); - tempTargetRangePlugin.initializeData(); - updateGUI(); - Intent restartNSClient = new Intent(Intents.ACTION_RESTART); - MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - } - }); - builder.setNegativeButton(this.getContext().getString(R.string.cancel), null); - builder.show(); - } + AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); + builder.setTitle(this.getContext().getString(R.string.confirmation)); + builder.setMessage(this.getContext().getString(R.string.refresheventsfromnightscout) + " ?"); + builder.setPositiveButton(this.getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + MainApp.getDbHelper().resetTempTargets(); + Intent restartNSClient = new Intent(Intents.ACTION_RESTART); + MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); + } + }); + builder.setNegativeButton(this.getContext().getString(R.string.cancel), null); + builder.show(); break; } + } @Override @@ -232,7 +215,7 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis } @Subscribe - public void onStatusEvent(final EventTempTargetRangeChange ev) { + public void onStatusEvent(final EventTempTargetChange ev) { updateGUI(); } @@ -242,7 +225,7 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis activity.runOnUiThread(new Runnable() { @Override public void run() { - recyclerView.swapAdapter(new RecyclerViewAdapter(tempTargetRangePlugin.getList()), false); + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getConfigBuilder().getTempTargetsFromHistory()), false); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java new file mode 100644 index 0000000000..61c93abd96 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java @@ -0,0 +1,242 @@ +package info.nightscout.androidaps.plugins.Treatments.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.CardView; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.crashlytics.android.answers.Answers; +import com.crashlytics.android.answers.CustomEvent; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.androidaps.data.OverlappingIntervals; + + +public class TreatmentsTemporaryBasalsFragment extends Fragment { + private static Logger log = LoggerFactory.getLogger(TreatmentsTemporaryBasalsFragment.class); + + RecyclerView recyclerView; + LinearLayoutManager llm; + + TextView tempBasalTotalView; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + OverlappingIntervals tempBasalList; + + RecyclerViewAdapter(OverlappingIntervals tempBasalList) { + this.tempBasalList = tempBasalList; + } + + @Override + public TempBasalsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.treatments_tempbasals_item, viewGroup, false); + return new TempBasalsViewHolder(v); + } + + @Override + public void onBindViewHolder(TempBasalsViewHolder holder, int position) { + TemporaryBasal tempBasal = tempBasalList.getReversed(position); + holder.ph.setVisibility(tempBasal.source == Source.PUMP ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(tempBasal._id != null ? View.VISIBLE : View.GONE); + if (tempBasal.isEndingEvent()) { + holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date)); + holder.duration.setText(MainApp.sResources.getString(R.string.cancel)); + holder.absolute.setText(""); + holder.percent.setText(""); + holder.realDuration.setText(""); + holder.iob.setText(""); + holder.netInsulin.setText(""); + holder.netRatio.setText(""); + holder.extendedFlag.setVisibility(View.GONE); + holder.iob.setTextColor(holder.netRatio.getCurrentTextColor()); + } else { + if (tempBasal.isInProgress()) { + holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date)); + } else { + holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date) + " - " + DateUtil.timeString(tempBasal.end())); + } + holder.duration.setText(DecimalFormatter.to0Decimal(tempBasal.durationInMinutes) + " min"); + if (tempBasal.isAbsolute) { + holder.absolute.setText(DecimalFormatter.to0Decimal(tempBasal.tempBasalConvertedToAbsolute(tempBasal.date)) + " U/h"); + holder.percent.setText(""); + } else { + holder.absolute.setText(""); + holder.percent.setText(DecimalFormatter.to0Decimal(tempBasal.percentRate) + "%"); + } + holder.realDuration.setText(DecimalFormatter.to0Decimal(tempBasal.getRealDuration()) + " min"); + IobTotal iob = tempBasal.iobCalc(new Date().getTime()); + holder.iob.setText(DecimalFormatter.to2Decimal(iob.basaliob) + " U"); + holder.netInsulin.setText(DecimalFormatter.to2Decimal(iob.netInsulin) + " U"); + holder.netRatio.setText(DecimalFormatter.to2Decimal(iob.netRatio) + " U/h"); + //holder.extendedFlag.setVisibility(tempBasal.isExtended ? View.VISIBLE : View.GONE); + holder.extendedFlag.setVisibility(View.GONE); + if (tempBasal.isInProgress()) + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.date.setTextColor(holder.netRatio.getCurrentTextColor()); + if (tempBasal.iobCalc(new Date().getTime()).basaliob != 0) + holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.iob.setTextColor(holder.netRatio.getCurrentTextColor()); + } + holder.remove.setTag(tempBasal); + } + + @Override + public int getItemCount() { + return tempBasalList.size(); + } + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + } + + public class TempBasalsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + CardView cv; + TextView date; + TextView duration; + TextView absolute; + TextView percent; + TextView realDuration; + TextView netRatio; + TextView netInsulin; + TextView iob; + TextView extendedFlag; + TextView remove; + TextView ph; + TextView ns; + + TempBasalsViewHolder(View itemView) { + super(itemView); + cv = (CardView) itemView.findViewById(R.id.tempbasals_cardview); + date = (TextView) itemView.findViewById(R.id.tempbasals_date); + duration = (TextView) itemView.findViewById(R.id.tempbasals_duration); + absolute = (TextView) itemView.findViewById(R.id.tempbasals_absolute); + percent = (TextView) itemView.findViewById(R.id.tempbasals_percent); + realDuration = (TextView) itemView.findViewById(R.id.tempbasals_realduration); + netRatio = (TextView) itemView.findViewById(R.id.tempbasals_netratio); + netInsulin = (TextView) itemView.findViewById(R.id.tempbasals_netinsulin); + iob = (TextView) itemView.findViewById(R.id.tempbasals_iob); + extendedFlag = (TextView) itemView.findViewById(R.id.tempbasals_extendedflag); + ph = (TextView) itemView.findViewById(R.id.pump_sign); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.tempbasals_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final TemporaryBasal tempBasal = (TemporaryBasal) v.getTag(); + switch (v.getId()) { + case R.id.tempbasals_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(tempBasal.date)); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = tempBasal._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeCareportalEntryFromNS(_id); + } + MainApp.getDbHelper().delete(tempBasal); + Answers.getInstance().logCustom(new CustomEvent("RemoveTempBasal")); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + } + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.treatments_tempbasals_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.tempbasals_recyclerview); + recyclerView.setHasFixedSize(true); + llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getConfigBuilder().getTemporaryBasalsFromHistory()); + recyclerView.setAdapter(adapter); + + tempBasalTotalView = (TextView) view.findViewById(R.id.tempbasals_totaltempiob); + + context = getContext(); + + updateGUI(); + return view; + } + + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + } + + @Subscribe + public void onStatusEvent(final EventTempBasalChange ev) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + public void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + recyclerView.swapAdapter(new RecyclerViewAdapter(MainApp.getConfigBuilder().getTemporaryBasalsFromHistory()), false); + if (MainApp.getConfigBuilder().getLastCalculationTempBasals() != null) { + String totalText = DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getLastCalculationTempBasals().basaliob) + " U"; + tempBasalTotalView.setText(totalText); + } + } + }); + } + +} 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 ba93968e78..8fc7e9f868 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 @@ -4,9 +4,6 @@ import android.os.Handler; import android.os.HandlerThread; import android.support.annotation.NonNull; -import com.j256.ormlite.dao.Dao; - -import java.sql.SQLException; import java.text.DecimalFormat; import java.util.Date; @@ -15,17 +12,17 @@ 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.GlucoseStatus; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -46,13 +43,14 @@ public class ActionStringHandler { private static BolusWizard lastBolusWizard = null; private static HandlerThread handlerThread = new HandlerThread(FillDialog.class.getSimpleName()); + static { handlerThread.start(); } - public synchronized static void handleInitiate(String actionstring){ + public synchronized static void handleInitiate(String actionstring) { - if(!BuildConfig.WEAR_CONTROL) return; + if (!BuildConfig.WEAR_CONTROL) return; lastBolusWizard = null; @@ -113,29 +111,24 @@ public class ActionStringHandler { ///////////////////////////////////////////////////////// TEMPTARGET boolean isMGDL = Boolean.parseBoolean(act[1]); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); - if (!(Config.APS && tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL))) { - sendError("TempTargets not possible! Please check your configuration."); - return; - } + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) { sendError("No profile found!"); return; } - if(profile.getUnits().equals(Constants.MGDL) != isMGDL){ + if (profile.getUnits().equals(Constants.MGDL) != isMGDL) { sendError("Different units used on watch and phone!"); return; } int duration = SafeParse.stringToInt(act[2]); - if (duration == 0){ + if (duration == 0) { rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?"; rAction = "temptarget true 0 0 0"; } else { double low = SafeParse.stringToDouble(act[3]); double high = SafeParse.stringToDouble(act[4]); - if(!isMGDL){ + if (!isMGDL) { low *= Constants.MMOLL_TO_MGDL; high *= Constants.MMOLL_TO_MGDL; } @@ -147,7 +140,7 @@ public class ActionStringHandler { sendError("Max-BG out of range!"); return; } - rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2]; + rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2]; rAction = actionstring; } @@ -156,14 +149,14 @@ public class ActionStringHandler { ////////////////////////////////////////////// STATUS rTitle = "STATUS"; rAction = "statusmessage"; - if("pump".equals(act[1])){ + if ("pump".equals(act[1])) { rTitle += " PUMP"; rMessage = getPumpStatus(); - } else if("loop".equals(act[1])){ + } else if ("loop".equals(act[1])) { rTitle += " LOOP"; rMessage = getLoopStatus(); - } else if("targets".equals(act[1])){ + } else if ("targets".equals(act[1])) { rTitle += " TARGETS"; rMessage = getTargetsStatus(); } @@ -173,41 +166,43 @@ public class ActionStringHandler { Integer carbsBeforeConstraints = SafeParse.stringToInt(act[1]); Integer carbsAfterConstraints = MainApp.getConfigBuilder().applyCarbsConstraints(carbsBeforeConstraints); - if(carbsAfterConstraints - carbsBeforeConstraints !=0){ - sendError("Carb constraint violation!"); return; + if (carbsAfterConstraints - carbsBeforeConstraints != 0) { + sendError("Carb constraint violation!"); + return; } boolean useBG = Boolean.parseBoolean(act[2]); boolean useBolusIOB = Boolean.parseBoolean(act[3]); boolean useBasalIOB = Boolean.parseBoolean(act[4]); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) { - sendError("No profile found!"); return; + sendError("No profile found!"); + return; } - BgReading bgReading = GlucoseStatus.actualBg(); - if(bgReading==null && useBG){ - sendError("No recent BG to base calculation on!"); return; + BgReading bgReading = DatabaseHelper.actualBg(); + if (bgReading == null && useBG) { + sendError("No recent BG to base calculation on!"); + return; } DecimalFormat format = new DecimalFormat("0.00"); BolusWizard bolusWizard = new BolusWizard(); - bolusWizard.doCalc(profile.getDefaultProfile(), carbsAfterConstraints, 0d, useBG?bgReading.valueToUnits(profile.getUnits()):0d, 0d, useBolusIOB, useBasalIOB, false, false); + bolusWizard.doCalc(profile, carbsAfterConstraints, 0d, useBG ? bgReading.valueToUnits(profile.getUnits()) : 0d, 0d, useBolusIOB, useBasalIOB, false, false); Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(bolusWizard.calculatedTotalInsulin); - if(insulinAfterConstraints - bolusWizard.calculatedTotalInsulin !=0){ + if (insulinAfterConstraints - bolusWizard.calculatedTotalInsulin != 0) { sendError("Insulin contraint violation!" + - "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) +"!"); + "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!"); return; } - double insulin = bolusWizard.calculatedTotalInsulin; - if(bolusWizard.calculatedTotalInsulin < 0) { + if (bolusWizard.calculatedTotalInsulin < 0) { bolusWizard.calculatedTotalInsulin = 0d; } - if(bolusWizard.calculatedTotalInsulin <=0 && bolusWizard.carbs <=0){ + if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) { rAction = "info"; rTitle = "INFO"; } else { @@ -216,11 +211,13 @@ public class ActionStringHandler { rMessage += "Carbs: " + bolusWizard.carbs + "g"; rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U"; rMessage += "\n_____________"; - rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "; + rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): "; rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U"; - if(useBG)rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U"; - if(useBolusIOB)rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulingFromBolusIOB) + "U"; - if(useBasalIOB)rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulingFromBasalsIOB) + "U"; + if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U"; + if (useBolusIOB) + rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulingFromBolusIOB) + "U"; + if (useBasalIOB) + rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulingFromBasalsIOB) + "U"; lastBolusWizard = bolusWizard; @@ -242,25 +239,24 @@ public class ActionStringHandler { String ret = ""; // decide if enabled/disabled closed/open; what Plugin as APS? final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); - if(activeloop != null && activeloop.isEnabled(activeloop.getType())) { + if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { if (MainApp.getConfigBuilder().isClosedModeEnabled()) { ret += "CLOSED LOOP\n"; } else { ret += "OPEN LOOP\n"; } final APSInterface aps = MainApp.getConfigBuilder().getActiveAPS(); - ret += "APS: " + ((aps==null)?"NO APS SELECTED!":((PluginBase) aps).getName()); - if(activeloop.lastRun != null){ - if(activeloop.lastRun.lastAPSRun != null) + ret += "APS: " + ((aps == null) ? "NO APS SELECTED!" : ((PluginBase) aps).getName()); + if (activeloop.lastRun != null) { + if (activeloop.lastRun.lastAPSRun != null) ret += "\nLast Run: " + DateUtil.timeString(activeloop.lastRun.lastAPSRun); - if(activeloop.lastRun.lastEnact != null) + if (activeloop.lastRun.lastEnact != null) ret += "\nLast Enact: " + DateUtil.timeString(activeloop.lastRun.lastEnact); } - } else { ret += "LOOP DISABLED\n"; } @@ -271,23 +267,20 @@ public class ActionStringHandler { @NonNull private static String getTargetsStatus() { String ret = ""; - if (!Config.APS){ + if (!Config.APS) { return "Targets only apply in APS mode!"; } - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile == null){ + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) { return "No profile set :("; } //Check for Temp-Target: - TempTargetRangePlugin tempTargetRangePlugin = (TempTargetRangePlugin) MainApp.getSpecificPlugin(TempTargetRangePlugin.class); - if (Config.APS && tempTargetRangePlugin != null && tempTargetRangePlugin.isEnabled(PluginBase.GENERAL)) { - TempTarget tempTarget = tempTargetRangePlugin.getTempTargetInProgress(new Date().getTime()); - if (tempTarget != null) { - ret += "Temp Target: " + NSProfile.toUnitsString(tempTarget.low, NSProfile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + NSProfile.toUnitsString(tempTarget.high, NSProfile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits()); - ret += "\nuntil: " + DateUtil.timeString(tempTarget.getPlannedTimeEnd()); - ret += "\n\n"; - } + TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(new Date().getTime()); + if (tempTarget != null) { + ret += "Temp Target: " + Profile.toUnitsString(tempTarget.low, Profile.fromMgdlToUnits(tempTarget.low, profile.getUnits()), profile.getUnits()) + " - " + Profile.toUnitsString(tempTarget.high, Profile.fromMgdlToUnits(tempTarget.high, profile.getUnits()), profile.getUnits()); + ret += "\nuntil: " + DateUtil.timeString(tempTarget.originalEnd()); + ret += "\n\n"; } //Default Range/Target @@ -306,9 +299,9 @@ public class ActionStringHandler { } - public synchronized static void handleConfirmation(String actionString){ + public synchronized static void handleConfirmation(String actionString) { - if(!BuildConfig.WEAR_CONTROL) return; + if (!BuildConfig.WEAR_CONTROL) return; //Guard from old or duplicate confirmations @@ -320,10 +313,10 @@ public class ActionStringHandler { // do the parsing, check constraints and enact! String[] act = actionString.split("\\s+"); - if ("fill".equals(act[0])){ + if ("fill".equals(act[0])) { Double amount = SafeParse.stringToDouble(act[1]); Double insulinAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(amount); - if(amount - insulinAfterConstraints != 0){ + if (amount - insulinAfterConstraints != 0) { ToastUtils.showToastInUiThread(MainApp.instance(), "aborting: previously applied constraint changed"); sendError("aborting: previously applied constraint changed"); return; @@ -334,12 +327,12 @@ public class ActionStringHandler { double low = SafeParse.stringToDouble(act[3]); double high = SafeParse.stringToDouble(act[4]); boolean isMGDL = Boolean.parseBoolean(act[1]); - if(!isMGDL){ + if (!isMGDL) { low *= Constants.MMOLL_TO_MGDL; high *= Constants.MMOLL_TO_MGDL; } generateTempTarget(duration, low, high); - } else if ("wizard".equals(act[0])){ + } else if ("wizard".equals(act[0])) { //use last calculation as confirmed string matches doBolus(lastBolusWizard.calculatedTotalInsulin, lastBolusWizard.carbs); @@ -354,28 +347,21 @@ public class ActionStringHandler { private static void generateTempTarget(int duration, double low, double high) { TempTarget tempTarget = new TempTarget(); - tempTarget.timeStart = new Date(); - tempTarget.duration = duration; + tempTarget.date = new Date().getTime(); + tempTarget.durationInMinutes = duration; tempTarget.reason = "WearPlugin"; - if(tempTarget.duration != 0) { + tempTarget.source = Source.USER; + if (tempTarget.durationInMinutes != 0) { tempTarget.low = low; tempTarget.high = high; } else { tempTarget.low = 0; tempTarget.high = 0; } - tempTarget.setTimeIndex(tempTarget.getTimeIndex()); - Dao dao = null; - try { - dao = MainApp.getDbHelper().getDaoTempTargets(); - dao.createIfNotExists(tempTarget); - MainApp.bus().post(new EventTempTargetRangeChange()); + MainApp.getDbHelper().createOrUpdate(tempTarget); - //TODO: Nightscout-Treatment for Temp-Target! - //ConfigBuilderPlugin.uploadCareportalEntryToNS(data); - } catch (SQLException e) { - e.printStackTrace(); - } + //TODO: Nightscout-Treatment for Temp-Target! + //ConfigBuilderPlugin.uploadCareportalEntryToNS(data); } private static void doFillBolus(final Double amount) { @@ -384,9 +370,13 @@ public class ActionStringHandler { handler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(amount, 0, null, false); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = amount; + detailedBolusInfo.addToTreatments = false; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(detailedBolusInfo); if (!result.success) { - sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + + sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + "\n" + result.comment); } @@ -400,9 +390,13 @@ public class ActionStringHandler { handler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(amount, carbs, null, true); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = amount; + detailedBolusInfo.carbs = carbs; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(detailedBolusInfo); if (!result.success) { - sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + + sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + "\n" + result.comment); } @@ -410,7 +404,7 @@ public class ActionStringHandler { }); } - private synchronized static void sendError(String errormessage){ + private synchronized static void sendError(String errormessage) { WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation("ERROR", errormessage, "error"); lastSentTimestamp = System.currentTimeMillis(); lastConfirmActionString = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearFragment.java index 8f4e7f9be2..d243da7d60 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/WearFragment.java @@ -8,19 +8,18 @@ import android.view.View; import android.view.ViewGroup; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.FragmentBase; /** * Created by adrian on 17/11/16. */ -public class WearFragment extends Fragment implements FragmentBase { +public class WearFragment extends Fragment { private static WearPlugin wearPlugin; public static WearPlugin getPlugin(Context ctx) { - if (wearPlugin == null){ + if (wearPlugin == null) { wearPlugin = new WearPlugin(ctx); } 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 0884cdf55e..0c8932278e 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 @@ -5,9 +5,11 @@ import android.content.Intent; import com.squareup.otto.Subscribe; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventBolusRequested; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBasalProfile; import info.nightscout.androidaps.events.EventPreferenceChange; @@ -28,7 +30,7 @@ import info.nightscout.utils.ToastUtils; public class WearPlugin implements PluginBase { - static boolean fragmentEnabled = true; + static boolean fragmentEnabled = Config.WEAR; static boolean fragmentVisible = true; private static WatchUpdaterService watchUS; private final Context ctx; @@ -79,6 +81,16 @@ public class WearPlugin implements PluginBase { return true; } + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + @Override public void setFragmentEnabled(int type, boolean fragmentEnabled) { if (type == GENERAL) { @@ -138,6 +150,11 @@ public class WearPlugin implements PluginBase { sendDataToWatch(true, true, false); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + sendDataToWatch(true, true, false); + } + @Subscribe public void onStatusEvent(final EventNewBG ev) { sendDataToWatch(true, true, true); 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 5df62fd4dd..d58742d32a 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 @@ -7,6 +7,7 @@ import android.content.SharedPreferences; import android.os.BatteryManager; import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import android.util.Log; import com.google.android.gms.common.ConnectionResult; @@ -26,16 +27,18 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.TempBasal; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; import info.nightscout.androidaps.plugins.Wear.ActionStringHandler; import info.nightscout.androidaps.plugins.Wear.WearPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -65,7 +68,6 @@ public class WatchUpdaterService extends WearableListenerService implements public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest"; - boolean wear_integration = false; SharedPreferences mPrefs; private static boolean lastLoopStatus; @@ -92,7 +94,9 @@ public class WatchUpdaterService extends WearableListenerService implements } public void googleApiConnect() { - if(googleApiClient != null && (googleApiClient.isConnected() || googleApiClient.isConnecting())) { googleApiClient.disconnect(); } + if (googleApiClient != null && (googleApiClient.isConnected() || googleApiClient.isConnecting())) { + googleApiClient.disconnect(); + } googleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) @@ -128,15 +132,14 @@ public class WatchUpdaterService extends WearableListenerService implements sendStatus(); } else if (ACTION_SEND_BASALS.equals(action)) { sendBasals(); - } else if (ACTION_SEND_BOLUSPROGRESS.equals(action)){ - sendBolusProgress(intent.getIntExtra("progresspercent", 0), intent.hasExtra("progressstatus")?intent.getStringExtra("progressstatus"):""); - } else if (ACTION_SEND_ACTIONCONFIRMATIONREQUEST.equals(action)){ + } else if (ACTION_SEND_BOLUSPROGRESS.equals(action)) { + sendBolusProgress(intent.getIntExtra("progresspercent", 0), intent.hasExtra("progressstatus") ? intent.getStringExtra("progressstatus") : ""); + } else if (ACTION_SEND_ACTIONCONFIRMATIONREQUEST.equals(action)) { String title = intent.getStringExtra("title"); String message = intent.getStringExtra("message"); String actionstring = intent.getStringExtra("actionstring"); sendActionConfirmationRequest(title, message, actionstring); - } - else { + } else { sendData(); } } else { @@ -185,15 +188,17 @@ public class WatchUpdaterService extends WearableListenerService implements private void sendData() { - BgReading lastBG = GlucoseStatus.lastBg(); + BgReading lastBG = DatabaseHelper.lastBg(); if (lastBG != null) { GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); } + if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { + googleApiConnect(); + } if (wear_integration) { final DataMap dataMap = dataMapSingleBG(lastBG, glucoseStatus); - if(dataMap==null) { + if (dataMap == null) { ToastUtils.showToastInUiThread(this, getString(R.string.noprofile)); return; } @@ -204,24 +209,24 @@ public class WatchUpdaterService extends WearableListenerService implements } private DataMap dataMapSingleBG(BgReading lastBG, GlucoseStatus glucoseStatus) { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if(profile == null) return null; + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) return null; Double lowLine = SafeParse.stringToDouble(mPrefs.getString("low_mark", "0")); Double highLine = SafeParse.stringToDouble(mPrefs.getString("high_mark", "0")); //convert to mg/dl - if (! profile.getUnits().equals(Constants.MGDL)){ + if (!profile.getUnits().equals(Constants.MGDL)) { lowLine *= Constants.MMOLL_TO_MGDL; highLine *= Constants.MMOLL_TO_MGDL; } - if (lowLine < 1){ + if (lowLine < 1) { lowLine = OverviewPlugin.bgTargetLow; } - if(highLine < 1){ + if (highLine < 1) { highLine = OverviewPlugin.bgTargetHigh; } @@ -235,9 +240,9 @@ public class WatchUpdaterService extends WearableListenerService implements int battery = getBatteryLevel(getApplicationContext()); dataMap.putString("sgvString", lastBG.valueToUnitsToString(profile.getUnits())); - dataMap.putDouble("timestamp", lastBG.getTimeIndex()); - if(glucoseStatus == null) { - dataMap.putString("slopeArrow", "" ); + dataMap.putDouble("timestamp", lastBG.date); + if (glucoseStatus == null) { + dataMap.putString("slopeArrow", ""); dataMap.putString("delta", ""); dataMap.putString("avgDelta", ""); } else { @@ -247,7 +252,7 @@ public class WatchUpdaterService extends WearableListenerService implements } dataMap.putString("battery", "" + battery); dataMap.putLong("sgvLevel", sgvLevel); - dataMap.putInt("batteryLevel", (battery>=30)?1:0); + dataMap.putInt("batteryLevel", (battery >= 30) ? 1 : 0); dataMap.putDouble("sgvDouble", lastBG.value); dataMap.putDouble("high", highLine); dataMap.putDouble("low", lowLine); @@ -256,33 +261,32 @@ public class WatchUpdaterService extends WearableListenerService implements private String deltastring(double deltaMGDL, double deltaMMOL, String units) { String deltastring = ""; - if (deltaMGDL >=0){ + if (deltaMGDL >= 0) { deltastring += "+"; - } else{ + } else { deltastring += "-"; } - if (units.equals(Constants.MGDL)){ + if (units.equals(Constants.MGDL)) { deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMGDL)); - } - else { + } else { deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMMOL)); } return deltastring; } private String slopeArrow(double delta) { - if (delta <= (-3.5*5)) { + if (delta <= (-3.5 * 5)) { return "\u21ca"; - } else if (delta <= (-2*5)) { + } else if (delta <= (-2 * 5)) { return "\u2193"; - } else if (delta <= (-1*5)) { + } else if (delta <= (-1 * 5)) { return "\u2198"; - } else if (delta <= (1*5)) { + } else if (delta <= (1 * 5)) { return "\u2192"; - } else if (delta <= (2*5)) { + } else if (delta <= (2 * 5)) { return "\u2197"; - } else if (delta <= (3.5*5)) { + } else if (delta <= (3.5 * 5)) { return "\u2191"; } else { return "\u21c8"; @@ -291,25 +295,27 @@ public class WatchUpdaterService extends WearableListenerService implements private void resendData() { - if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); } - long startTime = System.currentTimeMillis() - (long)(60000 * 60 * 5.5); - BgReading last_bg = GlucoseStatus.lastBg(); + if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { + googleApiConnect(); + } + long startTime = System.currentTimeMillis() - (long) (60000 * 60 * 5.5); + BgReading last_bg = DatabaseHelper.lastBg(); if (last_bg == null) return; - List graph_bgs = MainApp.getDbHelper().getBgreadingsDataFromTime(startTime, true); + List graph_bgs = MainApp.getDbHelper().getBgreadingsDataFromTime(startTime, true); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); if (!graph_bgs.isEmpty()) { DataMap entries = dataMapSingleBG(last_bg, glucoseStatus); - if(entries==null) { + if (entries == null) { ToastUtils.showToastInUiThread(this, getString(R.string.noprofile)); return; } final ArrayList dataMaps = new ArrayList<>(graph_bgs.size()); for (BgReading bg : graph_bgs) { DataMap dataMap = dataMapSingleBG(bg, glucoseStatus); - if(dataMap != null) { + if (dataMap != null) { dataMaps.add(dataMap); } } @@ -321,47 +327,48 @@ public class WatchUpdaterService extends WearableListenerService implements } private void sendBasals() { - if(googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); } + if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { + googleApiConnect(); + } long now = System.currentTimeMillis(); - long startTimeWindow = now - (long)(60000 * 60 * 5.5); - + long startTimeWindow = now - (long) (60000 * 60 * 5.5); ArrayList basals = new ArrayList<>(); ArrayList temps = new ArrayList<>(); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); - if(profile==null) { + if (profile == null) { return; } long beginBasalSegmentTime = startTimeWindow; long runningTime = startTimeWindow; - double beginBasalValue = profile.getBasal(NSProfile.secondsFromMidnight(new Date(beginBasalSegmentTime))); + double beginBasalValue = profile.getBasal(beginBasalSegmentTime); double endBasalValue = beginBasalValue; - TempBasal tb1 = MainApp.getConfigBuilder().getTempBasal(new Date(runningTime)); - TempBasal tb2 = MainApp.getConfigBuilder().getTempBasal(new Date(runningTime)); + TemporaryBasal tb1 = MainApp.getConfigBuilder().getTempBasalFromHistory(runningTime); + TemporaryBasal tb2 = MainApp.getConfigBuilder().getTempBasalFromHistory(runningTime); double tb_before = beginBasalValue; double tb_amount = beginBasalValue; long tb_start = runningTime; - if(tb1 != null){ + if (tb1 != null) { tb_before = beginBasalValue; - tb_amount = tb1.tempBasalConvertedToAbsolute(new Date(runningTime)); + tb_amount = tb1.tempBasalConvertedToAbsolute(runningTime); tb_start = runningTime; } - for(;runningTime= 0) ? "+" : "") + DecimalFormatter.to2Decimal(bgi); + + return status; + } + @Override public void onDestroy() { if (googleApiClient != null && googleApiClient.isConnected()) { @@ -567,7 +589,7 @@ public class WatchUpdaterService extends WearableListenerService implements public void onConnectionFailed(ConnectionResult connectionResult) { } - public static boolean shouldReportLoopStatus(boolean enabled){ + public static boolean shouldReportLoopStatus(boolean enabled) { return (lastLoopStatus != enabled); } @@ -575,9 +597,9 @@ public class WatchUpdaterService extends WearableListenerService implements 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) { + if (level == -1 || scale == -1) { return 50; } - return (int)(((float)level / (float)scale) * 100.0f); + return (int) (((float) level / (float) scale) * 100.0f); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslineFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslineFragment.java new file mode 100644 index 0000000000..ba2cbc0783 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslineFragment.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.XDripStatusline; + +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import info.nightscout.androidaps.R; + +/** + * Created by adrian on 17/11/16. + */ + +public class StatuslineFragment extends Fragment { + + private static StatuslinePlugin statuslinePlugin; + + public static StatuslinePlugin getPlugin(Context ctx) { + + if (statuslinePlugin == null) { + statuslinePlugin = new StatuslinePlugin(ctx); + } + + return statuslinePlugin; + } + +} 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 new file mode 100644 index 0000000000..35b82d185c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java @@ -0,0 +1,247 @@ +package info.nightscout.androidaps.plugins.XDripStatusline; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; + +import com.squareup.otto.Subscribe; + +import java.util.Date; + +import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventExtendedBolusChange; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.events.EventPreferenceChange; +import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.events.EventTreatmentChange; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.plugins.Loop.LoopPlugin; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.utils.DecimalFormatter; + +/** + * Created by adrian on 17/11/16. + */ + +public class StatuslinePlugin implements PluginBase { + + //broadcast related constants + public static final String EXTRA_STATUSLINE = "com.eveningoutpost.dexdrip.Extras.Statusline"; + public static final String ACTION_NEW_EXTERNAL_STATUSLINE = "com.eveningoutpost.dexdrip.ExternalStatusline"; + public static final String RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_EXTERNAL_STATUSLINE"; + + + static boolean fragmentEnabled = false; + private static boolean lastLoopStatus; + + private final Context ctx; + SharedPreferences mPrefs; + + StatuslinePlugin(Context ctx) { + this.ctx = ctx; + this.mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx); + } + + @Override + public int getType() { + return PluginBase.GENERAL; + } + + @Override + public String getFragmentClass() { + return StatuslineFragment.class.getName(); + } + + @Override + public String getName() { + return ctx.getString(R.string.xdripstatus); + } + + @Override + public String getNameShort() { + String name = MainApp.sResources.getString(R.string.xdripstatus_shortname); + if (!name.trim().isEmpty()) { + //only if translation exists + return name; + } + // use long name as fallback + return getName(); + } + + @Override + public boolean isEnabled(int type) { + return type == GENERAL && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return false; + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return false; + } + + @Override + public boolean showInList(int type) { + return !Config.NSCLIENT; + } + + @Override + public void setFragmentEnabled(int type, boolean fragmentEnabled) { + if (type == GENERAL) { + this.fragmentEnabled = fragmentEnabled; + + if (fragmentEnabled) { + try { + MainApp.bus().register(this); + } catch (Exception e) { + } + sendStatus(); + } else { + try { + MainApp.bus().unregister(this); + } catch (Exception e) { + } + sendStatus(); + } + } + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + // do nothing, no gui + } + + + private void sendStatus() { + + + String status = ""; // sent once on disable + + if (fragmentEnabled) { + status = buildStatusString(); + } + + + //sendData + final Bundle bundle = new Bundle(); + bundle.putString(EXTRA_STATUSLINE, status); + Intent intent = new Intent(ACTION_NEW_EXTERNAL_STATUSLINE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + ctx.sendBroadcast(intent, null); + } + + @NonNull + private String buildStatusString() { + String status = ""; + boolean shortString = true; // make setting? + + LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + + if (activeloop != null && !activeloop.isEnabled(PluginBase.LOOP)) { + status += ctx.getString(R.string.disabledloop) + "\n"; + lastLoopStatus = false; + } else if (activeloop != null && activeloop.isEnabled(PluginBase.LOOP)) { + lastLoopStatus = true; + } + + //Temp basal + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + + if (treatmentsInterface.isTempBasalInProgress()) { + TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(new Date().getTime()); + if (shortString) { + status += activeTemp.toStringShort(); + } else { + status += activeTemp.toStringMedium(); + } + } + + //IOB + treatmentsInterface.updateTotalIOBTreatments(); + IobTotal bolusIob = treatmentsInterface.getLastCalculationTreatments().round(); + treatmentsInterface.updateTotalIOBTempBasals(); + IobTotal basalIob = treatmentsInterface.getLastCalculationTempBasals().round(); + status += (shortString ? "" : (ctx.getString(R.string.treatments_iob_label_string) + " ")) + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob); + + + if (mPrefs.getBoolean("xdripstatus_detailediob", true)) { + status += "(" + + DecimalFormatter.to2Decimal(bolusIob.iob) + "|" + + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")"; + } + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (!mPrefs.getBoolean("xdripstatus_showbgi", false)) { + return status; + } + + double bgi = -(bolusIob.activity + basalIob.activity) * 5 * profile.getIsf(); + + status += " " + ((bgi >= 0) ? "+" : "") + DecimalFormatter.to2Decimal(bgi); + + return status; + } + + + @Subscribe + public void onStatusEvent(final EventPreferenceChange ev) { + // status may be formated differently + sendStatus(); + } + + @Subscribe + public void onStatusEvent(final EventTreatmentChange ev) { + sendStatus(); + } + + @Subscribe + public void onStatusEvent(final EventTempBasalChange ev) { + sendStatus(); + } + + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + sendStatus(); + } + + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + sendStatus(); + } + + @Subscribe + public void onStatusEvent(final EventRefreshGui ev) { + + //Filter events where loop is (de)activated + + LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); + if (activeloop == null) return; + + if ((lastLoopStatus != activeloop.isEnabled(PluginBase.LOOP))) { + sendStatus(); + } + } + + + public static boolean isEnabled() { + return fragmentEnabled; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/persistentnotification/PersistentNotificationFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/persistentnotification/PersistentNotificationFragment.java deleted file mode 100644 index 6834124167..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/persistentnotification/PersistentNotificationFragment.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.persistentnotification; - -import android.support.v4.app.Fragment; - -import info.nightscout.androidaps.interfaces.FragmentBase; - -/** - * Created by adrian on 23/12/16. - */ - -public class PersistentNotificationFragment extends Fragment implements FragmentBase { - - -} 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 5c889b661f..6b48804926 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java @@ -21,7 +21,7 @@ import java.util.Date; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; public class KeepAliveReceiver extends BroadcastReceiver { private static Logger log = LoggerFactory.getLogger(KeepAliveReceiver.class); @@ -34,15 +34,15 @@ public class KeepAliveReceiver extends BroadcastReceiver { final PumpInterface pump = MainApp.getConfigBuilder(); - final NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (pump != null && profile != null && profile.getBasal(NSProfile.secondsFromMidnight()) != null) { + final Profile profile = MainApp.getConfigBuilder().getProfile(); + if (pump != null && profile != null && profile.getBasal() != null) { boolean isBasalOutdated = false; boolean isStatusOutdated = false; Date lastConnection = pump.lastDataTime(); if (lastConnection.getTime() + 30 * 60 * 1000L < new Date().getTime()) isStatusOutdated = true; - if (Math.abs(profile.getBasal(NSProfile.secondsFromMidnight()) - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep) + if (Math.abs(profile.getBasal() - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep) isBasalOutdated = true; SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java b/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java index 5c1ef3b25f..80424a04f7 100644 --- a/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java +++ b/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabLayout.java @@ -29,6 +29,8 @@ 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. @@ -95,6 +97,7 @@ public class SlidingTabLayout extends HorizontalScrollView { mTabStrip = new SlidingTabStrip(context); addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + setBackgroundColor(context.getResources().getColor(R.color.tabBgColor)); } /** diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabStrip.java b/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabStrip.java index bb462e0782..587850f678 100644 --- a/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabStrip.java +++ b/app/src/main/java/info/nightscout/androidaps/tabs/SlidingTabStrip.java @@ -23,12 +23,14 @@ import android.util.TypedValue; import android.view.View; import android.widget.LinearLayout; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + class SlidingTabStrip extends LinearLayout { private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0; private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3; - private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; private final int mBottomBorderThickness; private final Paint mBottomBorderPaint; @@ -60,7 +62,7 @@ class SlidingTabStrip extends LinearLayout { DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); mDefaultTabColorizer = new SimpleTabColorizer(); - mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); + mDefaultTabColorizer.setIndicatorColors(MainApp.sResources.getColor(R.color.tabBgColorSelected)); mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); mBottomBorderPaint = new Paint(); diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/TabFragment.java b/app/src/main/java/info/nightscout/androidaps/tabs/TabFragment.java deleted file mode 100644 index 54b6ce217f..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/tabs/TabFragment.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.tabs; - -import android.support.v4.app.Fragment; - -/** - * Created by mike on 30.05.2016. - */ -public abstract class TabFragment extends Fragment { - -} diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java index cedae6e9d7..b6eaf73ce4 100644 --- a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java @@ -7,6 +7,7 @@ import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; +import android.view.ViewGroup; import java.util.ArrayList; @@ -17,15 +18,12 @@ import info.nightscout.androidaps.interfaces.PluginBase; */ public class TabPageAdapter extends FragmentStatePagerAdapter { - ArrayList fragmentList = new ArrayList<>(); ArrayList visibleFragmentList = new ArrayList<>(); - FragmentManager fm; Context context; public TabPageAdapter(FragmentManager fm, Context context) { super(fm); - this.fm = fm; this.context = context; } @@ -36,6 +34,15 @@ public class TabPageAdapter extends FragmentStatePagerAdapter { return Fragment.instantiate(context, visibleFragmentList.get(position).getFragmentClass()); } + @Override + public void finishUpdate(ViewGroup container) { + try{ + super.finishUpdate(container); + } catch (NullPointerException nullPointerException){ + System.out.println("Catch the NullPointerException in FragmentStatePagerAdapter.finishUpdate"); + } + } + @Override public CharSequence getPageTitle(int position) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); @@ -52,10 +59,11 @@ public class TabPageAdapter extends FragmentStatePagerAdapter { } public void registerNewFragment(PluginBase plugin) { - fragmentList.add(plugin); if (plugin.isVisibleInTabs(plugin.getType())) { visibleFragmentList.add(plugin); notifyDataSetChanged(); } } + + } diff --git a/app/src/main/java/info/nightscout/utils/BolusWizard.java b/app/src/main/java/info/nightscout/utils/BolusWizard.java index 848263ebc5..ea34c7c8f9 100644 --- a/app/src/main/java/info/nightscout/utils/BolusWizard.java +++ b/app/src/main/java/info/nightscout/utils/BolusWizard.java @@ -1,16 +1,12 @@ package info.nightscout.utils; -import org.json.JSONObject; - import java.util.Date; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.data.GlucoseStatus; -import info.nightscout.androidaps.interfaces.TempBasalsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; /** * Created by mike on 11.10.2016. @@ -18,7 +14,7 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; public class BolusWizard { // Inputs - JSONObject specificProfile = null; + Profile specificProfile = null; public Integer carbs = 0; Double bg = 0d; Double correction; @@ -53,7 +49,7 @@ public class BolusWizard { public Double calculatedTotalInsulin = 0d; public Double carbsEquivalent = 0d; - public Double doCalc(JSONObject specificProfile, Integer carbs, Double cob, Double bg, Double correction, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { + public Double doCalc(Profile specificProfile, Integer carbs, Double cob, Double bg, Double correction, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { this.specificProfile = specificProfile; this.carbs = carbs; this.bg = bg; @@ -61,12 +57,11 @@ public class BolusWizard { this.superBolus = superBolus; this.trend = trend; - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); // Insulin from BG - sens = profile.getIsf(specificProfile, NSProfile.secondsFromMidnight()); - targetBGLow = profile.getTargetLow(specificProfile, NSProfile.secondsFromMidnight()); - targetBGHigh = profile.getTargetHigh(specificProfile, NSProfile.secondsFromMidnight()); + sens = specificProfile.getIsf(); + targetBGLow = specificProfile.getTargetLow(); + targetBGHigh = specificProfile.getTargetHigh(); if (bg <= targetBGLow) { bgDiff = bg - targetBGLow; } else { @@ -76,26 +71,22 @@ public class BolusWizard { // Insulin from 15 min trend glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if (glucoseStatus != null) { - insulinFromTrend = (NSProfile.fromMgdlToUnits(glucoseStatus.short_avgdelta, profile.getUnits()) * 3) / sens; + if (glucoseStatus != null && trend) { + insulinFromTrend = (Profile.fromMgdlToUnits(glucoseStatus.short_avgdelta, specificProfile.getUnits()) * 3) / sens; } // Insuling from carbs - ic = profile.getIc(specificProfile, NSProfile.secondsFromMidnight()); + ic = specificProfile.getIc(); insulinFromCarbs = carbs / ic; - insulinFromCOB = -cob / ic; + insulinFromCOB = cob / ic; // Insulin from IOB // IOB calculation - TreatmentsInterface treatments = ConfigBuilderPlugin.getActiveTreatments(); - treatments.updateTotalIOB(); - IobTotal bolusIob = treatments.getLastCalculation(); - TempBasalsInterface tempBasals = ConfigBuilderPlugin.getActiveTempBasals(); - IobTotal basalIob = new IobTotal(new Date().getTime()); - if (tempBasals != null) { - tempBasals.updateTotalIOB(); - basalIob = tempBasals.getLastCalculation().round(); - } + TreatmentsInterface treatments = MainApp.getConfigBuilder(); + treatments.updateTotalIOBTreatments(); + IobTotal bolusIob = treatments.getLastCalculationTreatments().round(); + treatments.updateTotalIOBTempBasals(); + IobTotal basalIob = treatments.getLastCalculationTempBasals().round(); insulingFromBolusIOB = includeBolusIOB ? -bolusIob.iob : 0d; insulingFromBasalsIOB = includeBasalIOB ? -basalIob.basaliob : 0d; @@ -105,10 +96,10 @@ public class BolusWizard { // Insulin from superbolus for 2h. Get basal rate now and after 1h if (superBolus) { - insulinFromSuperBolus = profile.getBasal(NSProfile.secondsFromMidnight()); + insulinFromSuperBolus = specificProfile.getBasal(); long timeAfter1h = new Date().getTime(); timeAfter1h += 60L * 60 * 1000; - insulinFromSuperBolus += profile.getBasal(NSProfile.secondsFromMidnight(new Date(timeAfter1h))); + insulinFromSuperBolus += specificProfile.getBasal(Profile.secondsFromMidnight(new Date(timeAfter1h))); } // Total diff --git a/app/src/main/java/info/nightscout/utils/ImportExportPrefs.java b/app/src/main/java/info/nightscout/utils/ImportExportPrefs.java index 567e5e412b..1e501fbdf0 100644 --- a/app/src/main/java/info/nightscout/utils/ImportExportPrefs.java +++ b/app/src/main/java/info/nightscout/utils/ImportExportPrefs.java @@ -3,7 +3,6 @@ package info.nightscout.utils; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; -import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -11,6 +10,9 @@ import android.os.Environment; import android.preference.PreferenceManager; import android.support.v4.app.ActivityCompat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -22,12 +24,14 @@ import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventAppExit; /** * Created by mike on 03.07.2016. */ public class ImportExportPrefs { + private static Logger log = LoggerFactory.getLogger(ImportExportPrefs.class); static File path = new File(Environment.getExternalStorageDirectory().toString()); static final File file = new File(path, MainApp.sResources.getString(R.string.app_name) + "Preferences"); @@ -52,7 +56,7 @@ public class ImportExportPrefs { } } - public static void exportSharedPreferences(final Context c) { + public static void exportSharedPreferences(final Activity c) { new AlertDialog.Builder(c) .setMessage(MainApp.sResources.getString(R.string.export_to) + " " + file + " ?") @@ -82,7 +86,7 @@ public class ImportExportPrefs { .show(); } - public static void importSharedPreferences(final Context c) { + public static void importSharedPreferences(final Activity c) { new AlertDialog.Builder(c) .setMessage(MainApp.sResources.getString(R.string.import_from) + " " + file + " ?") .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @@ -109,7 +113,18 @@ public class ImportExportPrefs { } reader.close(); editor.commit(); - ToastUtils.showToastInUiThread(c, MainApp.sResources.getString(R.string.setting_imported)); + OKDialog.show(c, MainApp.sResources.getString(R.string.setting_imported), MainApp.sResources.getString(R.string.restartingapp), new Runnable() { + @Override + public void run() { + log.debug("Exiting"); + MainApp.instance().stopKeepAliveService(); + MainApp.bus().post(new EventAppExit()); + MainApp.closeDbHelper(); + c.finish(); + System.runFinalization(); + System.exit(0); + } + }); } catch (FileNotFoundException e) { ToastUtils.showToastInUiThread(c, MainApp.sResources.getString(R.string.filenotfound) + " " + file); e.printStackTrace(); diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java new file mode 100644 index 0000000000..86d15dc9b7 --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -0,0 +1,408 @@ +package info.nightscout.utils; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Date; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.plugins.Loop.APSResult; +import info.nightscout.androidaps.plugins.Loop.DeviceStatus; +import info.nightscout.androidaps.plugins.Loop.LoopPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.data.DbLogger; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; +import info.nightscout.androidaps.plugins.OpenAPSMA.DetermineBasalResultMA; + +/** + * Created by mike on 26.05.2017. + */ + +public class NSUpload { + private static Logger log = LoggerFactory.getLogger(NSUpload.class); + + public static void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.TEMPBASAL); + data.put("duration", temporaryBasal.durationInMinutes); + data.put("absolute", temporaryBasal.absoluteRate); + if (temporaryBasal.pumpId != 0) + data.put("pumpId", temporaryBasal.pumpId); + data.put("created_at", DateUtil.toISOString(temporaryBasal.date)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + temporaryBasal.absoluteRate + "u/h " + temporaryBasal.durationInMinutes + " min"); // ECOR + if (originalExtendedAmount != null) + data.put("originalExtendedAmount", originalExtendedAmount); // for back synchronization + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadTempBasalStartPercent(TemporaryBasal temporaryBasal) { + try { + SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); + boolean useAbsolute = SP.getBoolean("ns_sync_use_absolute", false); + if (useAbsolute) { + TemporaryBasal t = temporaryBasal.clone(); + t.isAbsolute = true; + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile != null) { + t.absoluteRate = profile.getBasal(temporaryBasal.date) * temporaryBasal.percentRate / 100d; + uploadTempBasalStartAbsolute(t, null); + } + } else { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.TEMPBASAL); + data.put("duration", temporaryBasal.durationInMinutes); + data.put("percent", temporaryBasal.percentRate - 100); + if (temporaryBasal.pumpId != 0) + data.put("pumpId", temporaryBasal.pumpId); + data.put("created_at", DateUtil.toISOString(temporaryBasal.date)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalstartnote) + " " + temporaryBasal.percentRate + "% " + temporaryBasal.durationInMinutes + " min"); // ECOR + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadTempBasalEnd(long time, boolean isFakedTempBasal, long pumpId) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.TEMPBASAL); + data.put("created_at", DateUtil.toISOString(time)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + data.put("notes", MainApp.sResources.getString(R.string.androidaps_tempbasalendnote)); // ECOR + if (isFakedTempBasal) + data.put("isFakedTempBasal", isFakedTempBasal); + if (pumpId != 0) + data.put("pumpId", pumpId); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadExtendedBolus(ExtendedBolus extendedBolus) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.COMBOBOLUS); + data.put("duration", extendedBolus.durationInMinutes); + data.put("splitNow", 0); + data.put("splitExt", 100); + data.put("enteredinsulin", extendedBolus.insulin); + data.put("relative", extendedBolus.insulin); + if (extendedBolus.pumpId != 0) + data.put("pumpId", extendedBolus.pumpId); + data.put("created_at", DateUtil.toISOString(extendedBolus.date)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadExtendedBolusEnd(long time, long pumpId) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.COMBOBOLUS); + data.put("duration", 0); + data.put("splitNow", 0); + data.put("splitExt", 100); + data.put("enteredinsulin", 0); + data.put("relative", 0); + data.put("created_at", DateUtil.toISOString(time)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + if (pumpId != 0) + data.put("pumpId", pumpId); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadDeviceStatus() { + DeviceStatus deviceStatus = new DeviceStatus(); + try { + LoopPlugin.LastRun lastRun = LoopPlugin.lastRun; + if (lastRun != null && lastRun.lastAPSRun.getTime() > new Date().getTime() - 300 * 1000L) { + // do not send if result is older than 1 min + APSResult apsResult = lastRun.request; + apsResult.json().put("timestamp", DateUtil.toISOString(lastRun.lastAPSRun)); + deviceStatus.suggested = apsResult.json(); + + if (lastRun.request instanceof DetermineBasalResultMA) { + DetermineBasalResultMA result = (DetermineBasalResultMA) lastRun.request; + deviceStatus.iob = result.iob.json(); + deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun)); + } + + if (lastRun.request instanceof DetermineBasalResultAMA) { + DetermineBasalResultAMA result = (DetermineBasalResultAMA) lastRun.request; + deviceStatus.iob = result.iob.json(); + deviceStatus.iob.put("time", DateUtil.toISOString(lastRun.lastAPSRun)); + } + + if (lastRun.setByPump != null && lastRun.setByPump.enacted) { // enacted + deviceStatus.enacted = lastRun.request.json(); + deviceStatus.enacted.put("rate", lastRun.setByPump.json().get("rate")); + deviceStatus.enacted.put("duration", lastRun.setByPump.json().get("duration")); + deviceStatus.enacted.put("recieved", true); + JSONObject requested = new JSONObject(); + requested.put("duration", lastRun.request.duration); + requested.put("rate", lastRun.request.rate); + requested.put("temp", "absolute"); + deviceStatus.enacted.put("requested", requested); + } + } else { + log.debug("OpenAPS data too old to upload"); + } + deviceStatus.device = "openaps://" + MainApp.getConfigBuilder().deviceID(); + JSONObject pumpstatus = MainApp.getConfigBuilder().getJSONStatus(); + if (pumpstatus != null) { + deviceStatus.pump = pumpstatus; + } + + int batteryLevel = BatteryLevel.getBatteryLevel(); + deviceStatus.uploaderBattery = batteryLevel; + + deviceStatus.created_at = DateUtil.toISOString(new Date()); + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "devicestatus"); + bundle.putString("data", deviceStatus.mongoRecord().toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, deviceStatus.mongoRecord().toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadBolusWizardRecord(DetailedBolusInfo detailedBolusInfo) { + JSONObject data = new JSONObject(); + try { + data.put("eventType", detailedBolusInfo.eventType); + if (detailedBolusInfo.insulin != 0d) data.put("insulin", detailedBolusInfo.insulin); + if (detailedBolusInfo.carbs != 0d) data.put("carbs", (int) detailedBolusInfo.carbs); + data.put("created_at", DateUtil.toISOString(detailedBolusInfo.date)); + data.put("date", detailedBolusInfo.date); + if (detailedBolusInfo.pumpId != 0) + data.put("pumpId", detailedBolusInfo.pumpId); + if (detailedBolusInfo.glucose != 0d) + data.put("glucose", detailedBolusInfo.glucose); + if (!detailedBolusInfo.glucoseType.equals("")) + data.put("glucoseType", detailedBolusInfo.glucoseType); + if (detailedBolusInfo.boluscalc != null) + data.put("boluscalc", detailedBolusInfo.boluscalc); + if (detailedBolusInfo.carbTime != 0) + data.put("preBolus", detailedBolusInfo.carbTime); + } catch (JSONException e) { + e.printStackTrace(); + } + uploadCareportalEntryToNS(data); + } + + public static void uploadProfileSwitch(ProfileSwitch profileSwitch) { + try { + JSONObject data = new JSONObject(); + data.put("eventType", CareportalEvent.PROFILESWITCH); + data.put("duration", profileSwitch.durationInMinutes); + data.put("profile", profileSwitch.profileName); + data.put("profileJson", profileSwitch.profileJson); + data.put("profilePlugin", profileSwitch.profilePlugin); + if (profileSwitch.isCPP) { + data.put("CircadianPercentageProfile", true); + data.put("timeshift", profileSwitch.timeshift); + data.put("percentage", profileSwitch.percentage); + } + data.put("created_at", DateUtil.toISOString(profileSwitch.date)); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + uploadCareportalEntryToNS(data); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadCareportalEntryToNS(JSONObject data) { + try { + if (data.has("preBolus") && data.has("carbs")) { + JSONObject prebolus = new JSONObject(); + prebolus.put("carbs", data.get("carbs")); + data.remove("carbs"); + prebolus.put("eventType", data.get("eventType")); + if (data.has("enteredBy")) prebolus.put("enteredBy", data.get("enteredBy")); + if (data.has("notes")) prebolus.put("notes", data.get("notes")); + long mills = DateUtil.fromISODateString(data.getString("created_at")).getTime(); + Date preBolusDate = new Date(mills + data.getInt("preBolus") * 60000L); + prebolus.put("created_at", DateUtil.toISOString(preBolusDate)); + uploadCareportalEntryToNS(prebolus); + } + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static void removeCareportalEntryFromNS(String _id) { + try { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbRemove"); + bundle.putString("collection", "treatments"); + bundle.putString("_id", _id); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbRemove(intent, _id); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static void uploadOpenAPSOffline(double durationInMinutes) { + try { + Context context = MainApp.instance().getApplicationContext(); + JSONObject data = new JSONObject(); + data.put("eventType", "OpenAPS Offline"); + data.put("duration", durationInMinutes); + data.put("created_at", DateUtil.toISOString(new Date())); + data.put("enteredBy", MainApp.instance().getString(R.string.app_name)); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public static void uploadError(String error) { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + JSONObject data = new JSONObject(); + try { + data.put("eventType", "Announcement"); + data.put("created_at", DateUtil.toISOString(new Date())); + data.put("notes", error); + data.put("isAnnouncement", true); + } catch (JSONException e) { + e.printStackTrace(); + } + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } + + public static void uploadAppStart() { + if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) { + Context context = MainApp.instance().getApplicationContext(); + Bundle bundle = new Bundle(); + bundle.putString("action", "dbAdd"); + bundle.putString("collection", "treatments"); + JSONObject data = new JSONObject(); + try { + data.put("eventType", "Note"); + data.put("created_at", DateUtil.toISOString(new Date())); + data.put("notes", MainApp.sResources.getString(R.string.androidaps_start)); + } catch (JSONException e) { + e.printStackTrace(); + } + bundle.putString("data", data.toString()); + Intent intent = new Intent(Intents.ACTION_DATABASE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + DbLogger.dbAdd(intent, data.toString()); + } + } +} diff --git a/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java b/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java index 9bb7062f04..c9949252af 100644 --- a/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java +++ b/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java @@ -116,6 +116,10 @@ public class PlusMinusEditText implements View.OnKeyListener, return value; } + public String getText() { + return editText.getText().toString(); + } + public void setStep(Double step) { this.step = step; } diff --git a/app/src/main/java/info/nightscout/utils/SP.java b/app/src/main/java/info/nightscout/utils/SP.java index 9bed316195..4733c42d04 100644 --- a/app/src/main/java/info/nightscout/utils/SP.java +++ b/app/src/main/java/info/nightscout/utils/SP.java @@ -98,6 +98,12 @@ public class SP { editor.apply(); } + static public void putString(String key, String value) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(key, value); + editor.apply(); + } + static public void removeString(int resourceID) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.remove(MainApp.sResources.getString(resourceID)); diff --git a/app/src/main/java/info/nightscout/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/utils/TimeListEdit.java index 1c4f5d4edd..ce1f604060 100644 --- a/app/src/main/java/info/nightscout/utils/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/utils/TimeListEdit.java @@ -229,8 +229,7 @@ public class TimeListEdit { } ArrayAdapter adapter = new ArrayAdapter(context, - android.R.layout.simple_spinner_item, timeList); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + R.layout.spinner_centered, timeList); spinner.setAdapter(adapter); spinner.setSelection(posInList, false); } diff --git a/app/src/main/java/info/nightscout/utils/XdripCalibrations.java b/app/src/main/java/info/nightscout/utils/XdripCalibrations.java index 53c3bf45ec..2bc60d3693 100644 --- a/app/src/main/java/info/nightscout/utils/XdripCalibrations.java +++ b/app/src/main/java/info/nightscout/utils/XdripCalibrations.java @@ -17,7 +17,7 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; /** * Created by mike on 10.02.2017. @@ -44,7 +44,7 @@ public class XdripCalibrations { } public static boolean sendIntent(Double bg) { - final NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + final Profile profile = MainApp.getConfigBuilder().getProfile(); Context context = MainApp.instance().getApplicationContext(); Bundle bundle = new Bundle(); diff --git a/app/src/main/res/drawable/bread.png b/app/src/main/res/drawable/bread.png deleted file mode 100644 index aa18f4f1d9..0000000000 Binary files a/app/src/main/res/drawable/bread.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_more_vert_black_24dp.xml b/app/src/main/res/drawable/ic_more_vert_black_24dp.xml new file mode 100644 index 0000000000..5176d8a4b1 --- /dev/null +++ b/app/src/main/res/drawable/ic_more_vert_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/icon_bolus.png b/app/src/main/res/drawable/icon_bolus.png new file mode 100644 index 0000000000..e0d0204a22 Binary files /dev/null and b/app/src/main/res/drawable/icon_bolus.png differ diff --git a/app/src/main/res/drawable/icon_calculator.png b/app/src/main/res/drawable/icon_calculator.png new file mode 100644 index 0000000000..b327e69327 Binary files /dev/null and b/app/src/main/res/drawable/icon_calculator.png differ diff --git a/app/src/main/res/drawable/icon_calibration.png b/app/src/main/res/drawable/icon_calibration.png new file mode 100644 index 0000000000..8a6db6f8d1 Binary files /dev/null and b/app/src/main/res/drawable/icon_calibration.png differ diff --git a/app/src/main/res/drawable/icon_cancelbasal.png b/app/src/main/res/drawable/icon_cancelbasal.png new file mode 100644 index 0000000000..55a39b40e5 Binary files /dev/null and b/app/src/main/res/drawable/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable/icon_quickwizard.png b/app/src/main/res/drawable/icon_quickwizard.png new file mode 100644 index 0000000000..0487ee2ac1 Binary files /dev/null and b/app/src/main/res/drawable/icon_quickwizard.png differ diff --git a/app/src/main/res/drawable/initializingborder.xml b/app/src/main/res/drawable/initializingborder.xml deleted file mode 100644 index 7a46a6f1eb..0000000000 --- a/app/src/main/res/drawable/initializingborder.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/loopmodeborder.xml b/app/src/main/res/drawable/loopmodeborder.xml deleted file mode 100644 index 95f3c114e6..0000000000 --- a/app/src/main/res/drawable/loopmodeborder.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/loopmodedisabledborder.xml b/app/src/main/res/drawable/loopmodedisabledborder.xml deleted file mode 100644 index 2326b5ca14..0000000000 --- a/app/src/main/res/drawable/loopmodedisabledborder.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/loopmodesuspendedborder.xml b/app/src/main/res/drawable/loopmodesuspendedborder.xml deleted file mode 100644 index 9caa1789c1..0000000000 --- a/app/src/main/res/drawable/loopmodesuspendedborder.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/temptargetborder.xml b/app/src/main/res/drawable/temptargetborder.xml deleted file mode 100644 index 8dc85926e2..0000000000 --- a/app/src/main/res/drawable/temptargetborder.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/temptargetborderdisabled.xml b/app/src/main/res/drawable/temptargetborderdisabled.xml deleted file mode 100644 index 60a46f667e..0000000000 --- a/app/src/main/res/drawable/temptargetborderdisabled.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/actions_fragment.xml b/app/src/main/res/layout/actions_fragment.xml index 45c57e0107..5a0faa4099 100644 --- a/app/src/main/res/layout/actions_fragment.xml +++ b/app/src/main/res/layout/actions_fragment.xml @@ -8,77 +8,91 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - -