diff --git a/app/build.gradle b/app/build.gradle index 2b6af5681e..d6f321e942 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,8 +43,8 @@ android { applicationId "info.nightscout.androidaps" minSdkVersion 21 targetSdkVersion 23 - versionCode 1400 - version "1.46" + versionCode 1500 + version "1.51" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", generateGitBuild() } @@ -173,6 +173,9 @@ dependencies { 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') + compile ('com.google.android:flexbox:0.3.0') { + exclude group: 'com.android.support' + } compile('io.socket:socket.io-client:0.8.3') { // excluding org.json which is provided by Android exclude group: 'org.json', module: 'json' @@ -180,4 +183,4 @@ dependencies { compile 'com.google.code.gson:gson:2.7' compile 'com.google.guava:guava:20.0' -} \ No newline at end of file +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ab45d3d4f5..7d792556b7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,6 +17,7 @@ + @@ -41,14 +42,11 @@ android:name=".plugins.Overview.Dialogs.BolusProgressHelperActivity" android:theme="@style/Theme.AppCompat.Translucent" /> - - - - + + - @@ -58,17 +56,6 @@ android:enabled="true" android:exported="true"> - - - - - - - - - - - @@ -79,7 +66,6 @@ - @@ -116,11 +102,15 @@ android:name=".Services.DataService" android:exported="false" /> + + + - - \ No newline at end of file diff --git a/app/src/main/assets/logback.xml b/app/src/main/assets/logback.xml index 41ed7bdefe..c34ff08b80 100644 --- a/app/src/main/assets/logback.xml +++ b/app/src/main/assets/logback.xml @@ -6,7 +6,7 @@ - ${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}.%i.zip + ${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip 5MB @@ -15,7 +15,7 @@ 120 - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + %d{HH:mm:ss.SSS} [%thread] %-5level [%file:%line]: %msg%n @@ -24,7 +24,7 @@ %logger{0} - [%thread] %-5level %logger{36} - %msg%n + [%thread] %-5level [%file:%line]: %msg%n diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 7f094281f8..e6c06583c9 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -4,6 +4,8 @@ package info.nightscout.androidaps; * Created by mike on 07.06.2016. */ public class Config { + public static int SUPPORTEDNSVERSION = 1000; // 0.10.00 + // MAIN FUCTIONALITY public static final boolean APS = BuildConfig.APS; // PLUGINS @@ -11,15 +13,15 @@ public class Config { public static final boolean LOOPENABLED = APS; public static final boolean WEAR = BuildConfig.WEAR; + public static final boolean NSCLIENT = BuildConfig.NSCLIENTOLNY; public static final boolean DANAR = true && BuildConfig.PUMPDRIVERS; - public static final boolean DANARKOREAN = true && BuildConfig.PUMPDRIVERS; + public static final boolean DANARv2 = true && BuildConfig.PUMPDRIVERS; public static final boolean ACTION = !BuildConfig.NSCLIENTOLNY; public static final boolean VIRTUALPUMP = !BuildConfig.NSCLIENTOLNY; public static final boolean MDI = !BuildConfig.NSCLIENTOLNY; public static final boolean OTHERPROFILES = !BuildConfig.NSCLIENTOLNY; - public static final boolean TEMPBASALS = !BuildConfig.NSCLIENTOLNY; public static final boolean SAFETY = !BuildConfig.NSCLIENTOLNY; public static final boolean SMSCOMMUNICATORENABLED = !BuildConfig.NSCLIENTOLNY; @@ -29,18 +31,16 @@ public class Config { public static final boolean detailedLog = true; public static final boolean logFunctionCalls = true; - public static final boolean logIncommingBG = true; public static final boolean logIncommingData = true; public static final boolean logAPSResult = true; public static final boolean logPumpComm = true; public static final boolean logPrefsChange = true; public static final boolean logConfigBuilder = true; public static final boolean logConstraintsChanges = true; - public static final boolean logTempBasalsCut = true; public static final boolean logNSUpload = true; public static final boolean logPumpActions = true; - public static final boolean logSMSComm = true; public static final boolean logCongigBuilderActions = true; + public static final boolean logAutosensData = true; // DanaR specific public static final boolean logDanaBTComm = true; diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java index 51f27d84a2..e361e4cc8c 100644 --- a/app/src/main/java/info/nightscout/androidaps/Constants.java +++ b/app/src/main/java/info/nightscout/androidaps/Constants.java @@ -33,14 +33,6 @@ public class Constants { public static final int CPP_MIN_PERCENTAGE = 50; public static final int CPP_MAX_PERCENTAGE = 200; - // Defaults for settings - public static final Double MAX_BG_DEFAULT_MGDL = 180d; - public static final Double MAX_BG_DEFAULT_MMOL = 10d; - public static final Double MIN_BG_DEFAULT_MGDL = 100d; - public static final Double MIN_BG_DEFAULT_MMOL = 5d; - public static final Double TARGET_BG_DEFAULT_MGDL = 150d; - public static final Double TARGET_BG_DEFAULT_MMOL = 7d; - // Very Hard Limits Ranges // First value is the Lowest and second value is the Highest a Limit can define public static final int[] VERY_HARD_LIMIT_MIN_BG = {72,180}; diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index 9ae5081dbc..528cbd21bd 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -19,11 +19,11 @@ import android.support.v4.view.ViewPager; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.PopupMenu; -import android.util.AttributeSet; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageButton; @@ -35,10 +35,14 @@ import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.Services.AlarmSoundService; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventRefreshGui; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; import info.nightscout.androidaps.tabs.SlidingTabLayout; import info.nightscout.androidaps.tabs.TabPageAdapter; import info.nightscout.utils.ImportExportPrefs; @@ -59,6 +63,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe ImageButton menuButton; + protected PowerManager.WakeLock mWakeLock; @Override protected void onCreate(Bundle savedInstanceState) { @@ -75,13 +80,28 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe Manifest.permission.WRITE_EXTERNAL_STORAGE}, CASE_STORAGE); } askForBatteryOptimizationPermission(); + checkUpgradeToProfileTarget(); if (Config.logFunctionCalls) log.debug("onCreate"); + onStatusEvent(new EventSetWakeLock(SP.getBoolean("lockscreen", false))); + registerBus(); setUpTabs(false); } + @Subscribe + public void onStatusEvent(final EventSetWakeLock ev) { + final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + if (ev.lock) { + mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "AAPS"); + mWakeLock.acquire(); + } else { + if (mWakeLock != null) + mWakeLock.release(); + } + } + @Subscribe public void onStatusEvent(final EventRefreshGui ev) { String lang = SP.getString("language", "en"); @@ -91,10 +111,15 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe public void run() { recreate(); try { // activity may be destroyed - setUpTabs(ev.isSwitchToLast()); + setUpTabs(true); } catch (IllegalStateException e) { e.printStackTrace(); } + boolean lockScreen = BuildConfig.NSCLIENTOLNY && SP.getBoolean("lockscreen", false); + if (lockScreen) + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + else + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }); } @@ -131,6 +156,29 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe } } + private void checkUpgradeToProfileTarget() { // TODO: can be removed in the future + boolean oldKeyExists = SP.contains("openapsma_min_bg"); + if (oldKeyExists) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + String oldRange = SP.getDouble("openapsma_min_bg", 0d) + " - " + SP.getDouble("openapsma_max_bg", 0d); + String newRange = ""; + if (profile != null) { + newRange = profile.getTargetLow() + " - " + profile.getTargetHigh(); + } + String message = "Target range is changed in current version.\n\nIt's not taken from preferences but from profile.\n\n!!! REVIEW YOUR SETTINGS !!!"; + message += "\n\nOld settings: " + oldRange; + message += "\nProfile settings: " + newRange; + OKDialog.show(this, "Target range change", message, new Runnable() { + @Override + public void run() { + SP.remove("openapsma_min_bg"); + SP.remove("openapsma_max_bg"); + SP.remove("openapsma_target_bg"); + } + }); + } + } + //check for sms permission if enable in prefernces @Subscribe public void onStatusEvent(final EventPreferenceChange ev) { @@ -155,6 +203,13 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe askForSMSPermissions(); } + @Override + public void onDestroy() { + if (mWakeLock != null) + mWakeLock.release(); + super.onDestroy(); + } + private void askForBatteryOptimizationPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { final String packageName = getPackageName(); @@ -296,11 +351,13 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe case R.id.nav_about: AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext()); builder.setTitle(getString(R.string.app_name) + " " + BuildConfig.VERSION); - if (BuildConfig.NSCLIENTOLNY) + if (Config.NSCLIENT) builder.setIcon(R.mipmap.yellowowl); else builder.setIcon(R.mipmap.blueowl); - builder.setMessage("Build: " + BuildConfig.BUILDVERSION); + String message = "Build: " + BuildConfig.BUILDVERSION + "\n"; + message += MainApp.sResources.getString(R.string.configbuilder_nightscoutversion_label) + " " + ConfigBuilderPlugin.nightscoutVersionName; + builder.setMessage(message); builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), null); AlertDialog alertDialog = builder.create(); alertDialog.show(); diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index fab46087be..ac9aa93c7b 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -2,8 +2,10 @@ package info.nightscout.androidaps; import android.app.Application; import android.content.Intent; +import android.content.IntentFilter; import android.content.res.Resources; import android.support.annotation.Nullable; +import android.support.v4.content.LocalBroadcastManager; import com.crashlytics.android.Crashlytics; import com.crashlytics.android.answers.Answers; @@ -17,44 +19,57 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; +import info.nightscout.androidaps.Services.Intents; 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.InsulinFastactingProlonged.InsulinFastactingProlongedFragment; -import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorFragment; -import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfileFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanFragment; -import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingFragment; -import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfileFragment; -import info.nightscout.androidaps.plugins.Loop.LoopFragment; -import info.nightscout.androidaps.plugins.PumpMDI.MDIFragment; -import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalFragment; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfileFragment; import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesFragment; +import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin; +import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingFragment; +import info.nightscout.androidaps.plugins.InsulinFastactingProlonged.InsulinFastactingProlongedFragment; +import info.nightscout.androidaps.plugins.InsulinOrefCurves.InsulinOrefFreePeakFragment; +import info.nightscout.androidaps.plugins.InsulinOrefCurves.InsulinOrefRapidActingFragment; +import info.nightscout.androidaps.plugins.InsulinOrefCurves.InsulinOrefUltraRapidActingFragment; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.Loop.LoopFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.receivers.AckAlarmReceiver; 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.ConstraintsSafety.SafetyFragment; -import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfileFragment; -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.PumpVirtual.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.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.MDIPlugin; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; +import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; +import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; +import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment; +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.Treatments.TreatmentsFragment; +import info.nightscout.androidaps.plugins.Wear.WearFragment; import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; +import info.nightscout.androidaps.receivers.DataReceiver; import info.nightscout.androidaps.receivers.KeepAliveReceiver; +import info.nightscout.androidaps.receivers.NSAlarmReceiver; +import info.nightscout.utils.NSUpload; import io.fabric.sdk.android.Fabric; @@ -71,6 +86,11 @@ public class MainApp extends Application { private static ArrayList pluginsList = null; + private static DataReceiver dataReceiver = new DataReceiver(); + private static NSAlarmReceiver alarmReciever = new NSAlarmReceiver(); + private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver(); + private LocalBroadcastManager lbm; + @Override public void onCreate() { super.onCreate(); @@ -80,25 +100,32 @@ public class MainApp extends Application { log.info("Version: " + BuildConfig.VERSION_NAME); log.info("BuildVersion: " + BuildConfig.BUILDVERSION); - Answers.getInstance().logCustom(new CustomEvent("AppStart")); - sBus = new Bus(ThreadEnforcer.ANY); sInstance = this; sResources = getResources(); + registerLocalBroadcastReceiver(); + if (pluginsList == null) { pluginsList = new ArrayList<>(); // Register all tabs in app here pluginsList.add(OverviewFragment.getPlugin()); - pluginsList.add(IobCobCalculatorFragment.getPlugin()); + pluginsList.add(IobCobCalculatorPlugin.getPlugin()); if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); pluginsList.add(InsulinFastactingFragment.getPlugin()); pluginsList.add(InsulinFastactingProlongedFragment.getPlugin()); + pluginsList.add(InsulinOrefRapidActingFragment.getPlugin()); + pluginsList.add(InsulinOrefUltraRapidActingFragment.getPlugin()); + pluginsList.add(InsulinOrefFreePeakFragment.getPlugin()); + pluginsList.add(SensitivityOref0Plugin.getPlugin()); + //pluginsList.add(SensitivityAAPSPlugin.getPlugin()); + //pluginsList.add(SensitivityWeightedAveragePlugin.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.MDI) pluginsList.add(MDIPlugin.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()); @@ -107,19 +134,20 @@ public class MainApp extends Application { if (Config.OTHERPROFILES) pluginsList.add(LocalProfileFragment.getPlugin()); if (Config.OTHERPROFILES) pluginsList.add(CircadianPercentageProfileFragment.getPlugin()); - if (Config.APS) pluginsList.add(TempTargetRangeFragment.getPlugin()); pluginsList.add(TreatmentsFragment.getPlugin()); - if (Config.TEMPBASALS) pluginsList.add(TempBasalsFragment.getPlugin()); - if (Config.SAFETY) pluginsList.add(SafetyFragment.getPlugin()); + if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin()); if (Config.APS) pluginsList.add(ObjectivesFragment.getPlugin()); - pluginsList.add(SourceXdripFragment.getPlugin()); - pluginsList.add(SourceNSClientFragment.getPlugin()); - pluginsList.add(SourceMM640gFragment.getPlugin()); - pluginsList.add(SourceGlimpFragment.getPlugin()); + if (!Config.NSCLIENT) + pluginsList.add(SourceXdripPlugin.getPlugin()); + pluginsList.add(SourceNSClientPlugin.getPlugin()); + if (!Config.NSCLIENT) + pluginsList.add(SourceMM640gPlugin.getPlugin()); + if (!Config.NSCLIENT) + pluginsList.add(SourceGlimpPlugin.getPlugin()); if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorFragment.getPlugin()); if (Config.WEAR) pluginsList.add(WearFragment.getPlugin(this)); - pluginsList.add(StatuslineFragment.getPlugin(this)); + pluginsList.add(StatuslinePlugin.getPlugin(this)); pluginsList.add(new PersistentNotificationPlugin(this)); pluginsList.add(NSClientInternalFragment.getPlugin()); @@ -127,7 +155,12 @@ public class MainApp extends Application { MainApp.getConfigBuilder().initialize(); } - MainApp.getConfigBuilder().uploadAppStart(); + NSUpload.uploadAppStart(); + if (MainApp.getConfigBuilder().isClosedModeEnabled()) + Answers.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop")); + else + Answers.getInstance().logCustom(new CustomEvent("AppStart")); + startKeepAliveService(); @@ -144,14 +177,38 @@ public class MainApp extends Application { } }); t.start(); + + } + + private void registerLocalBroadcastReceiver() { + lbm = LocalBroadcastManager.getInstance(this); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_SGV)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_PROFILE)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_STATUS)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_MBG)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_DEVICESTATUS)); + lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_CAL)); + + //register alarms + lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_ALARM)); + lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_ANNOUNCEMENT)); + lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_CLEAR_ALARM)); + lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_URGENT_ALARM)); + + //register ack alarm + lbm.registerReceiver(ackAlarmReciever, new IntentFilter(Intents.ACTION_ACK_ALARM)); } private void startKeepAliveService() { if (keepAliveReceiver == null) { keepAliveReceiver = new KeepAliveReceiver(); if (Config.DANAR) { - startService(new Intent(this, info.nightscout.androidaps.plugins.PumpDanaR.Services.ExecutionService.class)); - startService(new Intent(this, info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService.class)); + startService(new Intent(this, DanaRExecutionService.class)); + startService(new Intent(this, DanaRKoreanExecutionService.class)); + startService(new Intent(this, DanaRv2ExecutionService.class)); } keepAliveReceiver.setAlarm(this); } @@ -207,6 +264,19 @@ public class MainApp extends Application { return newList; } + @Nullable + public static InsulinInterface getInsulinIterfaceById(int id) { + 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<>(); @@ -252,11 +322,11 @@ public class MainApp extends Application { } @Nullable - public static PluginBase getSpecificPlugin(Class pluginClass) { + public static T getSpecificPlugin(Class pluginClass) { if (pluginsList != null) { for (PluginBase p : pluginsList) { - if (p.getClass() == pluginClass) - return p; + if (pluginClass.isAssignableFrom(p.getClass())) + return (T) p; } } else { log.error("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 ed7f780547..5c3372123e 100644 --- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java @@ -14,15 +14,22 @@ 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.InsulinOrefCurves.InsulinOrefFreePeakPlugin; 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.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; +import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; +import info.nightscout.androidaps.plugins.SensitivityWeightedAverage.SensitivityWeightedAveragePlugin; import info.nightscout.androidaps.plugins.Wear.WearPlugin; import info.nightscout.androidaps.plugins.XDripStatusline.StatuslinePlugin; import info.nightscout.utils.LocaleHelper; +import info.nightscout.utils.OKDialog; +import info.nightscout.utils.SP; public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener { MyPreferenceFragment myPreferenceFragment; @@ -42,10 +49,13 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre String lang = sharedPreferences.getString("language", "en"); LocaleHelper.setLocale(getApplicationContext(), lang); recreate(); - MainApp.bus().post(new EventRefreshGui(true)); + MainApp.bus().post(new EventRefreshGui()); } if (key.equals("short_tabtitles")) { - MainApp.bus().post(new EventRefreshGui(true)); + MainApp.bus().post(new EventRefreshGui()); + } + if (key.equals("openapsama_useautosens") && SP.getBoolean("openapsama_useautosens", false)) { + OKDialog.show(this, MainApp.sResources.getString(R.string.configbuilder_sensitivity), MainApp.sResources.getString(R.string.sensitivity_warning), null); } updatePrefSummary(myPreferenceFragment.getPreference(key)); } @@ -87,8 +97,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre super.onCreate(savedInstanceState); if (Config.ALLPREFERENCES) { addPreferencesFromResource(R.xml.pref_password); - addPreferencesFromResource(R.xml.pref_age); } + addPreferencesFromResource(R.xml.pref_age); addPreferencesFromResource(R.xml.pref_language); if (Config.ALLPREFERENCES) { addPreferencesFromResource(R.xml.pref_quickwizard); @@ -104,24 +114,38 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) addPreferencesFromResource(R.xml.pref_openapsama); } + if (MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class) != null && MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class).isEnabled(PluginBase.SENSITIVITY) + || MainApp.getSpecificPlugin(SensitivityWeightedAveragePlugin.class) != null && MainApp.getSpecificPlugin(SensitivityWeightedAveragePlugin.class).isEnabled(PluginBase.SENSITIVITY)) + addPreferencesFromResource(R.xml.pref_absorption_aaps); + if (MainApp.getSpecificPlugin(SensitivityOref0Plugin.class) != null && MainApp.getSpecificPlugin(SensitivityOref0Plugin.class).isEnabled(PluginBase.SENSITIVITY)) + addPreferencesFromResource(R.xml.pref_absorption_oref0); if (Config.ALLPREFERENCES) { addPreferencesFromResource(R.xml.pref_profile); } if (Config.DANAR) { - DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); + DanaRPlugin danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); + DanaRKoreanPlugin danaRKoreanPlugin = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); + 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); } } - VirtualPumpPlugin virtualPumpPlugin = (VirtualPumpPlugin) MainApp.getSpecificPlugin(VirtualPumpPlugin.class); + VirtualPumpPlugin virtualPumpPlugin = MainApp.getSpecificPlugin(VirtualPumpPlugin.class); if (virtualPumpPlugin != null && virtualPumpPlugin.isEnabled(PluginBase.PUMP)) { addPreferencesFromResource(R.xml.pref_virtualpump); } - NSClientInternalPlugin nsClientInternalPlugin = (NSClientInternalPlugin) MainApp.getSpecificPlugin(NSClientInternalPlugin.class); + InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin = MainApp.getSpecificPlugin(InsulinOrefFreePeakPlugin.class); + if(insulinOrefFreePeakPlugin.isEnabled(PluginBase.INSULIN)){ + addPreferencesFromResource(R.xml.pref_insulinoreffreepeak); + } + + NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); if (nsClientInternalPlugin != null && nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) { addPreferencesFromResource(R.xml.pref_nsclientinternal); } @@ -129,17 +153,17 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre addPreferencesFromResource(R.xml.pref_smscommunicator); if (Config.ALLPREFERENCES) { addPreferencesFromResource(R.xml.pref_others); - addPreferencesFromResource(R.xml.pref_advanced); } + addPreferencesFromResource(R.xml.pref_advanced); if (Config.WEAR) { - WearPlugin wearPlugin = (WearPlugin) MainApp.getSpecificPlugin(WearPlugin.class); + WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class); if (wearPlugin != null && wearPlugin.isEnabled(PluginBase.GENERAL)) { addPreferencesFromResource(R.xml.pref_wear); } } - StatuslinePlugin statuslinePlugin = (StatuslinePlugin) MainApp.getSpecificPlugin(StatuslinePlugin.class); + StatuslinePlugin statuslinePlugin = MainApp.getSpecificPlugin(StatuslinePlugin.class); if (statuslinePlugin != null && statuslinePlugin.isEnabled(PluginBase.GENERAL)) { addPreferencesFromResource(R.xml.pref_xdripstatus); } diff --git a/app/src/main/java/info/nightscout/androidaps/Services/AlarmSoundService.java b/app/src/main/java/info/nightscout/androidaps/Services/AlarmSoundService.java new file mode 100644 index 0000000000..41587e79b9 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/Services/AlarmSoundService.java @@ -0,0 +1,73 @@ +package info.nightscout.androidaps.Services; + +import android.app.Service; +import android.content.Intent; +import android.content.res.AssetFileDescriptor; +import android.media.MediaPlayer; +import android.os.IBinder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +public class AlarmSoundService extends Service { + private static Logger log = LoggerFactory.getLogger(AlarmSoundService.class); + + MediaPlayer player; + int resourceId = R.raw.error; + + public AlarmSoundService() { + } + + @Override + public IBinder onBind(Intent intent) { + // TODO: Return the communication channel to the service. + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void onCreate() { + super.onCreate(); + log.debug("onCreate"); + } + + public int onStartCommand(Intent intent, int flags, int startId) { + if (player != null && player.isPlaying()) + player.stop(); + log.debug("onStartCommand"); + if (intent != null && intent.hasExtra("soundid")) + resourceId = intent.getIntExtra("soundid", R.raw.error); + + player = new MediaPlayer(); + AssetFileDescriptor afd = MainApp.sResources.openRawResourceFd(resourceId); + if (afd == null) + return START_STICKY; + try { + player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); + afd.close(); + } catch (IOException e) { + e.printStackTrace(); + } + player.setLooping(true); // Set looping + player.setVolume(100, 100); + + try { + player.prepare(); + player.start(); + } catch (IOException e) { + e.printStackTrace(); + } + + return START_STICKY; + } + + @Override + public void onDestroy() { + player.stop(); + player.release(); + } +} 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 e60a89e6a0..39eb023cb3 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -2,58 +2,42 @@ package info.nightscout.androidaps.Services; import android.app.IntentService; import android.content.Intent; -import android.content.SharedPreferences; +import android.content.pm.PackageManager; 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.InsulinInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.History.DanaRNSHistorySync; -import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingFragment; -import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; 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.NSClientInternal.data.NSSettingsStatus; 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.activities.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.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; +import info.nightscout.utils.BundleLogger; import info.nightscout.utils.SP; @@ -73,7 +57,7 @@ public class DataService extends IntentService { @Override protected void onHandleIntent(final Intent intent) { if (Config.logFunctionCalls) - log.debug("onHandleIntent " + intent); + log.debug("onHandleIntent " + BundleLogger.log(intent.getExtras())); if (ConfigBuilderPlugin.getActiveBgSource().getClass().equals(SourceXdripPlugin.class)) { xDripEnabled = true; @@ -97,7 +81,7 @@ public class DataService extends IntentService { glimpEnabled = true; } - boolean isNSProfile = ConfigBuilderPlugin.getActiveProfile().getClass().equals(NSProfilePlugin.class); + boolean isNSProfile = ConfigBuilderPlugin.getActiveProfileInterface().getClass().equals(NSProfilePlugin.class); boolean nsUploadOnly = SP.getBoolean(R.string.key_ns_upload_only, false); @@ -180,25 +164,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) { @@ -209,20 +178,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) { @@ -247,23 +206,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); @@ -274,7 +220,6 @@ public class DataService extends IntentService { } } } - MainApp.bus().post(new EventNewBG()); } private void handleNewDataFromNSClient(Intent intent) { @@ -285,19 +230,27 @@ public class DataService extends IntentService { if (intent.getAction().equals(Intents.ACTION_NEW_STATUS)) { - if (Config.logIncommingData) - log.debug("Received status: " + bundles); if (bundles.containsKey("nsclientversioncode")) { ConfigBuilderPlugin.nightscoutVersionCode = bundles.getInt("nightscoutversioncode"); // for ver 1.2.3 contains 10203 ConfigBuilderPlugin.nightscoutVersionName = bundles.getString("nightscoutversionname"); ConfigBuilderPlugin.nsClientVersionCode = bundles.getInt("nsclientversioncode"); // for ver 1.17 contains 117 ConfigBuilderPlugin.nsClientVersionName = bundles.getString("nsclientversionname"); log.debug("Got versions: NSClient: " + ConfigBuilderPlugin.nsClientVersionName + " Nightscout: " + ConfigBuilderPlugin.nightscoutVersionName); - if (ConfigBuilderPlugin.nsClientVersionCode < 121) { - Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT); + try { + if (ConfigBuilderPlugin.nsClientVersionCode < MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode) { + Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT)); + } + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (ConfigBuilderPlugin.nightscoutVersionCode < Config.SUPPORTEDNSVERSION) { + Notification notification = new Notification(Notification.OLD_NS, MainApp.sResources.getString(R.string.unsupportednsversion), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); } else { - MainApp.bus().post(new EventDismissNotification(Notification.OLD_NSCLIENT)); + MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS)); } } else { Notification notification = new Notification(Notification.OLD_NSCLIENT, MainApp.sResources.getString(R.string.unsupportedclientver), Notification.URGENT); @@ -306,18 +259,15 @@ public class DataService extends IntentService { if (bundles.containsKey("status")) { try { JSONObject statusJson = new JSONObject(bundles.getString("status")); - if (statusJson.has("settings")) { - JSONObject settings = statusJson.getJSONObject("settings"); - if (settings.has("thresholds")) { - JSONObject thresholds = settings.getJSONObject("thresholds"); - if (thresholds.has("bgTargetTop")) { - OverviewPlugin.bgTargetHigh = thresholds.getDouble("bgTargetTop"); - } - if (thresholds.has("bgTargetBottom")) { - OverviewPlugin.bgTargetLow = thresholds.getDouble("bgTargetBottom"); - } - } - } + NSSettingsStatus.getInstance().setData(statusJson); + if (Config.logIncommingData) + log.debug("Received status: " + statusJson.toString()); + Double targetHigh = NSSettingsStatus.getInstance().getThreshold("bgTargetTop"); + Double targetlow = NSSettingsStatus.getInstance().getThreshold("bgTargetBottom"); + if (targetHigh != null) + OverviewPlugin.bgTargetHigh = targetHigh; + if (targetlow != null) + OverviewPlugin.bgTargetLow = targetlow; } catch (JSONException e) { e.printStackTrace(); } @@ -326,8 +276,8 @@ public class DataService extends IntentService { if (intent.getAction().equals(Intents.ACTION_NEW_DEVICESTATUS)) { try { if (bundles.containsKey("devicestatus")) { - String devicestatusesstring = bundles.getString("devicestatus"); JSONObject devicestatusJson = new JSONObject(bundles.getString("devicestatus")); + NSDeviceStatus.getInstance().setData(devicestatusJson); if (devicestatusJson.has("pump")) { // Objectives 0 ObjectivesPlugin.pumpStatusIsAvailableInNS = true; @@ -337,8 +287,9 @@ public class DataService extends IntentService { if (bundles.containsKey("devicestatuses")) { String devicestatusesstring = bundles.getString("devicestatuses"); JSONArray jsonArray = new JSONArray(devicestatusesstring); - if (jsonArray.length() > 0) { - JSONObject devicestatusJson = jsonArray.getJSONObject(0); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject devicestatusJson = jsonArray.getJSONObject(i); + NSDeviceStatus.getInstance().setData(devicestatusJson); if (devicestatusJson.has("pump")) { // Objectives 0 ObjectivesPlugin.pumpStatusIsAvailableInNS = true; @@ -355,25 +306,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, "NSClient")); + 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(); } @@ -382,7 +320,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"); @@ -390,7 +328,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) { @@ -403,7 +341,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"); @@ -411,7 +349,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) { @@ -425,8 +363,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")) { @@ -435,8 +372,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) { @@ -451,14 +387,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")) { @@ -468,248 +397,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); - InsulinInterface insulinInterface = MainApp.getConfigBuilder().getActiveInsulin(); - if (insulinInterface == null) insulinInterface = InsulinFastactingFragment.getPlugin(); - Treatment treatment = new Treatment(insulinInterface); - 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); - InsulinInterface insulinInterface = MainApp.getConfigBuilder().getActiveInsulin(); - if (insulinInterface == null) insulinInterface = InsulinFastactingFragment.getPlugin(); - Treatment treatment = new Treatment(insulinInterface); - 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.has("eventType") && trJson.getString("eventType").equals(CareportalEvent.ANNOUNCEMENT)) { + long date = trJson.getLong("mills"); + long now = System.currentTimeMillis(); + if (date > now - 15 * 60 * 1000L && trJson.has("notes")) { + Notification announcement = new Notification(Notification.NSANNOUNCEMENT, trJson.getString("notes"), Notification.ANNOUNCEMENT, 60); + 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/Services/Intents.java b/app/src/main/java/info/nightscout/androidaps/Services/Intents.java index 1b7b0875e5..77ef5139ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/Intents.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/Intents.java @@ -12,12 +12,17 @@ public interface Intents { String ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL"; String ACTION_NEW_STATUS = "info.nightscout.client.NEW_STATUS"; String ACTION_QUEUE_STATUS = "info.nightscout.client.QUEUE_STATUS"; + String ACTION_ANNOUNCEMENT = "info.nightscout.client.ANNOUNCEMENT"; + String ACTION_ALARM = "info.nightscout.client.ALARM"; + String ACTION_URGENT_ALARM = "info.nightscout.client.URGENT_ALARM"; + String ACTION_CLEAR_ALARM = "info.nightscout.client.CLEAR_ALARM"; // App -> NSClient String ACTION_DATABASE = "info.nightscout.client.DBACCESS"; String ACTION_RESTART = "info.nightscout.client.RESTART"; String ACTION_RESEND = "info.nightscout.client.RESEND"; + String ACTION_ACK_ALARM = "info.nightscout.client.ACK_ALARM"; // xDrip -> App String RECEIVER_PERMISSION = "com.eveningoutpost.dexdrip.permissions.RECEIVE_BG_ESTIMATE"; 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..2d928a5541 --- /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 = System.currentTimeMillis(); + public String eventType = CareportalEvent.MEALBOLUS; + public double insulin = 0; + public double carbs = 0; + public int source = Source.NONE; + public boolean isValid = true; + 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 long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) + public boolean isSMB = false; // is a Super-MicroBolus +} 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 c4caf2f1af..1623028a82 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); + long fromtime = (long) (System.currentTimeMillis() - 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 < System.currentTimeMillis() - 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; @@ -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/Intervals.java b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java new file mode 100644 index 0000000000..108b4060e0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/Intervals.java @@ -0,0 +1,90 @@ +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 abstract class Intervals { + + LongSparseArray rawData = new LongSparseArray(); // oldest at index 0 + + public synchronized Intervals reset() { + rawData = new LongSparseArray(); + return this; + } + + protected abstract void merge(); + + /** + * The List must be sorted by `T.start()` in ascending order + * + * */ + public synchronized void add(List list) { + for (T interval : list) { + rawData.put(interval.start(), interval); + } + merge(); + } + + + + public synchronized List getList() { + List list = new ArrayList<>(); + for (int i = 0; i < rawData.size(); i++) + list.add(rawData.valueAt(i)); + return list; + } + + public synchronized List getReversedList() { + List list = new ArrayList<>(); + for (int i = rawData.size() -1; i>=0; i--) + list.add(rawData.valueAt(i)); + return list; + } + + protected synchronized 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 abstract T getValueByInterval(long time); + + public synchronized int size() { + return rawData.size(); + } + + public synchronized T get(int index) { + return rawData.valueAt(index); + } + + public synchronized 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/IobTotal.java b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java index ed3096c945..bd924d35b5 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java +++ b/app/src/main/java/info/nightscout/androidaps/data/IobTotal.java @@ -1,26 +1,29 @@ 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; public class IobTotal { - public Double iob; - public Double activity; - public Double bolussnooze; - public Double basaliob; - public Double netbasalinsulin; - public Double hightempinsulin; + public double iob; + public double activity; + public double bolussnooze; + public double basaliob; + public double netbasalinsulin; + public double hightempinsulin; - public Double netInsulin = 0d; // for calculations from temp basals only - public Double netRatio = 0d; // net ratio at start of temp basal + // oref1 + public double microBolusInsulin; + public double microBolusIOB; + + public double netInsulin = 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; @@ -31,6 +34,8 @@ public class IobTotal { this.basaliob = 0d; this.netbasalinsulin = 0d; this.hightempinsulin = 0d; + this.microBolusInsulin = 0d; + this.microBolusIOB = 0d; this.time = time; } @@ -42,7 +47,9 @@ public class IobTotal { netbasalinsulin += other.netbasalinsulin; hightempinsulin += other.hightempinsulin; netInsulin += other.netInsulin; - netRatio += other.netRatio; + extendedBolusInsulin += other.extendedBolusInsulin; + microBolusInsulin += other.microBolusInsulin; + microBolusIOB += other.microBolusIOB; return this; } @@ -54,6 +61,8 @@ public class IobTotal { result.basaliob = basalIob.basaliob; result.netbasalinsulin = basalIob.netbasalinsulin; result.hightempinsulin = basalIob.hightempinsulin; + result.microBolusInsulin = bolusIOB.microBolusInsulin + basalIob.microBolusInsulin; + result.microBolusIOB = bolusIOB.microBolusIOB + basalIob.microBolusIOB; return result; } @@ -64,6 +73,8 @@ public class IobTotal { this.basaliob = Round.roundTo(this.basaliob, 0.001); this.netbasalinsulin = Round.roundTo(this.netbasalinsulin, 0.001); this.hightempinsulin = Round.roundTo(this.hightempinsulin, 0.001); + this.microBolusInsulin = Round.roundTo(this.microBolusInsulin, 0.001); + this.microBolusIOB = Round.roundTo(this.microBolusIOB, 0.001); return this; } diff --git a/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java new file mode 100644 index 0000000000..385eeb9594 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/NonOverlappingIntervals.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.data; + + +import android.support.annotation.Nullable; + +import info.nightscout.androidaps.interfaces.Interval; + +/** + * Created by adrian on 15/07/17. + */ + +public class NonOverlappingIntervals extends Intervals { + + protected synchronized 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 synchronized T getValueByInterval(long time) { + int index = binarySearch(time); + if (index >= 0) return rawData.valueAt(index); + return null; + } +} 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..070426cca0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/OverlappingIntervals.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.data; + + +import android.support.annotation.Nullable; + +import info.nightscout.androidaps.interfaces.Interval; + +/** + * Created by adrian on 15/07/17. + */ + +public class OverlappingIntervals extends Intervals { + + protected synchronized void merge() { + boolean needToCut = false; + long cutTime = 0; + + for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest + Interval cur = rawData.valueAt(index); + if (cur.isEndingEvent()){ + needToCut = true; + cutTime = cur.start(); + } else { + //event that is no EndingEvent might need to be stopped by an ending event + if(needToCut&&cur.end() > cutTime){ + cur.cutEndTo(cutTime); + } + } + } + } + + @Nullable + public synchronized T getValueByInterval(long time) { + for (int index = rawData.size()-1; index >= 0; index--) { //begin with newest + T cur = rawData.valueAt(index); + if (cur.match(time)){ + return cur; + } + } + return null; + } + +} 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..984d92c4e5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -0,0 +1,413 @@ +package info.nightscout.androidaps.data; + +import android.support.v4.util.LongSparseArray; + +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; + private LongSparseArray isf_v = null; // oldest at index 0 + JSONArray ic; + private LongSparseArray ic_v = null; // oldest at index 0 + JSONArray basal; + private LongSparseArray basal_v = null; // oldest at index 0 + 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; + ic = 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; + basal = 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; + targetLow = 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; + targetHigh = 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((Integer) (hour * 60 * 60)); + ret += "NS basal value for " + hour + ":00 is " + value + "\n"; + } + ret += "NS units: " + getUnits(); + return ret; + } + + public JSONObject getData() { + if (!json.has("units")) + try { + json.put("units", units); + } catch (JSONException e) { + e.printStackTrace(); + } + return json; + } + + public double getDia() { + return dia; + } + + // mmol or mg/dl + public String getUnits() { + return units; + } + + public TimeZone getTimeZone() { + return timeZone; + } + + private LongSparseArray convertToSparseArray(JSONArray array) { + LongSparseArray sparse = new LongSparseArray<>(); + for (Integer index = 0; index < array.length(); index++) { + try { + JSONObject o = array.getJSONObject(index); + long tas = o.getLong("timeAsSeconds"); + Double value = o.getDouble("value"); + sparse.put(tas, value); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return sparse; + } + + 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 Double getValueToTime(LongSparseArray array, long timeAsSeconds) { + Double lastValue = null; + + for (Integer index = 0; index < array.size(); index++) { + long tas = array.keyAt(index); + double value = array.valueAt(index); + if (lastValue == null) lastValue = value; + if (timeAsSeconds < tas) { + break; + } + lastValue = value; + } + 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; + if (index + 1 < array.length()) + retValue += "\n"; + } catch (JSONException e) { + e.printStackTrace(); + } + } + return retValue; + } + + public Double getIsf() { + return getIsf(secondsFromMidnight(System.currentTimeMillis())); + } + + public Double getIsf(long time) { + return getIsf(secondsFromMidnight(time)); + } + + public Double getIsf(Integer timeAsSeconds) { + if (isf_v == null) + isf_v = convertToSparseArray(isf); + return getValueToTime(isf_v, timeAsSeconds); + } + + public String getIsfList() { + return getValuesList(isf, null, new DecimalFormat("0.0"), getUnits() + "/U"); + } + + public Double getIc() { + return getIc(secondsFromMidnight(System.currentTimeMillis())); + } + + public Double getIc(long time) { + return getIc(secondsFromMidnight(time)); + } + + public Double getIc(Integer timeAsSeconds) { + if (ic_v == null) + ic_v = convertToSparseArray(ic); + return getValueToTime(ic_v, timeAsSeconds); + } + + public String getIcList() { + return getValuesList(ic, null, new DecimalFormat("0.0"), " g/U"); + } + + public Double getBasal() { + return getBasal(secondsFromMidnight(System.currentTimeMillis())); + } + + public Double getBasal(long time) { + return getBasal(secondsFromMidnight(time)); + } + + public Double getBasal(Integer timeAsSeconds) { + if (basal_v == null) + basal_v = convertToSparseArray(basal); + return getValueToTime(basal_v, 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(System.currentTimeMillis())); + } + + public Double getTargetLow(long time) { + return getTargetLow(secondsFromMidnight(time)); + } + + public Double getTargetLow(Integer timeAsSeconds) { + return getValueToTime(targetLow, timeAsSeconds); + } + + public Double getTargetHigh() { + return getTargetHigh(secondsFromMidnight(System.currentTimeMillis())); + } + + 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((Integer) (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 toMmol(Double value, String units) { + if (units.equals(Constants.MGDL)) return value * Constants.MGDL_TO_MMOLL; + else return value; + } + + 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); + } + + // targets are stored in mg/dl but profile vary + public static String toTargetRangeString(double low, double high, String sourceUnits, String units) { + double lowMgdl = toMgdl(low, sourceUnits); + double highMgdl = toMgdl(high, sourceUnits); + double lowMmol = toMmol(low, sourceUnits); + double highMmol = toMmol(high, sourceUnits); + if (low == high) + return toUnitsString(lowMgdl, lowMmol, units); + else + return toUnitsString(lowMgdl, lowMmol, units) + " - " + toUnitsString(highMgdl, highMmol, units); + + } +} 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..3633f1079e --- /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 synchronized ProfileIntervals reset() { + rawData = new LongSparseArray<>(); + return this; + } + + public synchronized void add(T newInterval) { + rawData.put(newInterval.start(), newInterval); + merge(); + } + + public synchronized void add(List list) { + for (T interval : list) { + rawData.put(interval.start(), interval); + } + merge(); + } + + private synchronized 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 synchronized Interval getValueToTime(long time) { + int index = binarySearch(time); + if (index >= 0) return rawData.valueAt(index); + return null; + } + + public synchronized List getList() { + List list = new ArrayList<>(); + for (int i = 0; i < rawData.size(); i++) + list.add(rawData.valueAt(i)); + return list; + } + + public synchronized List getReversedList() { + List list = new ArrayList<>(); + for (int i = rawData.size() -1; i>=0; i--) + list.add(rawData.valueAt(i)); + return list; + } + + private synchronized 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 synchronized int size() { + return rawData.size(); + } + + public synchronized T get(int index) { + return rawData.valueAt(index); + } + + public synchronized 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..3e2217454f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/data/ProfileStore.java @@ -0,0 +1,118 @@ +package info.nightscout.androidaps.data; + +import android.support.annotation.Nullable; +import android.support.v4.util.ArrayMap; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Iterator; + +import info.nightscout.androidaps.Constants; + +/** + * Created by mike on 01.06.2017. + */ + +public class ProfileStore { + private static Logger log = LoggerFactory.getLogger(ProfileStore.class); + private JSONObject json = null; + private String units = Constants.MGDL; + + ArrayMap cachedObjects = new ArrayMap<>(); + + public ProfileStore(JSONObject json) { + this.json = json; + getDefaultProfile(); // initialize units + } + + 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)) { + profile = cachedObjects.get(defaultProfileName); + if (profile == null) { + if (store.has("units")) + units = store.getString("units"); + profile = new Profile(store.getJSONObject(defaultProfileName), units); + units = profile.getUnits(); + cachedObjects.put(defaultProfileName, profile); + } + } + } 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; + } + + public String getUnits() { + return units; + } + + @Nullable + public Profile getSpecificProfile(String profileName) { + Profile profile = null; + try { + JSONObject store = json.getJSONObject("store"); + if (store.has(profileName)) { + profile = cachedObjects.get(profileName); + if (profile == null) { + if (store.has("units")) + units = store.getString("units"); + profile = new Profile(store.getJSONObject(profileName), units); + units = profile.getUnits(); + cachedObjects.put(profileName, profile); + } + } + } 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..cbe1850958 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,9 +67,11 @@ 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) { + if (direction == null) { + symbol = "??"; + } else if (direction.compareTo("DoubleDown") == 0) { symbol = "\u21ca"; } else if (direction.compareTo("SingleDown") == 0) { symbol = "\u2193"; @@ -101,23 +107,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().getProfileUnits(); 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().getProfileUnits(); + 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..f65da51176 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -0,0 +1,245 @@ +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.OverviewFragment; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.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 System.currentTimeMillis() - date; + } + + public long getHoursFromStart() { + return (System.currentTimeMillis() - date) / (60 * 1000); + } + + public String age() { + Map diff = computeDiff(date, System.currentTimeMillis()); + if (OverviewFragment.shorttextmode) + return diff.get(TimeUnit.DAYS) +"d" + diff.get(TimeUnit.HOURS) + "h"; + else + return diff.get(TimeUnit.DAYS) + " " + MainApp.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() { + String units = MainApp.getConfigBuilder().getProfileUnits(); + if (eventType.equals(MBG)) { + double mbg = 0d; + try { + JSONObject object = new JSONObject(json); + mbg = object.getDouble("mgdl"); + } catch (JSONException e) { + e.printStackTrace(); + } + return Profile.fromMgdlToUnits(mbg, units); + } + + double glucose = 0d; + try { + JSONObject object = new JSONObject(json); + if (object.has("glucose")) { + glucose = object.getDouble("glucose"); + units = object.getString("units"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + if (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, units); + } + + 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 MainApp.sResources.getColor(R.color.notificationAnnouncement); + 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 17c01bd9ff..2b4cc87f20 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,12 +14,13 @@ 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; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -28,43 +30,80 @@ 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.EventRefreshOverview; +import info.nightscout.androidaps.events.EventReloadProfileSwitchData; +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.activities.DanaRNSHistorySync; +import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; 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 = 6; + private static final int DATABASE_VERSION = 8; - private static Long latestTreatmentChange = null; + 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,14 +113,23 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { @Override 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); - onCreate(database, connectionSource); + if (oldVersion == 7 && newVersion == 8) { + log.debug("Upgrading database from v7 to v8"); + TableUtils.dropTable(connectionSource, Treatment.class, true); + TableUtils.createTableIfNotExists(connectionSource, Treatment.class); + } else { + log.info(DatabaseHelper.class.getName(), "onUpgrade"); + 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); throw new RuntimeException(e); @@ -99,53 +147,96 @@ 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" + " < '" + (System.currentTimeMillis() - 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" + " < '" + (System.currentTimeMillis() - 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" + " < '" + (System.currentTimeMillis() - 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); + getWritableDatabase().delete(DATABASE_DANARHISTORY, "recordDate" + " < '" + (System.currentTimeMillis() - 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" + " < '" + (System.currentTimeMillis() - 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" + " < '" + (System.currentTimeMillis() - 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" + " < '" + (System.currentTimeMillis() - 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" + " < '" + (System.currentTimeMillis() - 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 = 0L; + 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(); } + VirtualPumpPlugin.setFakingStatus(true); + 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 EventRefreshOverview("resetDatabases")); + } + }, + 3000 + ); } public void resetTreatments() { try { TableUtils.dropTable(connectionSource, Treatment.class, true); TableUtils.createTableIfNotExists(connectionSource, Treatment.class); - latestTreatmentChange = 0L; + updateEarliestDataChange(0); } catch (SQLException e) { e.printStackTrace(); } + scheduleTreatmentChange(); } public void resetTempTargets() { @@ -155,13 +246,55 @@ 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(); + } + VirtualPumpPlugin.setFakingStatus(false); + 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); } @@ -169,30 +302,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 > System.currentTimeMillis() - 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; @@ -202,7 +435,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } - // DbRequests handling + // ------------- DbRequests handling ------------------- public void create(DbRequest dbr) { try { @@ -258,83 +491,131 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - // TREATMENT HANDLING - - public boolean affectingIobCob(Treatment t) { - Treatment existing = findTreatmentByTimeIndex(t.timeIndex); - if (existing == null) - return true; - if (existing.insulin == t.insulin && existing.carbs == t.carbs) - return false; - return true; + 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 { - boolean historyChange = affectingIobCob(treatment); - updated = getDaoTreatments().update(treatment); - if (historyChange) - 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 { - boolean historyChange = affectingIobCob(treatment); - status = getDaoTreatments().createOrUpdate(treatment); - if (historyChange) - 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) { - 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(); - scheduleTreatmentChange(); - } else { - log.debug("REMOVE: Not stored treatment (ignoring): " + _id); + public void update(Treatment treatment) { + try { + getDaoTreatments().update(treatment); + updateEarliestDataChange(treatment.date); + } catch (SQLException e) { + e.printStackTrace(); + } + scheduleTreatmentChange(); + } + + public void deleteTreatmentById(String _id) { + Treatment stored = findTreatmentById(_id); + if (stored != null) { + log.debug("TREATMENT: Removing Treatment record from database: " + stored.toString()); + delete(stored); + updateEarliestDataChange(stored.date); + scheduleTreatmentChange(); } - return removed; } @Nullable @@ -360,47 +641,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()); - if (latestTreatmentChange != null) - MainApp.bus().post(new EventNewHistoryData(latestTreatmentChange)); - latestTreatmentChange = null; - 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); } @@ -409,9 +678,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; @@ -421,24 +690,45 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return new ArrayList(); } - public void delete(TempBasal tempBasal) { + public void createTreatmentFromJsonIfNotExists(JSONObject trJson) { try { - getDaoTempBasals().delete(tempBasal); - latestTreatmentChange = tempBasal.getTimeIndex(); - } catch (SQLException e) { + 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("isSMB")) + treatment.isSMB = trJson.getBoolean("isSMB"); + 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(); } - scheduleTreatmentChange(); } + // ---------------- 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; @@ -448,22 +738,938 @@ 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 { + String units = MainApp.getConfigBuilder().getProfileUnits(); + 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.isAbsolute && tempBasal.isAbsolute) { // converted to absolute by "ns_sync_use_absolute" + // so far ignore, do not convert back because it may not be accurate + return false; + } + 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"); + if (!VirtualPumpPlugin.getFakingStatus()) { + VirtualPumpPlugin.setFakingStatus(true); + updateEarliestDataChange(0); + scheduleTemporaryBasalChange(); + } + 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"); + if (!VirtualPumpPlugin.getFakingStatus()) { + VirtualPumpPlugin.setFakingStatus(true); + updateEarliestDataChange(0); + scheduleTemporaryBasalChange(); + } + 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); + scheduleExtendedBolusChange(); + 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); + scheduleExtendedBolusChange(); + 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); + scheduleExtendedBolusChange(); + return true; + } + } + } + getDaoExtendedBolus().create(extendedBolus); + log.debug("EXTENDEDBOLUS: New record from: " + Source.getString(extendedBolus.source) + " " + extendedBolus.toString()); + updateEarliestDataChange(extendedBolus.date); + scheduleExtendedBolusChange(); + 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); + scheduleExtendedBolusChange(); + 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()); + scheduleProfileSwitchChange(); + 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()); + scheduleProfileSwitchChange(); + return true; + } + } + } + getDaoProfileSwitch().create(profileSwitch); + log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); + scheduleProfileSwitchChange(); + return true; + } + if (profileSwitch.source == Source.USER) { + getDaoProfileSwitch().create(profileSwitch); + log.debug("PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); + scheduleProfileSwitchChange(); + 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 EventReloadProfileSwitchData()); + 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..0bd929030f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/ExtendedBolus.java @@ -0,0 +1,283 @@ +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(System.currentTimeMillis()); + } + + @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); + InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); + + int realDuration = getDurationToTime(time); + + if (realDuration > 0) { + double dia_ago = time - dia * 60 * 60 * 1000; + int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); + double spacing = realDuration / aboutFiveMinIntervals; + + for (long j = 0L; j < aboutFiveMinIntervals; j++) { + // find middle of the interval + long calcdate = (long) (date + j * spacing * 60 * 1000 + 0.5d * spacing * 60 * 1000); + + if (calcdate > dia_ago && calcdate <= time) { + double tempBolusSize = absoluteRate() * spacing / 60d; + + Treatment tempBolusPart = new Treatment(); + tempBolusPart.insulin = tempBolusSize; + tempBolusPart.date = calcdate; + + Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia); + result.iob += aIOB.iobContrib; + result.activity += aIOB.activityContrib; + result.extendedBolusInsulin += tempBolusPart.insulin; + } + } + } + return result; + } + + public int getRealDuration() { + return getDurationToTime(System.currentTimeMillis()); + } + + 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() - System.currentTimeMillis()) / 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..fb99934382 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java @@ -0,0 +1,217 @@ +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.Objects; + +import info.nightscout.androidaps.data.Profile; +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; + + private Profile profile = null; + + public Profile getProfileObject() { + if (profile == null) + try { + profile = new Profile(new JSONObject(profileJson)); + } catch (JSONException e) { + e.printStackTrace(); + } + return profile; + } + + 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(System.currentTimeMillis()); + } + + @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 toString() { + 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 d5a6c01235..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/db/TempBasal.java +++ /dev/null @@ -1,301 +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.interfaces.InsulinInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -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(long time) { - IobTotal result = new IobTotal(time); - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); - - if (profile == null) - return result; - - 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 date = (long) (timeStart.getTime() + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000); - - Double basalRate = profile.getBasal(NSProfile.secondsFromMidnight(date)); - - if (basalRate == null) - continue; - if (isExtended) { - netBasalRate = this.absolute; - } else { - if (this.isAbsolute) { - netBasalRate = this.absolute - basalRate; - } else { - netBasalRate = (this.percent - 100) / 100d * basalRate; - } - } - - if (date > dia_ago && date <= time) { - double tempBolusSize = netBasalRate * tempBolusSpacing / 60d; - netBasalAmount += tempBolusSize; - - Treatment tempBolusPart = new Treatment(insulinInterface); - tempBolusPart.insulin = tempBolusSize; - tempBolusPart.created_at = new Date(date); - - Iob aIOB = insulinInterface.iobCalc(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 IobTotal old_iobCalc(long time) { - IobTotal result = new IobTotal(time); - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); - - if (profile == null) - return result; - - Double basalRate = profile.getBasal(NSProfile.secondsFromMidnight(time)); - - if (basalRate == null) - return result; - - int realDuration = getDurationToTime(time); - - 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(insulinInterface); - tempBolusPart.insulin = tempBolusSize; - Long date = this.timeStart.getTime() + j * tempBolusSpacing * 60 * 1000; - tempBolusPart.created_at = new Date(date); - - Iob aIOB = insulinInterface.iobCalc(tempBolusPart, time, profile.getDia()); - result.basaliob += aIOB.iobContrib; - result.activity += aIOB.activityContrib; - Double dia_ago = time - profile.getDia() * 60 * 60 * 1000; - if (date > dia_ago && date <= time) { - result.netbasalinsulin += tempBolusPart.insulin; - if (tempBolusPart.insulin > 0) { - result.hightempinsulin += tempBolusPart.insulin; - } - } - } - } - } - return result; - } -*/ - - // Determine end of basal - public long getTimeEnd() { - long tempBasalTimePlannedEnd = getPlannedTimeEnd(); - long now = new Date().getTime(); - - if (timeEnd != null && timeEnd.getTime() < tempBasalTimePlannedEnd) { - tempBasalTimePlannedEnd = timeEnd.getTime(); - } - - if (now < tempBasalTimePlannedEnd) - tempBasalTimePlannedEnd = now; - - return tempBasalTimePlannedEnd; - } - - public long getPlannedTimeEnd() { - return timeStart.getTime() + 60 * 1_000 * duration; - } - - public int getRealDuration() { - long msecs = getTimeEnd() - timeStart.getTime(); - return Math.round(msecs / 60f / 1000); - } - - public int getDurationToTime(long time) { - long endTime = Math.min(time, getTimeEnd()); - long msecs = endTime - 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() - 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() > 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..3bbdcbc06c 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 (!Objects.equals(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(System.currentTimeMillis()); + } + + @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..3c8f95f5af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/db/TemporaryBasal.java @@ -0,0 +1,375 @@ +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.R; +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; +import info.nightscout.utils.SP; + +/** + * 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; + + public boolean isFakeExtended = false; + + @DatabaseField + public int percentRate = 0; + @DatabaseField + public double absoluteRate = 0d; + + public double netExtendedRate = 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.isFakeExtended = true; + this.netExtendedRate = extendedBolus.absoluteRate(); + 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 (netExtendedRate != other.netExtendedRate) + return false; + if (isFakeExtended != other.isFakeExtended) + 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; + isFakeExtended = t.isFakeExtended; + netExtendedRate = t.netExtendedRate; + } + + // -------- 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(System.currentTimeMillis()); + } + + @Override + public boolean isEndingEvent() { + return durationInMinutes == 0; + } + + // -------- Interval interface end --------- + + public IobTotal iobCalc(long time) { + + if(isFakeExtended){ + log.error("iobCalc should only be called on Extended boluses separately"); + return new IobTotal(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 = profile.getDia(); + double dia_ago = time - dia * 60 * 60 * 1000; + int aboutFiveMinIntervals = (int) Math.ceil(realDuration / 5d); + double tempBolusSpacing = realDuration / aboutFiveMinIntervals; + + for (long j = 0L; j < aboutFiveMinIntervals; j++) { + // find middle of the interval + long calcdate = (long) (date + j * tempBolusSpacing * 60 * 1000 + 0.5d * tempBolusSpacing * 60 * 1000); + + Double basalRate = profile.getBasal(calcdate); + + 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(); + tempBolusPart.insulin = tempBolusSize; + tempBolusPart.date = calcdate; + + Iob aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia); + result.basaliob += aIOB.iobContrib; + result.activity += aIOB.activityContrib; + result.netbasalinsulin += tempBolusPart.insulin; + if (tempBolusPart.insulin > 0) { + result.hightempinsulin += tempBolusPart.insulin; + } + } + result.netRatio = netBasalRate; // ratio at the end of interval + } + } + result.netInsulin = netBasalAmount; + return result; + } + + public int getRealDuration() { + return getDurationToTime(System.currentTimeMillis()); + } + + 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() - System.currentTimeMillis()) / 1000f / 60; + return (remainingMin < 0) ? 0 : Math.round(remainingMin); + } + + public double tempBasalConvertedToAbsolute(long time) { + if(isFakeExtended){ + return MainApp.getConfigBuilder().getProfile(time).getBasal(time) + netExtendedRate; + } else 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 + + ", isFakeExtended=" + isFakeExtended + + ", netExtendedRate=" + netExtendedRate + + '}'; + } + + public String toStringFull() { + if(isFakeExtended){ + + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double currentBasalRate = profile.getBasal(); + double rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate); + return getCalcuatedPercentageIfNeeded() + DecimalFormatter.to2Decimal(rate) + "U/h ("+DecimalFormatter.to2Decimal(netExtendedRate)+"E) @" + + DateUtil.timeString(date) + + " " + getRealDuration() + "/" + durationInMinutes + "'"; + } else if (isAbsolute) { + return DecimalFormatter.to2Decimal(absoluteRate) + "U/h @" + + DateUtil.timeString(date) + + " " + getRealDuration() + "/" + durationInMinutes + "'"; + } else { // percent + return percentRate + "% @" + + DateUtil.timeString(date) + + " " + getRealDuration() + "/" + durationInMinutes + "'"; + } + } + + public String toStringShort() { + if (isAbsolute || isFakeExtended) { + + double rate = 0d; + if (isFakeExtended) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double currentBasalRate = profile.getBasal(); + rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate); + } else if (isAbsolute){ + rate = absoluteRate; + } + + if(SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)){ + Profile profile = MainApp.getConfigBuilder().getProfile(); + if(profile != null) { + double basal = profile.getBasal(); + if(basal != 0){ + return Math.round(rate*100d/basal) + "% "; + } + } + } + return DecimalFormatter.to2Decimal(rate) + "U/h "; + } else { // percent + return percentRate + "% "; + } + } + + private String getCalcuatedPercentageIfNeeded(){ + if (isAbsolute || isFakeExtended) { + + double rate = 0d; + if (isFakeExtended) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double currentBasalRate = profile.getBasal(); + rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate); + } else if (isAbsolute){ + rate = absoluteRate; + } + + if(SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false) && SP.getBoolean(R.string.key_danar_useextended, false)){ + Profile profile = MainApp.getConfigBuilder().getProfile(); + if(profile != null) { + double basal = profile.getBasal(); + if(basal != 0){ + return Math.round(rate*100d/basal) + "% "; + } + } + } + } + return ""; + } + + public String toStringVeryShort() { + if (isAbsolute || isFakeExtended) { + + double rate = 0d; + if (isFakeExtended) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double currentBasalRate = profile.getBasal(); + rate = (currentBasalRate == null)?0d:(currentBasalRate+netExtendedRate); + } else if (isAbsolute){ + rate = absoluteRate; + } + return DecimalFormatter.to2Decimal(rate) + "U/h "; + } else { // percent + return percentRate + "% "; + } + } + +} 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 dc933e59ee..9de76e6bf8 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/Treatment.java +++ b/app/src/main/java/info/nightscout/androidaps/db/Treatment.java @@ -1,15 +1,14 @@ 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; @@ -17,7 +16,7 @@ import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; 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; @@ -25,81 +24,95 @@ 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 int insulinType = InsulinInterface.FASTACTINGINSULIN; - - @DatabaseField - public double dia = Constants.defaultDIA; - - @DatabaseField - public Double carbs = 0d; - + public double carbs = 0d; @DatabaseField public boolean mealBolus = true; // true for meal bolus , false for correction bolus + @DatabaseField + public boolean isSMB = false; + + @DatabaseField + public int insulinInterfaceID = InsulinInterface.FASTACTINGINSULIN; // currently unused, will be used in the future + @DatabaseField + public double dia = Constants.defaultDIA; // currently unused, will be used in the future public Treatment() { - InsulinInterface insulin = MainApp.getConfigBuilder().getActiveInsulin(); - if (insulin != null) { - insulinType = insulin.getId(); - dia = insulin.getDia(); - } else { - insulinType = InsulinInterface.FASTACTINGINSULIN; - dia = Constants.defaultDIA; - } } - public Treatment(InsulinInterface insulin) { - insulinType = insulin.getId(); - dia = insulin.getDia(); - } - - 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; - } - - public long getMillisecondsFromStart() { - return new Date().getTime() - created_at.getTime(); - } - - 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 + + ", isSMB= " + isSMB + + ", _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 (isSMB != other.isSMB) + 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; + isSMB = t.isSMB; + } + + // ----------------- DataPointInterface -------------------- @Override public double getX() { - return timeIndex; + return date; } // default when no sgv around available @@ -115,36 +128,45 @@ 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() { + if (isValid) + return Color.CYAN; + else + return MainApp.instance().getResources().getColor(android.R.color.holo_red_light); + } + + @Override + public void setY(double y) { + yValue = y; + } + + // ----------------- DataPointInterface end -------------------- + + public Iob iobCalc(long time, double dia) { + if (!isValid) + return new Iob(); + + InsulinInterface 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 b3750f59c8..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,16 +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 String from = ""; - - public EventNewBasalProfile(NSProfile newProfile, String from) { - newNSProfile = newProfile; - this.from = from; - } } 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/EventRefreshGui.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java index cb57c361fc..f20dfb9329 100644 --- a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshGui.java @@ -4,15 +4,4 @@ package info.nightscout.androidaps.events; * Created by mike on 13.06.2016. */ public class EventRefreshGui { - - public boolean isSwitchToLast() { - return switchToLast; - } - - private final boolean switchToLast; - - public EventRefreshGui(boolean switchToLast){ - this.switchToLast = switchToLast; - } - } diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java new file mode 100644 index 0000000000..bf14f5f585 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventRefreshOverview.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 16.06.2017. + */ + +public class EventRefreshOverview { + public String from; + + public EventRefreshOverview(String from) { + this.from = from; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java new file mode 100644 index 0000000000..20073a7cf0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/events/EventReloadProfileSwitchData.java @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.events; + +/** + * Created by mike on 12.06.2017. + */ + +public class EventReloadProfileSwitchData { +} 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/DanaRInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java new file mode 100644 index 0000000000..abd1d8e304 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/DanaRInterface.java @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.interfaces; + +/** + * Created by mike on 12.06.2017. + */ + +public interface DanaRInterface { + boolean loadHistory(byte type); +} diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java index 6b50178652..0803f65373 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/InsulinInterface.java @@ -12,10 +12,14 @@ import info.nightscout.androidaps.db.Treatment; public interface InsulinInterface { final int FASTACTINGINSULIN = 0; final int FASTACTINGINSULINPROLONGED = 1; + final int OREF_RAPID_ACTING = 2; + final int OREF_ULTRA_RAPID_ACTING = 3; + final int OREF_FREE_PEAK = 4; + int getId(); String getFriendlyName(); String getComment(); double getDia(); - public Iob iobCalc(Treatment treatment, long time, Double dia); + 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 efbd51ea72..bf5e66f2a1 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -8,7 +8,7 @@ import java.util.Date; public interface PluginBase { int GENERAL = 1; int TREATMENT = 2; - int TEMPBASAL = 3; + int SENSITIVITY = 3; int PROFILE = 4; int APS = 5; int PUMP = 6; 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..e3b368fe86 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,14 @@ 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 getUnits(); + 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 b9c7e18650..2db7564de7 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,32 +17,26 @@ 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(InsulinInterface insulinType, Double insulin, Integer carbs, Context context); + PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo); void stopBolusDelivering(); - PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes); + PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force); PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes); PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes); - PumpEnactResult cancelTempBasal(); + //some pumps might set a very short temp close to 100% as cancelling a temp can be noisy + //when the cancel request is requested by the user (forced), the pump should always do a real cancel + PumpEnactResult cancelTempBasal(boolean force); PumpEnactResult cancelExtendedBolus(); // Status to be passed to NS @@ -56,4 +48,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/SensitivityInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java new file mode 100644 index 0000000000..deb649c21f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/SensitivityInterface.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.interfaces; + +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; + +/** + * Created by mike on 24.06.2017. + */ + +public interface SensitivityInterface { + AutosensResult detectSensitivity(long fromTime, long toTime); +} 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 9ecacf9e22..5e8b4e52e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/TreatmentsInterface.java @@ -2,19 +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.Intervals; +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 getTreatments5MinBack(long time); + + 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(); + Intervals getTemporaryBasalsFromHistory(); + + boolean isInHistoryExtendedBoluslInProgress(); + ExtendedBolus getExtendedBolusFromHistory(long time); + Intervals getExtendedBolusesFromHistory(); + + boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus); + + boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo); + + TempTarget getTempTargetFromHistory(long time); + Intervals 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 582feb89a6..849f875567 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,23 +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 info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventInitializationChanged; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRefreshOverview; +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.Actions.dialogs.NewExtendedBolusDialog; import info.nightscout.androidaps.plugins.Actions.dialogs.NewTempBasalDialog; +import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; /** * A simple {@link Fragment} subclass. */ -public class ActionsFragment extends Fragment implements View.OnClickListener { +public class ActionsFragment extends SubscriberFragment implements View.OnClickListener { static ActionsPlugin actionsPlugin = new ActionsPlugin(); @@ -37,10 +48,21 @@ public class ActionsFragment extends Fragment implements View.OnClickListener { Button profileSwitch; Button tempTarget; Button extendedBolus; + Button extendedBolusCancel; Button tempBasal; + Button tempBasalCancel; Button fill; + private static Handler sHandler; + private static HandlerThread sHandlerThread; + public ActionsFragment() { + super(); + if (sHandlerThread == null) { + sHandlerThread = new HandlerThread(ActionsFragment.class.getSimpleName()); + sHandlerThread.start(); + sHandler = new Handler(sHandlerThread.getLooper()); + } } @@ -52,63 +74,103 @@ public class ActionsFragment extends Fragment implements View.OnClickListener { 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); + tempBasalCancel = (Button) view.findViewById(R.id.actions_canceltempbasal); fill = (Button) view.findViewById(R.id.actions_fill); profileSwitch.setOnClickListener(this); tempTarget.setOnClickListener(this); extendedBolus.setOnClickListener(this); + extendedBolusCancel.setOnClickListener(this); tempBasal.setOnClickListener(this); + tempBasalCancel.setOnClickListener(this); fill.setOnClickListener(this); - updateGUIIfVisible(); + 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 EventInitializationChanged ev) { - updateGUIIfVisible(); + updateGUI(); } @Subscribe - public void onStatusEvent(final EventRefreshGui ev) { - updateGUIIfVisible(); + public void onStatusEvent(final EventRefreshOverview ev) { + updateGUI(); } - void updateGUIIfVisible() { + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventTempBasalChange ev) { + updateGUI(); + } + + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) + if (MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() == null) { + tempTarget.setVisibility(View.GONE); + profileSwitch.setVisibility(View.GONE); + extendedBolus.setVisibility(View.GONE); + extendedBolusCancel.setVisibility(View.GONE); + tempBasal.setVisibility(View.GONE); + tempBasalCancel.setVisibility(View.GONE); + fill.setVisibility(View.GONE); + 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().isFakingTempsByExtendedBoluses()) { extendedBolus.setVisibility(View.GONE); - else - extendedBolus.setVisibility(View.VISIBLE); - if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) + extendedBolusCancel.setVisibility(View.GONE); + } else { + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolus.setVisibility(View.GONE); + extendedBolusCancel.setVisibility(View.VISIBLE); + ExtendedBolus running = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + extendedBolusCancel.setText(MainApp.instance().getString(R.string.cancel) + " " + running.toString()); + } else { + extendedBolus.setVisibility(View.VISIBLE); + extendedBolusCancel.setVisibility(View.GONE); + } + } + + + if (!MainApp.getConfigBuilder().getPumpDescription().isTempBasalCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { tempBasal.setVisibility(View.GONE); - else - tempBasal.setVisibility(View.VISIBLE); + tempBasalCancel.setVisibility(View.GONE); + } else { + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + tempBasal.setVisibility(View.GONE); + tempBasalCancel.setVisibility(View.VISIBLE); + final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); + tempBasalCancel.setText(MainApp.instance().getString(R.string.cancel) + "\n" + activeTemp.toStringShort()); + } else { + tempBasal.setVisibility(View.VISIBLE); + tempBasalCancel.setVisibility(View.GONE); + } + } + if (!MainApp.getConfigBuilder().getPumpDescription().isRefillingCapable || !MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) fill.setVisibility(View.GONE); else fill.setVisibility(View.VISIBLE); + if (!Config.APS) tempTarget.setVisibility(View.GONE); else @@ -121,25 +183,48 @@ public class ActionsFragment extends Fragment implements View.OnClickListener { @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(); - 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 profileswitch = CareportalFragment.profileswitch; profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch); + newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.show(manager, "NewNSTreatmentDialog"); break; case R.id.actions_temptarget: NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); - final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true); + final OptionsToShow temptarget = CareportalFragment.temptarget; temptarget.executeTempTarget = true; - newTTDialog.setOptions(temptarget); + newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget); newTTDialog.show(manager, "NewNSTreatmentDialog"); break; case R.id.actions_extendedbolus: NewExtendedBolusDialog newExtendedDialog = new NewExtendedBolusDialog(); newExtendedDialog.show(manager, "NewExtendedDialog"); break; + case R.id.actions_extendedbolus_cancel: + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + sHandler.post(new Runnable() { + @Override + public void run() { + pump.cancelExtendedBolus(); + Answers.getInstance().logCustom(new CustomEvent("CancelExtended")); + } + }); + } + break; + case R.id.actions_canceltempbasal: + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + sHandler.post(new Runnable() { + @Override + public void run() { + pump.cancelTempBasal(true); + Answers.getInstance().logCustom(new CustomEvent("CancelTemp")); + } + }); + } + 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/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java index dd623c38e9..8a4d4001cb 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; @@ -67,8 +69,8 @@ public class FillDialog extends DialogFragment implements OnClickListener { insulin = (TextView) view.findViewById(R.id.treatments_newtreatment_insulinamount); Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); - - editInsulin = new PlusMinusEditText(view, R.id.treatments_newtreatment_insulinamount, R.id.treatments_newtreatment_insulinamount_plus, R.id.treatments_newtreatment_insulinamount_minus, 0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false); + double bolusstep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; + editInsulin = new PlusMinusEditText(view, R.id.treatments_newtreatment_insulinamount, R.id.treatments_newtreatment_insulinamount_plus, R.id.treatments_newtreatment_insulinamount_minus, 0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false); //setup preset buttons Button button1 = (Button) view.findViewById(R.id.fill_preset_button1); @@ -159,7 +161,12 @@ public class FillDialog extends DialogFragment implements OnClickListener { mHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = pump.deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), finalInsulinAfterConstraints, 0, context, false); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) + PumpEnactResult result = pump.deliverTreatment(detailedBolusInfo); if (!result.success) { 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 6930a0de21..9582dced87 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 @@ -11,45 +11,39 @@ 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.NumberPicker; 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; + LinearLayout typeSelectorLayout; LinearLayout percentLayout; LinearLayout absoluteLayout; - PlusMinusEditText basalPercentPM; - PlusMinusEditText basalAbsolutePM; + NumberPicker basalPercent; + NumberPicker basalAbsolute; + NumberPicker duration; Handler mHandler; public static HandlerThread mHandlerThread; @@ -66,75 +60,85 @@ 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 = (LinearLayout) 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 = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput); + double maxTempPercent = pumpDescription.maxTempPercent; + double tempPercentStep = pumpDescription.tempPercentStep; + basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true); - absoluteLayout.setVisibility(View.GONE); - okButton.setOnClickListener(this); + Profile profile = MainApp.getConfigBuilder().getProfile(); + Double currentBasal = profile != null ? profile.getBasal() : 0d; + basalAbsolute = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput); + basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true); + + double tempDurationStep = pumpDescription.tempDurationStep; + double tempMaxDuration = pumpDescription.tempMaxDuration; + duration = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_duration); + duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false); + + 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; } - @Override - public void onResume() { - super.onResume(); - if (getDialog() != null) - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - @Override public void onClick(View 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(); @@ -151,7 +155,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi if (setAsPercent) { result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes); } else { - result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes); + result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes, false); } if (!result.success) { if (context instanceof Activity) { @@ -178,6 +182,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 7c603ecaed..6ddda8cd68 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,20 +1,38 @@ 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.text.Layout; 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.BuildConfig; +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.Overview.OverviewFragment; -public class CareportalFragment extends Fragment implements View.OnClickListener { +public class CareportalFragment extends SubscriberFragment implements View.OnClickListener { static CareportalPlugin careportalPlugin; + TextView iage; + TextView cage; + TextView sage; + TextView pbage; + + View statsLayout; + static public CareportalPlugin getPlugin() { if (careportalPlugin == null) { careportalPlugin = new CareportalPlugin(); @@ -23,25 +41,26 @@ public class CareportalFragment extends Fragment implements View.OnClickListener } // 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); + public static final OptionsToShow bgcheck = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck, true, true, true, false, false, false, false, false, false, false); + public static final OptionsToShow snackbolus = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus, true, true, true, true, false, false, false, false, false, false); + public static final OptionsToShow mealbolus = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus, true, true, true, true, false, false, false, false, false, false); + public static final OptionsToShow correctionbolus = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus, true, true, true, true, false, false, false, false, false, false); + public static final OptionsToShow carbcorrection = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection, true, false, true, false, false, false, false, false, false, false); + public static final OptionsToShow combobolus = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus, true, true, true, true, true, false, false, false, true, false); + public static final OptionsToShow announcement = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow note = new OptionsToShow(R.id.careportal_note, R.string.careportal_note, true, false, false, false, true, false, false, false, false, false); + public static final OptionsToShow question = new OptionsToShow(R.id.careportal_question, R.string.careportal_question, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow exercise = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise, false, false, false, false, true, false, false, false, false, false); + public static final OptionsToShow sitechange = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange, true, true, false, false, false, false, false, false, false, false); + public static final OptionsToShow sensorstart = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow sensorchange = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow insulinchange = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow pumpbatterychange = new OptionsToShow(R.id.careportal_pumpbatterychange, R.string.careportal_pumpbatterychange, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow tempbasalstart = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart, true, false, false, false, true, true, true, false, false, false); + public static final OptionsToShow tempbasalend = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend, true, false, false, false, false, false, false, false, false, false); + public static final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, true, false, false, true, false, false); + public static final OptionsToShow openapsoffline = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline, false, false, false, false, true, false, false, false, false, false); + public 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, @@ -57,6 +76,7 @@ public class CareportalFragment extends Fragment implements View.OnClickListener 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); @@ -67,70 +87,90 @@ public class CareportalFragment extends Fragment implements View.OnClickListener 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); + + statsLayout = (View) view.findViewById(R.id.careportal_stats); + + if (BuildConfig.NSCLIENTOLNY) + statsLayout.setVisibility(View.GONE); // visible on overview + + 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); + newDialog.setOptions(bgcheck, R.string.careportal_bgcheck); break; case R.id.careportal_announcement: - newDialog.setOptions(announcement); + newDialog.setOptions(announcement, R.string.careportal_announcement); break; case R.id.careportal_cgmsensorinsert: - newDialog.setOptions(sensorchange); + newDialog.setOptions(sensorchange, R.string.careportal_cgmsensorinsert); break; case R.id.careportal_cgmsensorstart: - newDialog.setOptions(sensorstart); + newDialog.setOptions(sensorstart, R.string.careportal_cgmsensorstart); break; case R.id.careportal_combobolus: - newDialog.setOptions(combobolus); + newDialog.setOptions(combobolus, R.string.careportal_combobolus); break; case R.id.careportal_correctionbolus: - newDialog.setOptions(correctionbolus); + newDialog.setOptions(correctionbolus, R.string.careportal_correctionbolus); break; case R.id.careportal_carbscorrection: - newDialog.setOptions(carbcorrection); + newDialog.setOptions(carbcorrection, R.string.careportal_carbscorrection); break; case R.id.careportal_exercise: - newDialog.setOptions(exercise); + newDialog.setOptions(exercise, R.string.careportal_exercise); break; case R.id.careportal_insulincartridgechange: - newDialog.setOptions(insulinchange); + newDialog.setOptions(insulinchange, R.string.careportal_insulincartridgechange); + break; + case R.id.careportal_pumpbatterychange: + newDialog.setOptions(pumpbatterychange, R.string.careportal_pumpbatterychange); break; case R.id.careportal_mealbolus: - newDialog.setOptions(mealbolus); + newDialog.setOptions(mealbolus, R.string.careportal_mealbolus); break; case R.id.careportal_note: - newDialog.setOptions(note); + newDialog.setOptions(note, R.string.careportal_note); break; case R.id.careportal_profileswitch: - newDialog.setOptions(profileswitch); + profileswitch.executeProfileSwitch = false; + newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); break; case R.id.careportal_pumpsitechange: - newDialog.setOptions(sitechange); + newDialog.setOptions(sitechange, R.string.careportal_pumpsitechange); break; case R.id.careportal_question: - newDialog.setOptions(question); + newDialog.setOptions(question, R.string.careportal_question); break; case R.id.careportal_snackbolus: - newDialog.setOptions(snackbolus); + newDialog.setOptions(snackbolus, R.string.careportal_snackbolus); break; case R.id.careportal_tempbasalstart: - newDialog.setOptions(tempbasalstart); + newDialog.setOptions(tempbasalstart, R.string.careportal_tempbasalstart); break; case R.id.careportal_tempbasalend: - newDialog.setOptions(tempbasalend); + newDialog.setOptions(tempbasalend, R.string.careportal_tempbasalend); break; case R.id.careportal_openapsoffline: - newDialog.setOptions(openapsoffline); + newDialog.setOptions(openapsoffline, R.string.careportal_openapsoffline); break; case R.id.careportal_temporarytarget: - newDialog.setOptions(temptarget); + temptarget.executeTempTarget = false; + newDialog.setOptions(temptarget, R.string.careportal_temporarytarget); break; default: newDialog = null; @@ -139,4 +179,45 @@ public class CareportalFragment extends Fragment implements View.OnClickListener newDialog.show(manager, "NewNSTreatmentDialog"); } + @Subscribe + public void onStatusEvent(final EventCareportalEventChange c) { + updateGUI(); + } + + @Override + protected void updateGUI() { + Activity activity = getActivity(); + updateAge(activity, sage, iage, cage, pbage); + } + + 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; + String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.sResources.getString(R.string.notavailable); + if (sage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE); + sage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + } + if (iage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); + iage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + } + if (cage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); + cage.setText(careportalEvent != null ? careportalEvent.age() : notavailable); + } + if (pbage != null) { + careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.PUMPBATTERYCHANGE); + pbage.setText(careportalEvent != null ? careportalEvent.age() : 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 e6981083d0..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; @@ -57,7 +58,7 @@ public class CareportalPlugin implements PluginBase { @Override public boolean showInList(int type) { - return true; + return !Config.NSCLIENT; } @Override 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 9c89fdd948..b10ab5dab8 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; @@ -16,18 +15,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.Button; 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; @@ -37,7 +33,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; @@ -47,73 +42,68 @@ 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.Profile; +import info.nightscout.androidaps.data.ProfileStore; +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.ProfileCircadianPercentage.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.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; import info.nightscout.utils.DateUtil; -import info.nightscout.utils.PlusMinusEditText; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.NumberPicker; 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; + private static String event; - NSProfile profile; + Profile profile; + ProfileStore profileStore; String units; - RelativeLayout layoutBg; + TextView eventTypeText; + LinearLayout layoutBg; LinearLayout layoutBgSource; - RelativeLayout layoutInsulin; - RelativeLayout layoutCarbs; - RelativeLayout layoutSplit; - RelativeLayout layoutDuration; - RelativeLayout layoutPercent; - RelativeLayout layoutAbsolute; - RelativeLayout layoutCarbTime; - RelativeLayout layoutProfile; + LinearLayout layoutInsulin; + LinearLayout layoutCarbs; + LinearLayout layoutSplit; + LinearLayout layoutDuration; + LinearLayout layoutPercent; + LinearLayout layoutAbsolute; + LinearLayout layoutCarbTime; + LinearLayout layoutProfile; LinearLayout layoutTempTarget; - Button dateButton; - Button timeButton; - Button okButton; - Button cancelButton; + TextView dateButton; + TextView timeButton; TextView bgUnitsView; RadioButton meterRadioButton; RadioButton sensorRadioButton; RadioButton otherRadioButton; EditText notesEdit; - EditText bgInputEdit; - EditText insulinEdit; - EditText carbsEdit; - EditText percentEdit; - EditText absoluteEdit; - EditText durationeEdit; - EditText carbTimeEdit; - EditText splitEdit; Spinner profileSpinner; - EditText low; - EditText high; Spinner reasonSpinner; - PlusMinusEditText editBg; - PlusMinusEditText editCarbs; - PlusMinusEditText editInsulin; - PlusMinusEditText editSplit; - PlusMinusEditText editDuration; - PlusMinusEditText editPercent; - PlusMinusEditText editAbsolute; - PlusMinusEditText editCarbTime; + NumberPicker editBg; + NumberPicker editCarbs; + NumberPicker editInsulin; + NumberPicker editSplit; + NumberPicker editDuration; + NumberPicker editPercent; + NumberPicker editAbsolute; + NumberPicker editCarbTime; + NumberPicker editTemptarget; Date eventTime; @@ -121,8 +111,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick private static HandlerThread sHandlerThread; - public void setOptions(OptionsToShow options) { + public void setOptions(OptionsToShow options, int event) { this.options = options; + this.event = MainApp.sResources.getString(event); } public NewNSTreatmentDialog() { @@ -136,10 +127,16 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick @Override public void onAttach(Activity activity) { - context = (FragmentActivity) activity; + context = activity; super.onAttach(activity); } + @Override + public void onDetach() { + super.onDetach(); + this.context = null; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -147,29 +144,118 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick setStyle(DialogFragment.STYLE_NORMAL, getTheme()); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); - layoutBg = (RelativeLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout); + layoutBg = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout); layoutBgSource = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bgsource_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); + 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); layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout); + eventTypeText = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventtype); + eventTypeText.setText(event); bgUnitsView = (TextView) view.findViewById(R.id.careportal_newnstreatment_bgunits); meterRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_meter); sensorRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_sensor); otherRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_other); profileSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_profile); - bgInputEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_bginput); - insulinEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_insulininput); - carbsEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_carbsinput); - percentEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_percentinput); - percentEdit.addTextChangedListener(new TextWatcher() { + notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes); + + reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason); + + eventTime = new Date(); + dateButton = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventdate); + timeButton = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventtime); + dateButton.setText(DateUtil.dateString(eventTime)); + timeButton.setText(DateUtil.timeString(eventTime)); + dateButton.setOnClickListener(this); + timeButton.setOnClickListener(this); + + view.findViewById(R.id.ok).setOnClickListener(this); + view.findViewById(R.id.cancel).setOnClickListener(this); + + // profile + profile = MainApp.getConfigBuilder().getProfile(); + profileStore = ConfigBuilderPlugin.getActiveProfileInterface().getProfile(); + ArrayList profileList; + units = profile != null ? profile.getUnits() : Constants.MGDL; + profileList = profileStore.getProfileList(); + ArrayAdapter adapter = new ArrayAdapter(getContext(), + 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(MainApp.getConfigBuilder().getProfileName())) + profileSpinner.setSelection(p); + } + + // temp target + ArrayList reasonList = new ArrayList(); + reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); + reasonList.add(MainApp.sResources.getString(R.string.activity)); + reasonList.add(MainApp.sResources.getString(R.string.manual)); + ArrayAdapter adapterReason = new ArrayAdapter(getContext(), + R.layout.spinner_centered, reasonList); + reasonSpinner.setAdapter(adapterReason); + + // bg + bgUnitsView.setText(units); + + Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile != null ? profile.getUnits() : Constants.MGDL); + editBg = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_bginput); + editTemptarget = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_temptarget); + if (profile == null) { + editBg.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false); + editTemptarget.setParams(bg, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false); + } else if (profile.getUnits().equals(Constants.MMOL)) { + editBg.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false); + editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false); + } else { + editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false); + editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false); + } + editBg.addTextChangedListener(new TextWatcher() { + public void afterTextChanged(Editable s) { + } + + 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); + } + }); + + sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()); + editBg.setValue(bg); + } + }); + + Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); + editCarbs = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbsinput); + editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); + + Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); + editInsulin = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_insulininput); + editInsulin.setParams(0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false); + + editSplit = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_splitinput); + editSplit.setParams(100d, 0d, 100d, 5d, new DecimalFormat("0"), true); + editDuration = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_durationinput); + editDuration.setParams(0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false); + + Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit); + editPercent = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentinput); + editPercent.setParams(0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true); + editPercent.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { } @@ -186,8 +272,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick layoutAbsolute.setVisibility(View.GONE); } }); - absoluteEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_absoluteinput); - absoluteEdit.addTextChangedListener(new TextWatcher() { + + Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit); + editAbsolute = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_absoluteinput); + editAbsolute.setParams(0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true); + editAbsolute.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { } @@ -204,115 +293,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick layoutAbsolute.setVisibility(View.VISIBLE); } }); - durationeEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_durationinput); - carbTimeEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput); - notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes); - splitEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_splitinput); - reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason); - low = (EditText) view.findViewById(R.id.careportal_temptarget_low); - high = (EditText) view.findViewById(R.id.careportal_temptarget_high); + editCarbTime = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput); + editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false); - eventTime = new Date(); - dateButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventdate); - timeButton = (Button) view.findViewById(R.id.careportal_newnstreatment_eventtime); - dateButton.setText(DateUtil.dateString(eventTime)); - timeButton.setText(DateUtil.timeString(eventTime)); - dateButton.setOnClickListener(this); - timeButton.setOnClickListener(this); - - 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(); - 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(); - } - ArrayAdapter adapter = new ArrayAdapter(getContext(), - 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); - } - } - - // temp target - ArrayList reasonList = new ArrayList(); - reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); - reasonList.add(MainApp.sResources.getString(R.string.activity)); - reasonList.add(MainApp.sResources.getString(R.string.manual)); - ArrayAdapter adapterReason = new ArrayAdapter(getContext(), - R.layout.spinner_centered, reasonList); - reasonSpinner.setAdapter(adapterReason); - - // bg - bgUnitsView.setText(units); - - // Set BG if not old -// BgReading lastBg = MainApp.getDbHelper().lastBg(); -// Double lastBgValue = 0d; -// if (lastBg != null) { -// lastBgValue = lastBg.valueToUnits(units); -// sensorRadioButton.setChecked(true); -// } else { -// meterRadioButton.setChecked(true); -// } - - Double bg = NSProfile.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)) - editBg = new PlusMinusEditText(view, R.id.careportal_newnstreatment_bginput, R.id.careportal_newnstreatment_bg_plus, R.id.careportal_newnstreatment_bg_minus, bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false); - else - 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 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); - } - }); - 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()); - editBg.setValue(bg); - } - }); - - Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); - editCarbs = new PlusMinusEditText(view, R.id.careportal_newnstreatment_carbsinput, R.id.careportal_newnstreatment_carbs_plus, R.id.careportal_newnstreatment_carbs_minus, 0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); - - Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); - editInsulin = new PlusMinusEditText(view, R.id.careportal_newnstreatment_insulininput, R.id.careportal_newnstreatment_insulin_plus, R.id.careportal_newnstreatment_insulin_minus, 0d, 0d, maxInsulin, 0.05d, new DecimalFormat("0.00"), false); - - editSplit = new PlusMinusEditText(view, R.id.careportal_newnstreatment_splitinput, R.id.careportal_newnstreatment_split_plus, R.id.careportal_newnstreatment_split_minus, 100d, 0d, 100d, 5d, new DecimalFormat("0"), true); - editDuration = new PlusMinusEditText(view, R.id.careportal_newnstreatment_durationinput, R.id.careportal_newnstreatment_duration_plus, R.id.careportal_newnstreatment_duration_minus, 0d, 0d, 24 * 60d, 10d, new DecimalFormat("0"), false); - - Integer maxPercent = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalPercentOnlyForCheckLimit); - editPercent = new PlusMinusEditText(view, R.id.careportal_newnstreatment_percentinput, R.id.careportal_newnstreatment_percent_plus, R.id.careportal_newnstreatment_percent_minus, 0d, 0d, (double) maxPercent, 5d, new DecimalFormat("0"), true); - - Double maxAbsolute = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit); - editAbsolute = new PlusMinusEditText(view, R.id.careportal_newnstreatment_absoluteinput, R.id.careportal_newnstreatment_absolute_plus, R.id.careportal_newnstreatment_absolute_minus, 0d, 0d, maxAbsolute, 0.05d, new DecimalFormat("0.00"), true); - - editCarbTime = new PlusMinusEditText(view, R.id.careportal_newnstreatment_carbtimeinput, R.id.careportal_newnstreatment_carbtime_plus, R.id.careportal_newnstreatment_carbtime_minus, 0d, -60d, 60d, 5d, new DecimalFormat("0"), false); showOrHide(layoutBg, options.bg); showOrHide(layoutBgSource, options.bg); @@ -329,13 +313,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick return view; } - @Override - public void onResume() { - super.onResume(); - if (getDialog() != null) - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - @Override public void onClick(View view) { Calendar calendar = Calendar.getInstance(); @@ -353,7 +330,6 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick dpd.show(context.getFragmentManager(), "Datepickerdialog"); break; case R.id.careportal_newnstreatment_eventtime: - android.text.format.DateFormat df = new android.text.format.DateFormat(); TimePickerDialog tpd = TimePickerDialog.newInstance( this, calendar.get(Calendar.HOUR_OF_DAY), @@ -404,22 +380,22 @@ 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"); break; 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("splitNow", SafeParse.stringToDouble(editSplit.getText())); + data.put("splitExt", 100 - SafeParse.stringToDouble(editSplit.getText())); + data.put("eventType", CareportalEvent.COMBOBOLUS); break; case R.id.careportal_correctionbolus: data.put("eventType", "Correction Bolus"); @@ -428,78 +404,82 @@ 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) - data.put("targetBottom", SafeParse.stringToDouble(low.getText().toString())); - if (SafeParse.stringToDouble(high.getText().toString()) != 0d) - data.put("targetTop", SafeParse.stringToDouble(high.getText().toString())); + if (SafeParse.stringToDouble(editTemptarget.getText()) != 0d) { + data.put("targetBottom", SafeParse.stringToDouble(editTemptarget.getText())); + data.put("targetTop", SafeParse.stringToDouble(editTemptarget.getText())); + } allowZeroDuration = true; break; } - if (SafeParse.stringToDouble(bgInputEdit.getText().toString()) != 0d) { - data.put("glucose", SafeParse.stringToDouble(bgInputEdit.getText().toString())); + if (SafeParse.stringToDouble(editBg.getText()) != 0d) { + data.put("glucose", SafeParse.stringToDouble(editBg.getText())); if (meterRadioButton.isChecked()) data.put("glucoseType", "Finger"); if (sensorRadioButton.isChecked()) data.put("glucoseType", "Sensor"); if (otherRadioButton.isChecked()) data.put("glucoseType", "Manual"); } - if (SafeParse.stringToDouble(carbsEdit.getText().toString()) != 0d) - data.put("carbs", SafeParse.stringToDouble(carbsEdit.getText().toString())); - if (SafeParse.stringToDouble(insulinEdit.getText().toString()) != 0d) - data.put("insulin", SafeParse.stringToDouble(insulinEdit.getText().toString())); - if (allowZeroDuration || SafeParse.stringToDouble(durationeEdit.getText().toString()) != 0d) - data.put("duration", SafeParse.stringToDouble(durationeEdit.getText().toString())); + if (SafeParse.stringToDouble(editCarbs.getText()) != 0d) + data.put("carbs", SafeParse.stringToDouble(editCarbs.getText())); + if (SafeParse.stringToDouble(editInsulin.getText()) != 0d) + data.put("insulin", SafeParse.stringToDouble(editInsulin.getText())); + if (allowZeroDuration || SafeParse.stringToDouble(editDuration.getText()) != 0d) + data.put("duration", SafeParse.stringToDouble(editDuration.getText())); if (layoutPercent.getVisibility() != View.GONE) - data.put("percent", SafeParse.stringToDouble(percentEdit.getText().toString())); + data.put("percent", SafeParse.stringToDouble(editPercent.getText())); if (layoutAbsolute.getVisibility() != View.GONE) - data.put("absolute", SafeParse.stringToDouble(absoluteEdit.getText().toString())); + data.put("absolute", SafeParse.stringToDouble(editAbsolute.getText())); if (options.profile && profileSpinner.getSelectedItem() != null) data.put("profile", profileSpinner.getSelectedItem().toString()); - if (SafeParse.stringToDouble(carbTimeEdit.getText().toString()) != 0d) - data.put("preBolus", SafeParse.stringToDouble(carbTimeEdit.getText().toString())); + if (SafeParse.stringToDouble(editCarbTime.getText()) != 0d) + data.put("preBolus", SafeParse.stringToDouble(editCarbTime.getText())); if (!notesEdit.getText().toString().equals("")) data.put("notes", notesEdit.getText().toString()); data.put("units", units); if (!enteredBy.equals("")) data.put("enteredBy", enteredBy); if (options.eventType == R.id.careportal_combobolus) { - Double enteredInsulin = SafeParse.stringToDouble(insulinEdit.getText().toString()); + Double enteredInsulin = SafeParse.stringToDouble(editInsulin.getText()); data.put("enteredinsulin", enteredInsulin); - data.put("insulin", enteredInsulin * SafeParse.stringToDouble(splitEdit.getText().toString()) / 100); - data.put("relative", enteredInsulin * (100 - SafeParse.stringToDouble(splitEdit.getText().toString())) / 100 / SafeParse.stringToDouble(durationeEdit.getText().toString()) * 60); + data.put("insulin", enteredInsulin * SafeParse.stringToDouble(editInsulin.getText()) / 100); + data.put("relative", enteredInsulin * (100 - SafeParse.stringToDouble(editSplit.getText())) / 100 / SafeParse.stringToDouble(editDuration.getText()) * 60); } } catch (JSONException e) { e.printStackTrace(); @@ -613,61 +593,36 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick public void onClick(DialogInterface dialog, int id) { if (options.executeProfileSwitch) { if (data.has("profile")) { - sHandler.post(new Runnable() { - @Override - public void run() { - try { - String profile = data.getString("profile"); - NSProfile nsProfile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - nsProfile.setActiveProfile(profile); - PumpInterface pump = MainApp.getConfigBuilder(); - if (pump != null) { - pump.setNewBasalProfile(nsProfile); - log.debug("Setting new profile: " + profile); - MainApp.bus().post(new EventNewBasalProfile(nsProfile, "NewNSTreatmentDialog")); - } 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(); - } - } - }); + try { + doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration")); + } catch (JSONException e) { + e.printStackTrace(); + } } } 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(); } } @@ -677,7 +632,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick e.printStackTrace(); } } else { - ConfigBuilderPlugin.uploadCareportalEntryToNS(data); + NSUpload.uploadCareportalEntryToNS(data); Answers.getInstance().logCustom(new CustomEvent("NSTreatment")); } } @@ -686,4 +641,35 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick builder.show(); } + public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration) { + sHandler.post(new Runnable() { + @Override + public void run() { + ProfileSwitch profileSwitch = new ProfileSwitch(); + profileSwitch.date = System.currentTimeMillis(); + profileSwitch.source = Source.USER; + profileSwitch.profileName = profileName; + profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString(); + profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName(); + profileSwitch.durationInMinutes = duration; + if (ConfigBuilderPlugin.getActiveProfileInterface() instanceof CircadianPercentageProfilePlugin) { + CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) ConfigBuilderPlugin.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(profileStore.getSpecificProfile(profileName)); + MainApp.bus().post(new EventNewBasalProfile()); + } else { + log.error("No active pump selected"); + } + Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch")); + } + }); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java new file mode 100644 index 0000000000..74abc837fe --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Common/SubscriberFragment.java @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.Common; + +import android.support.v4.app.Fragment; + +import info.nightscout.androidaps.MainApp; + +abstract public class SubscriberFragment extends Fragment { + @Override + public void onPause() { + super.onPause(); + MainApp.bus().unregister(this); + } + + @Override + public void onResume() { + super.onResume(); + MainApp.bus().register(this); + updateGUI(); + } + + protected abstract void updateGUI(); +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index ff6f69ca9f..be9341b860 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 @@ -34,9 +34,11 @@ 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.interfaces.SensitivityInterface; import info.nightscout.androidaps.plugins.InsulinFastacting.InsulinFastactingPlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.SensitivityOref0.SensitivityOref0Plugin; import info.nightscout.utils.PasswordProtection; @@ -49,32 +51,32 @@ public class ConfigBuilderFragment extends Fragment { } ListView insulinListView; + ListView sensitivityListView; 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; TextView constraintsLabel; ListView generalListView; - TextView nsclientVerView; - TextView nightscoutVerView; LinearLayout mainLayout; Button unlock; PluginCustomAdapter insulinDataAdapter = null; + PluginCustomAdapter sensivityDataAdapter = 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; @@ -96,31 +98,26 @@ public class ConfigBuilderFragment extends Fragment { smallWidth = screen_width < Constants.SMALL_WIDTH; insulinListView = (ListView) view.findViewById(R.id.configbuilder_insulinlistview); + sensitivityListView = (ListView) view.findViewById(R.id.configbuilder_sensitivitylistview); 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); constraintsLabel = (TextView) view.findViewById(R.id.configbuilder_constraintslabel); generalListView = (ListView) view.findViewById(R.id.configbuilder_generallistview); - 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); - if (ConfigBuilderPlugin.nightscoutVersionCode < 900) - nightscoutVerView.setTextColor(Color.RED); setViews(); if (PasswordProtection.isLocked("settings_password")) { @@ -149,6 +146,8 @@ public class ConfigBuilderFragment extends Fragment { 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(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.PUMP), PluginBase.PUMP); pumpListView.setAdapter(pumpDataAdapter); @@ -162,21 +161,23 @@ public class ConfigBuilderFragment extends Fragment { loopLabel.setVisibility(View.GONE); 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(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginBase.TEMPBASAL), PluginBase.TEMPBASAL); - tempsListView.setAdapter(tempsDataAdapter); - setListViewHeightBasedOnChildren(tempsListView); - if (MainApp.getSpecificPluginsVisibleInList(PluginBase.TEMPBASAL).size() == 0) - tempsLabel.setVisibility(View.GONE); - profileDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.BGSOURCE), PluginBase.PROFILE); + profileDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginBase.PROFILE), PluginBase.PROFILE); profileListView.setAdapter(profileDataAdapter); + if (MainApp.getSpecificPluginsVisibleInList(PluginBase.PROFILE).size() == 0) + profileLabel.setVisibility(View.GONE); setListViewHeightBasedOnChildren(profileListView); 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.getSpecificPluginsVisibleInList(PluginBase.APS).size() == 0) apsLabel.setVisibility(View.GONE); - constraintsDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginBase.BGSOURCE), PluginBase.CONSTRAINTS); + sensivityDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginBase.SENSITIVITY), PluginBase.SENSITIVITY); + sensitivityListView.setAdapter(sensivityDataAdapter); + setListViewHeightBasedOnChildren(sensitivityListView); + constraintsDataAdapter = new PluginCustomAdapter(getContext(), smallWidth?R.layout.configbuilder_smallitem :R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginBase.CONSTRAINTS), PluginBase.CONSTRAINTS); constraintsListView.setAdapter(constraintsDataAdapter); setListViewHeightBasedOnChildren(constraintsListView); if (MainApp.getSpecificPluginsVisibleInList(PluginBase.CONSTRAINTS).size() == 0) @@ -232,7 +233,7 @@ public class ConfigBuilderFragment extends Fragment { plugin.setFragmentVisible(type, cb.isChecked()); onEnabledCategoryChanged(plugin, type); configBuilderPlugin.storeSettings(); - MainApp.bus().post(new EventRefreshGui(true)); + MainApp.bus().post(new EventRefreshGui()); MainApp.bus().post(new EventConfigBuilderChange()); getPlugin().logPluginStatus(); Answers.getInstance().logCustom(new CustomEvent("ConfigurationChange")); @@ -245,7 +246,7 @@ public class ConfigBuilderFragment extends Fragment { PluginBase plugin = (PluginBase) cb.getTag(); plugin.setFragmentVisible(type, cb.isChecked()); configBuilderPlugin.storeSettings(); - MainApp.bus().post(new EventRefreshGui(true)); + MainApp.bus().post(new EventRefreshGui()); getPlugin().logPluginStatus(); } }); @@ -275,7 +276,7 @@ public class ConfigBuilderFragment extends Fragment { } // Hide enabled control and force enabled plugin if there is only one plugin available - if (type == PluginBase.INSULIN || 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 || type == PluginBase.SENSITIVITY) if (pluginList.size() < 2) { holder.checkboxEnabled.setEnabled(false); plugin.setFragmentEnabled(type, true); @@ -324,6 +325,9 @@ public class ConfigBuilderFragment extends Fragment { case PluginBase.INSULIN: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(InsulinInterface.class); break; + case PluginBase.SENSITIVITY: + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class); + break; case PluginBase.APS: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(APSInterface.class); break; @@ -333,7 +337,6 @@ public class ConfigBuilderFragment extends Fragment { case PluginBase.BGSOURCE: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(BgSourceInterface.class); break; - case PluginBase.TEMPBASAL: case PluginBase.TREATMENT: case PluginBase.PUMP: pluginsInCategory = MainApp.getSpecificPluginsListByInterface(PumpInterface.class); @@ -355,6 +358,8 @@ public class ConfigBuilderFragment extends Fragment { MainApp.getSpecificPlugin(VirtualPumpPlugin.class).setFragmentEnabled(type, true); else if (type == PluginBase.INSULIN) MainApp.getSpecificPlugin(InsulinFastactingPlugin.class).setFragmentEnabled(type, true); + else if (type == PluginBase.SENSITIVITY) + MainApp.getSpecificPlugin(SensitivityOref0Plugin.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 eaea986d19..6bc0e1e807 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 @@ -3,7 +3,6 @@ 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; @@ -16,17 +15,24 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Date; +import java.util.List; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.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.Intervals; +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.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; @@ -35,55 +41,48 @@ 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.SensitivityInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.plugins.PumpDanaR.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.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; /** * 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; - static InsulinInterface activeInsulin; + 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; + private static SensitivityInterface activeSensitivity; 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); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "ConfigBuilderPlugin"); - ; } @Override @@ -114,12 +113,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 @@ -197,19 +196,10 @@ 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; } @@ -222,12 +212,20 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain return activeLoop; } - public void logPluginStatus() { + public static PumpInterface getActivePump() { + return activePump; + } + + public static SensitivityInterface getActiveSensitivity() { + return activeSensitivity; + } + + void logPluginStatus() { for (PluginBase p : pluginList) { log.debug(p.getName() + ":" + (p.isEnabled(1) ? " GENERAL" : "") + (p.isEnabled(2) ? " TREATMENT" : "") + - (p.isEnabled(3) ? " TEMPBASAL" : "") + + (p.isEnabled(3) ? " SENSITIVITY" : "") + (p.isEnabled(4) ? " PROFILE" : "") + (p.isEnabled(5) ? " APS" : "") + (p.isEnabled(6) ? " PUMP" : "") + @@ -266,7 +264,18 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } } - // PluginBase.PROFILE + // PluginBase.SENSITIVITY + pluginsInCategory = MainApp.getSpecificPluginsListByInterface(SensitivityInterface.class); + activeSensitivity = (SensitivityInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.SENSITIVITY); + if (Config.logConfigBuilder) + log.debug("Selected sensitivity interface: " + ((PluginBase) activeSensitivity).getName()); + for (PluginBase p : pluginsInCategory) { + if (!p.getName().equals(((PluginBase) activeSensitivity).getName())) { + p.setFragmentVisible(PluginBase.SENSITIVITY, false); + } + } + + // PluginBase.PROFILE pluginsInCategory = MainApp.getSpecificPluginsListByInterface(ProfileInterface.class); activeProfile = (ProfileInterface) getTheOneEnabledInArray(pluginsInCategory, PluginBase.PROFILE); if (Config.logConfigBuilder) @@ -291,7 +300,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())) { @@ -312,17 +323,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); @@ -379,23 +379,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) { @@ -417,7 +403,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; @@ -445,166 +431,37 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } @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(InsulinInterface insulinType, Context context, Double insulin, Integer carbs, Double glucose, String glucoseType, int carbTime, JSONObject boluscalc) { + public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { mWakeLock.acquire(); PumpEnactResult result; - if (activePump != null) { - insulin = applyBolusConstraints(insulin); - carbs = applyCarbsConstraints(carbs); + detailedBolusInfo.insulin = applyBolusConstraints(detailedBolusInfo.insulin); + detailedBolusInfo.carbs = applyCarbsConstraints((int) detailedBolusInfo.carbs); - BolusProgressDialog bolusProgressDialog = null; - if (context != null) { - bolusProgressDialog = new BolusProgressDialog(); - bolusProgressDialog.setInsulin(insulin); - bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress"); - } - - MainApp.bus().post(new EventBolusRequested(insulin)); - - result = activePump.deliverTreatment(insulinType, insulin, carbs, context); - - BolusProgressDialog.bolusEnded = true; - - MainApp.bus().post(new EventDismissBolusprogressIfRunning(result)); - - if (result.success) { - 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.mealBolus = result.carbsDelivered > 0; - MainApp.getDbHelper().create(t); - t.setTimeIndex(t.getTimeIndex()); - t.carbs = (double) result.carbsDelivered; - uploadBolusWizardRecord(t, glucose, glucoseType, carbTime, boluscalc); - } + BolusProgressDialog bolusProgressDialog = null; + if (detailedBolusInfo.context != null) { + bolusProgressDialog = new BolusProgressDialog(); + bolusProgressDialog.setInsulin(detailedBolusInfo.insulin); + bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress"); } else { - if (Config.logCongigBuilderActions) - log.debug("Creating treatment: " + insulin + " carbs: " + carbs); - Treatment t = new Treatment(insulinType); - 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; + Intent i = new Intent(); + i.putExtra("insulin", detailedBolusInfo.insulin); + i.setClass(MainApp.instance(), BolusProgressHelperActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); } + + + MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); + + result = activePump.deliverTreatment(detailedBolusInfo); + + BolusProgressDialog.bolusEnded = true; + MainApp.bus().post(new EventDismissBolusprogressIfRunning(result)); + mWakeLock.release(); return result; } - @Override - public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context) { - return deliverTreatment(insulinType, insulin, carbs, context, true); - } - - public PumpEnactResult deliverTreatment(InsulinInterface insulinType, Double insulin, Integer carbs, Context context, boolean createTreatment) { - mWakeLock.acquire(); - PumpEnactResult result; - if (activePump != null) { - insulin = applyBolusConstraints(insulin); - carbs = applyCarbsConstraints(carbs); - - BolusProgressDialog bolusProgressDialog = null; - if (context != null) { - bolusProgressDialog = new BolusProgressDialog(); - bolusProgressDialog.setInsulin(insulin); - bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress"); - } else { - Intent i = new Intent(); - i.putExtra("insulin", insulin.doubleValue()); - i.setClass(MainApp.instance(), BolusProgressHelperActivity.class); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } - - MainApp.bus().post(new EventBolusRequested(insulin)); - - result = activePump.deliverTreatment(insulinType, insulin, carbs, context); - - BolusProgressDialog.bolusEnded = true; - - MainApp.bus().post(new EventDismissBolusprogressIfRunning(result)); - - if (Config.logCongigBuilderActions) - log.debug("deliverTreatment insulin: " + insulin + " carbs: " + carbs + " success: " + result.success + " enacted: " + result.enacted + " bolusDelivered: " + result.bolusDelivered); - - if (result.success && createTreatment) { - Treatment t = new Treatment(insulinType); - t.insulin = result.bolusDelivered; - t.carbs = (double) result.carbsDelivered; - t.created_at = new Date(); - t.mealBolus = t.carbs > 0; - MainApp.getDbHelper().create(t); - t.setTimeIndex(t.getTimeIndex()); - t.sendToNSClient(); - } - } else { - if (Config.logCongigBuilderActions) - log.debug("Creating treatment: " + insulin + " carbs: " + carbs); - Treatment t = new Treatment(insulinType); - 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 void stopBolusDelivering() { activePump.stopBolusDelivering(); @@ -618,22 +475,18 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain * @return */ @Override - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { Double rateAfterConstraints = applyBasalConstraints(absoluteRate); - PumpEnactResult result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes); + PumpEnactResult result = activePump.setTempBasalAbsolute(rateAfterConstraints, durationInMinutes, force); 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; } + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + return setTempBasalAbsolute(absoluteRate, durationInMinutes, false); + } + /** * apply constraints, set temp based on percent and expecting result in percent * @@ -647,10 +500,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; } @@ -660,22 +509,14 @@ 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; } @Override - public PumpEnactResult cancelTempBasal() { - PumpEnactResult result = activePump.cancelTempBasal(); + public PumpEnactResult cancelTempBasal(boolean force) { + PumpEnactResult result = activePump.cancelTempBasal(force); 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; } @@ -693,6 +534,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain * @param request * @return */ + public PumpEnactResult applyAPSRequest(APSResult request) { request.rate = applyBasalConstraints(request.rate); PumpEnactResult result; @@ -721,7 +563,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain if (isTempBasalInProgress()) { if (Config.logCongigBuilderActions) log.debug("applyAPSRequest: cancelTempBasal()"); - result = cancelTempBasal(); + result = cancelTempBasal(false); } else { result = new PumpEnactResult(); result.absolute = request.rate; @@ -732,10 +574,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(System.currentTimeMillis()).getPlannedRemainingMinutes(); result.enacted = false; result.comment = "Temp basal set correctly"; result.success = true; @@ -788,6 +630,11 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return activePump.isFakingTempsByExtendedBoluses(); + } + /** * Constraints interface **/ @@ -904,294 +751,246 @@ 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 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(), ConfigBuilderPlugin.class); - } catch (JSONException e) { - e.printStackTrace(); - } + @Override + public void updateTotalIOBTempBasals() { + activeTreatments.updateTotalIOBTempBasals(); } - 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 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 Intervals 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 Intervals getExtendedBolusesFromHistory() { + return activeTreatments.getExtendedBolusesFromHistory(); + } + + @Override + // return true if new record is created + public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo) { + boolean newRecordCreated = activeTreatments.addToHistoryTreatment(detailedBolusInfo); + if (newRecordCreated && detailedBolusInfo.isValid) + NSUpload.uploadBolusWizardRecord(detailedBolusInfo); + return newRecordCreated; + } + + @Override + @Nullable + public TempTarget getTempTargetFromHistory(long time) { + return activeTreatments.getTempTargetFromHistory(time); + } + + @Override + public Intervals 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(System.currentTimeMillis()); + } + + 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(System.currentTimeMillis()); } - 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 String getProfileUnits() { + return activeProfile.getUnits(); } - 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); - } - } else { - log.debug("OpenAPS data too old to upload"); - } - if (activePump != null) { - deviceStatus.device = "openaps://" + deviceID(); - JSONObject pumpstatus = getJSONStatus(); - if (pumpstatus != null) { - deviceStatus.pump = pumpstatus; + public Profile getProfile(long time) { + if (activeTreatments == null) + return null; //app not initialized + //log.debug("Profile for: " + new Date(time).toLocaleString() + " : " + getProfileName(time)); + boolean ignoreProfileSwitchEvents = SP.getBoolean(R.string.key_do_not_track_profile_switch, false); + if (!ignoreProfileSwitchEvents) { + ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time); + if (profileSwitch != null) { + if (profileSwitch.profileJson != null) { + return profileSwitch.getProfileObject(); + } else if (activeProfile.getProfile() != null) { + Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName); + if (profile != null) + return profile; } } - - 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/ConfigBuilder/DetailedBolusInfoStorage.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java new file mode 100644 index 0000000000..d6352cdb18 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/DetailedBolusInfoStorage.java @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.plugins.ConfigBuilder; + +import android.support.annotation.Nullable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.data.DetailedBolusInfo; + +/** + * Created by mike on 08.08.2017. + */ + +public class DetailedBolusInfoStorage { + private static Logger log = LoggerFactory.getLogger(DetailedBolusInfoStorage.class); + private static List store = new ArrayList<>(); + + public static void add(DetailedBolusInfo detailedBolusInfo) { + log.debug("Bolus info stored: " + new Date(detailedBolusInfo.date).toLocaleString()); + store.add(detailedBolusInfo); + } + + @Nullable + public static DetailedBolusInfo findDetailedBolusInfo(long bolustime) { + DetailedBolusInfo found = null; + for (int i = 0; i < store.size(); i++) { + long infoTime = store.get(i).date; + log.debug("Existing info: " + new Date(infoTime).toLocaleString()); + if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { + found = store.get(i); + break; + } + } + return found; + } + + public static void remove(long bolustime) { + for (int i = 0; i < store.size(); i++) { + long infoTime = store.get(i).date; + if (bolustime > infoTime - 60 * 1000 && bolustime < infoTime + 60 * 1000) { + log.debug("Removing info: " + new Date(infoTime).toLocaleString()); + store.remove(i); + break; + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java index 3334267057..906bf243ff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesFragment.java @@ -91,7 +91,7 @@ public class ObjectivesFragment extends Fragment { } }); - Long now = new Date().getTime(); + Long now = System.currentTimeMillis(); if (position > 0 && objectives.get(position - 1).accomplished.getTime() == 0) { // Phase 0: previous not completed holder.startedLayout.setVisibility(View.GONE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java index b6f4e57acd..e04efb70cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsObjectives/ObjectivesPlugin.java @@ -10,6 +10,7 @@ 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.MainApp; import info.nightscout.androidaps.R; @@ -67,8 +68,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface { @Override public boolean isVisibleInTabs(int type) { - LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); - return type == CONSTRAINTS && fragmentVisible && loopPlugin != null && loopPlugin.isVisibleInTabs(LOOP); + return type == CONSTRAINTS && fragmentVisible && !BuildConfig.NSCLIENTOLNY; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyFragment.java deleted file mode 100644 index 07583e7622..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyFragment.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.nightscout.androidaps.plugins.ConstraintsSafety; - - -import android.support.v4.app.Fragment; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SafetyFragment extends Fragment { - private static Logger log = LoggerFactory.getLogger(SafetyFragment.class); - - private static SafetyPlugin safetyPlugin = new SafetyPlugin(); - - public static SafetyPlugin getPlugin() { - return safetyPlugin; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java index cdf7f554ee..6880d1a21e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConstraintsSafety/SafetyPlugin.java @@ -3,6 +3,8 @@ package info.nightscout.androidaps.plugins.ConstraintsSafety; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Objects; + import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; @@ -10,7 +12,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; @@ -21,9 +23,17 @@ import info.nightscout.utils.SP; public class SafetyPlugin implements PluginBase, ConstraintsInterface { private static Logger log = LoggerFactory.getLogger(SafetyPlugin.class); + static SafetyPlugin plugin = null; + + public static SafetyPlugin getPlugin() { + if (plugin == null) + plugin = new SafetyPlugin(); + return plugin; + } + @Override public String getFragmentClass() { - return SafetyFragment.class.getName(); + return null; } @Override @@ -105,7 +115,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; @@ -118,8 +128,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"); } @@ -136,9 +146,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); @@ -153,17 +163,17 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { Double origRate = absoluteRate; if (absoluteRate > maxBasal) { absoluteRate = maxBasal; - if (Config.logConstraintsChanges && origPercentRate != Constants.basalPercentOnlyForCheckLimit) + if (Config.logConstraintsChanges && !Objects.equals(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 (Config.logConstraintsChanges && origPercentRate != Constants.basalPercentOnlyForCheckLimit) + if (absoluteRate > maxBasalMult * profile.getBasal()) { + absoluteRate = Math.floor(maxBasalMult * profile.getBasal() * 100) / 100; + if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Limiting rate " + origRate + " by maxBasalMult to " + absoluteRate + "U/h"); } if (absoluteRate > profile.getMaxDailyBasal() * maxBasalFromDaily) { absoluteRate = profile.getMaxDailyBasal() * maxBasalFromDaily; - if (Config.logConstraintsChanges && origPercentRate != Constants.basalPercentOnlyForCheckLimit) + if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Limiting rate " + origRate + " by 3 * maxDailyBasal to " + absoluteRate + "U/h"); } @@ -172,7 +182,7 @@ public class SafetyPlugin implements PluginBase, ConstraintsInterface { percentRateAfterConst = Round.ceilTo((double) percentRateAfterConst, 10d).intValue(); else percentRateAfterConst = Round.floorTo((double) percentRateAfterConst, 10d).intValue(); - if (Config.logConstraintsChanges && origPercentRate != Constants.basalPercentOnlyForCheckLimit) + if (Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) log.debug("Recalculated percent rate " + percentRate + "% to " + percentRateAfterConst + "%"); return percentRateAfterConst; } 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 index abc768afdc..3eda06fb37 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/ActivityGraph.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/ActivityGraph.java @@ -9,20 +9,17 @@ 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; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; /** * Created by mike on 21.04.2017. */ public class ActivityGraph extends GraphView { - Context context; public ActivityGraph(Context context) { @@ -36,28 +33,29 @@ public class ActivityGraph extends GraphView { } public void show(InsulinInterface insulin) { + removeAllSeries(); + mSecondScale = null; double dia = insulin.getDia(); int hours = (int) Math.floor(dia + 1); - Treatment t = new Treatment(insulin); - t.created_at = new Date(0); - t.timeIndex = 0; + Treatment t = new Treatment(); + t.date = 0; t.insulin = 1d; LineGraphSeries activitySeries = null; LineGraphSeries iobSeries = null; - List activityArray = new ArrayList(); - List iobArray = new ArrayList(); + List activityArray = new ArrayList<>(); + List iobArray = new ArrayList<>(); for (long time = 0; time <= hours * 60 * 60 * 1000; time += 5 * 60 * 1000L) { - Iob iob = insulin.iobCalc(t, time, dia); + 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)); + addSeries(activitySeries = new LineGraphSeries<>(activityDataPoints)); activitySeries.setThickness(8); getViewport().setXAxisBoundsManual(true); @@ -65,14 +63,16 @@ public class ActivityGraph extends GraphView { getViewport().setMaxX(hours * 60); getGridLabelRenderer().setNumHorizontalLabels(hours + 1); getGridLabelRenderer().setHorizontalAxisTitle("[min]"); + getGridLabelRenderer().setVerticalLabelsColor(activitySeries.getColor()); DataPoint[] iobDataPoints = new DataPoint[iobArray.size()]; iobDataPoints = iobArray.toArray(iobDataPoints); - getSecondScale().addSeries(iobSeries = new LineGraphSeries(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); + getGridLabelRenderer().setVerticalLabelsSecondScaleColor(Color.MAGENTA); } } 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 index a99e016621..f62d063193 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingFragment.java @@ -35,12 +35,22 @@ public class InsulinFastactingFragment extends Fragment { 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); + updateGUI(); return view; } + @Override + public void onResume() { + super.onResume(); + updateGUI(); + } + + private void updateGUI() { + insulinName.setText(insulinFastactingPlugin.getFriendlyName()); + insulinComment.setText(insulinFastactingPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(insulinFastactingPlugin.getDia()) + "h"); + insulinGraph.show(insulinFastactingPlugin); + } + } 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 index 9773c20f55..e055e3d3ed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastacting/InsulinFastactingPlugin.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.InsulinFastacting; -import java.util.Date; - import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -9,7 +7,6 @@ import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.ProfileInterface; /** * Created by mike on 17.04.2017. @@ -93,32 +90,29 @@ public class InsulinFastactingPlugin implements PluginBase, InsulinInterface { @Override public double getDia() { - ProfileInterface profileInterface = MainApp.getConfigBuilder().getActiveProfile(); - if (profileInterface.getProfile() != null) - return profileInterface.getProfile().getDia(); - return Constants.defaultDIA; + return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : Constants.defaultDIA; } @Override - public Iob iobCalc(Treatment treatment, long time, Double dia) { + public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { Iob result = new Iob(); - Double scaleFactor = 3.0 / dia; - Double peak = 75d; - Double end = 180d; + double scaleFactor = 3.0 / dia; + double peak = 75d; + double end = 180d; if (treatment.insulin != 0d) { - Long bolusTime = treatment.created_at.getTime(); - Double minAgo = scaleFactor * (time - bolusTime) / 1000d / 60d; + long bolusTime = treatment.date; + double minAgo = scaleFactor * (time - bolusTime) / 1000d / 60d; if (minAgo < peak) { - Double x1 = minAgo / 5d + 1; + 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; + 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)); } 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 index acc915b001..1747f5f4ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedFragment.java @@ -36,12 +36,22 @@ public class InsulinFastactingProlongedFragment extends Fragment { 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); + updateGUI(); return view; } + @Override + public void onResume() { + super.onResume(); + updateGUI(); + } + + private void updateGUI() { + insulinName.setText(insulinFastactingProlongedPlugin.getFriendlyName()); + insulinComment.setText(insulinFastactingProlongedPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(insulinFastactingProlongedPlugin.getDia()) + "h"); + insulinGraph.show(insulinFastactingProlongedPlugin); + } + } 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 index 58d644043c..3c5df052df 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinFastactingProlonged/InsulinFastactingProlongedPlugin.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.InsulinFastactingProlonged; -import java.util.Date; - import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -9,7 +7,6 @@ import info.nightscout.androidaps.data.Iob; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.InsulinInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.ProfileInterface; /** * Created by mike on 17.04.2017. @@ -93,37 +90,34 @@ public class InsulinFastactingProlongedPlugin implements PluginBase, InsulinInte @Override public double getDia() { - ProfileInterface profileInterface = MainApp.getConfigBuilder().getActiveProfile(); - if (profileInterface.getProfile() != null) - return profileInterface.getProfile().getDia(); - return Constants.defaultDIA; + return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : Constants.defaultDIA; } @Override - public Iob iobCalc(Treatment treatment, long time, Double dia) { + 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; + 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.created_at.getTime(); - Double minAgo = (time - bolusTime) / 1000d / 60d; + long bolusTime = treatment.date; + double minAgo = (time - bolusTime) / 1000d / 60d; if (minAgo < peak) { - Double x1 = 6 / dia * minAgo / 5d + 1; + 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; + 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; + 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); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefBasePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefBasePlugin.java new file mode 100644 index 0000000000..10dfd5dce5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefBasePlugin.java @@ -0,0 +1,108 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Iob; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; + +/** + * Created by adrian on 13.08.2017. + */ + +public abstract class InsulinOrefBasePlugin implements PluginBase, InsulinInterface { + + public static double MIN_DIA = 5; + + long lastWarned = 0; + + @Override + public int getType() { + return INSULIN; + } + + @Override + public String getNameShort() { + return MainApp.sResources.getString(R.string.insulin_shortname); + } + + @Override + public boolean canBeHidden(int type) { + return true; + } + + @Override + public boolean hasFragment() { + return true; + } + + @Override + public boolean showInList(int type) { + return true; + } + + @Override + public double getDia() { + double dia = getUserDefinedDia(); + if(dia >= MIN_DIA){ + return dia; + } else { + if((System.currentTimeMillis() - lastWarned) > 60*1000) { + lastWarned = System.currentTimeMillis(); + Notification notification = new Notification(Notification.SHORT_DIA, String.format(MainApp.sResources.getString(R.string.dia_too_short), dia, MIN_DIA), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + } + return MIN_DIA; + } + } + + public double getUserDefinedDia() { + return MainApp.getConfigBuilder().getProfile() != null ? MainApp.getConfigBuilder().getProfile().getDia() : Constants.defaultDIA; + } + + @Override + public Iob iobCalcForTreatment(Treatment treatment, long time, Double dia) { + Iob result = new Iob(); + + int peak = getPeak(); + + + if (treatment.insulin != 0d) { + + long bolusTime = treatment.date; + double t = (time - bolusTime) / 1000d / 60d; + + double td = getDia()*60; //getDIA() always > 5 + double tp = peak; + + // force the IOB to 0 if over DIA hours have passed + if (t < td) { + double tau = tp * (1 - tp / td) / (1 - 2 * tp / td); + double a = 2 * tau / td; + double S = 1 / (1 - a + (1 + a) * Math.exp(-td / tau)); + result.activityContrib = treatment.insulin * (S / Math.pow(tau, 2)) * t * (1 - t / td) * Math.exp(-t / tau); + result.iobContrib = treatment.insulin * (1 - S * (1 - a) * ((Math.pow(t, 2) / (tau * td * (1 - a)) - t / tau - 1) * Math.exp(-t / tau) + 1)); + } + } + return result; + } + + @Override + public String getComment() { + String comment = commentStandardText(); + double userDia = getUserDefinedDia(); + if(userDia < MIN_DIA){ + comment += "\n" + String.format(MainApp.sResources.getString(R.string.dia_too_short), userDia, MIN_DIA); + } + return comment; + } + + abstract int getPeak(); + + abstract String commentStandardText(); + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefFreePeakFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefFreePeakFragment.java new file mode 100644 index 0000000000..f7120369b3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefFreePeakFragment.java @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +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 adrian on 14/08/17. + */ + +public class InsulinOrefFreePeakFragment extends Fragment { + + static InsulinOrefFreePeakPlugin insulinPlugin = new InsulinOrefFreePeakPlugin(); + + static public InsulinOrefFreePeakPlugin getPlugin() { + return insulinPlugin; + } + + 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); + + updateGUI(); + + return view; + } + + @Override + public void onResume() { + super.onResume(); + updateGUI(); + } + + private void updateGUI() { + insulinName.setText(insulinPlugin.getFriendlyName()); + insulinComment.setText(insulinPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(insulinPlugin.getDia()) + "h"); + insulinGraph.show(insulinPlugin); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefFreePeakPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefFreePeakPlugin.java new file mode 100644 index 0000000000..747eabda5b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefFreePeakPlugin.java @@ -0,0 +1,67 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.utils.SP; + +/** + * Created by adrian on 14/08/17. + */ + +public class InsulinOrefFreePeakPlugin extends InsulinOrefBasePlugin { + + private static boolean fragmentEnabled = false; + private static boolean fragmentVisible = false; + + public static final int DEFAULT_PEAK = 75; + + @Override + public int getId() { + return OREF_FREE_PEAK; + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.free_peak_oref); + } + + @Override + public String getFragmentClass() { + return InsulinOrefFreePeakFragment.class.getName(); + } + + @Override + public String getFriendlyName() { + return MainApp.sResources.getString(R.string.free_peak_oref); + } + + @Override + public String commentStandardText() { + return MainApp.sResources.getString(R.string.insulin_peak_time) + ": " + getPeak(); + } + + @Override + public boolean isEnabled(int type) { + return type == INSULIN && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == INSULIN && fragmentVisible; + } + + @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; + } + + @Override + int getPeak() { + return SP.getInt(R.string.key_insulin_oref_peak, DEFAULT_PEAK); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefRapidActingFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefRapidActingFragment.java new file mode 100644 index 0000000000..e30c087d21 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefRapidActingFragment.java @@ -0,0 +1,57 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +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 adrian on 14/08/17. + */ + +public class InsulinOrefRapidActingFragment extends Fragment { + + static InsulinOrefRapidActingPlugin insulinPlugin = new InsulinOrefRapidActingPlugin(); + + static public InsulinOrefRapidActingPlugin getPlugin() { + return insulinPlugin; + } + + 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); + + updateGUI(); + + return view; + } + + @Override + public void onResume() { + super.onResume(); + updateGUI(); + } + + private void updateGUI() { + insulinName.setText(insulinPlugin.getFriendlyName()); + insulinComment.setText(insulinPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(insulinPlugin.getDia()) + "h"); + insulinGraph.show(insulinPlugin); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefRapidActingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefRapidActingPlugin.java new file mode 100644 index 0000000000..6f6973bc58 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefRapidActingPlugin.java @@ -0,0 +1,66 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +/** + * Created by adrian on 14/08/17. + */ + +public class InsulinOrefRapidActingPlugin extends InsulinOrefBasePlugin { + + private static boolean fragmentEnabled = false; + private static boolean fragmentVisible = false; + + public static final int PEAK = 75; + + @Override + public int getId() { + return OREF_RAPID_ACTING; + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.rapid_acting_oref); + } + + @Override + public String getFragmentClass() { + return InsulinOrefRapidActingFragment.class.getName(); + } + + @Override + public String getFriendlyName() { + return MainApp.sResources.getString(R.string.rapid_acting_oref); + } + + @Override + public String commentStandardText() { + return MainApp.sResources.getString(R.string.fastactinginsulincomment); + } + + @Override + public boolean isEnabled(int type) { + return type == INSULIN && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == INSULIN && fragmentVisible; + } + + @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; + } + + @Override + int getPeak() { + return PEAK; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefUltraRapidActingFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefUltraRapidActingFragment.java new file mode 100644 index 0000000000..ea05c7f2e7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefUltraRapidActingFragment.java @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +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 adrian on 14/08/17. + */ + +public class InsulinOrefUltraRapidActingFragment extends Fragment { + + static InsulinOrefUltraRapidActingPlugin insulinPlugin = new InsulinOrefUltraRapidActingPlugin(); + + static public InsulinOrefUltraRapidActingPlugin getPlugin() { + return insulinPlugin; + } + + 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); + + updateGUI(); + + return view; + } + + @Override + public void onResume() { + super.onResume(); + updateGUI(); + } + + private void updateGUI() { + insulinName.setText(insulinPlugin.getFriendlyName()); + insulinComment.setText(insulinPlugin.getComment()); + insulinDia.setText(MainApp.sResources.getText(R.string.dia) + " " + Double.toString(insulinPlugin.getDia()) + "h"); + insulinGraph.show(insulinPlugin); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefUltraRapidActingPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefUltraRapidActingPlugin.java new file mode 100644 index 0000000000..975707d38b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/InsulinOrefCurves/InsulinOrefUltraRapidActingPlugin.java @@ -0,0 +1,66 @@ +package info.nightscout.androidaps.plugins.InsulinOrefCurves; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +/** + * Created by adrian on 14/08/17. + */ + +public class InsulinOrefUltraRapidActingPlugin extends InsulinOrefBasePlugin { + + private static boolean fragmentEnabled = false; + private static boolean fragmentVisible = false; + + public static final int PEAK = 55; + + @Override + public int getId() { + return OREF_ULTRA_RAPID_ACTING; + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.ultrarapid_oref); + } + + @Override + public String getFragmentClass() { + return InsulinOrefUltraRapidActingFragment.class.getName(); + } + + @Override + public String getFriendlyName() { + return MainApp.sResources.getString(R.string.ultrarapid_oref); + } + + @Override + public String commentStandardText() { + return MainApp.sResources.getString(R.string.ultrafastactinginsulincomment); + } + + @Override + public boolean isEnabled(int type) { + return type == INSULIN && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == INSULIN && fragmentVisible; + } + + @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; + } + + @Override + int getPeak() { + return PEAK; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java index 32ed9f8ed5..9939bd44d1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/AutosensData.java @@ -1,24 +1,95 @@ package info.nightscout.androidaps.plugins.IobCobCalculator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin; +import info.nightscout.utils.SP; /** * Created by mike on 25.04.2017. */ public class AutosensData { - long time = 0L; + private static Logger log = LoggerFactory.getLogger(AutosensData.class); + + static class CarbsInPast { + long time = 0L; + double carbs = 0d; + double min5minCarbImpact = 0d; + double remaining = 0d; + + public CarbsInPast(Treatment t) { + time = t.date; + carbs = t.carbs; + remaining = t.carbs; + if (MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class) != null && MainApp.getSpecificPlugin(SensitivityAAPSPlugin.class).isEnabled(PluginBase.SENSITIVITY)) { + double maxAbsorptionHours = SP.getDouble(R.string.key_absorption_maxtime, 4d); + Profile profile = MainApp.getConfigBuilder().getProfile(t.date); + double sens = Profile.toMgdl(profile.getIsf(t.date), profile.getUnits()); + double ic = profile.getIc(t.date); + min5minCarbImpact = t.carbs / (maxAbsorptionHours * 60 / 5) * sens / ic; + log.debug("Min 5m carbs impact for " + carbs + "g @" + new Date(t.date).toLocaleString() + " for " + maxAbsorptionHours + "h calculated to " + min5minCarbImpact + " ISF: " + sens + " IC: " + ic); + } else { + min5minCarbImpact = SP.getDouble("openapsama_min_5m_carbimpact", 3.0); + } + } + } + + public long time = 0L; public String pastSensitivity = ""; public double deviation = 0d; - boolean calculateWithDeviation = false; + boolean nonCarbsDeviation = false; + public boolean nonEqualDeviation = false; + List activeCarbsList = new ArrayList<>(); double absorbed = 0d; - double carbsFromBolus = 0d; + public double carbsFromBolus = 0d; public double cob = 0; public double bgi = 0d; public double delta = 0d; + public double autosensRatio = 1d; + public String log(long time) { - return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " Bgi=" + bgi + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob; + return "AutosensData: " + new Date(time).toLocaleString() + " " + pastSensitivity + " Delta=" + delta + " Bgi=" + bgi + " Deviation=" + deviation + " Absorbed=" + absorbed + " CarbsFromBolus=" + carbsFromBolus + " COB=" + cob + " autosensRatio=" + autosensRatio; + } + + public int minOld() { + return (int) ((System.currentTimeMillis() - time) / 1000 / 60); + } + + // remove carbs older than 4h + public void removeOldCarbs(long toTime) { + for (int i = 0; i < activeCarbsList.size(); i++) { + CarbsInPast c = activeCarbsList.get(i); + if (c.time + 4 * 60 * 60 * 1000L < toTime) { + activeCarbsList.remove(i--); + if (c.remaining > 0) + cob -= c.remaining; + log.debug("Removing carbs at "+ new Date(toTime).toLocaleString() + " + after 4h :" + new Date(c.time).toLocaleString()); + } + } + } + + public void substractAbosorbedCarbs() { + double ac = absorbed; + for (int i = 0; i < activeCarbsList.size() && ac > 0; i++) { + CarbsInPast c = activeCarbsList.get(i); + if (c.remaining > 0) { + double sub = Math.min(ac, c.remaining); + c.remaining -= sub; + ac -= sub; + } + } } } 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 deleted file mode 100644 index db1db95998..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorFragment.java +++ /dev/null @@ -1,16 +0,0 @@ -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 index 85a5c886bd..445eda93cd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -12,27 +12,27 @@ 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.R; 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.EventConfigBuilderChange; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBasalProfile; +import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +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.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.Round; -import info.nightscout.utils.SP; -import info.nightscout.utils.SafeParse; /** * Created by mike on 24.04.2017. @@ -43,6 +43,7 @@ public class IobCobCalculatorPlugin implements PluginBase { 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; @@ -52,7 +53,23 @@ public class IobCobCalculatorPlugin implements PluginBase { private static Handler sHandler = null; private static HandlerThread sHandlerThread = null; - private static Object dataLock = new Object(); + private static final Object dataLock = new Object(); + + private static IobCobCalculatorPlugin plugin = null; + + public static IobCobCalculatorPlugin getPlugin() { + if (plugin == null) + plugin = new IobCobCalculatorPlugin(); + return plugin; + } + + public static LongSparseArray getAutosensDataTable() { + return autosensDataTable; + } + + public static List getBucketedData() { + return bucketed_data; + } @Override public int getType() { @@ -61,7 +78,7 @@ public class IobCobCalculatorPlugin implements PluginBase { @Override public String getFragmentClass() { - return IobCobCalculatorFragment.class.getName(); + return null; } @Override @@ -109,7 +126,7 @@ public class IobCobCalculatorPlugin implements PluginBase { } - public IobCobCalculatorPlugin() { + IobCobCalculatorPlugin() { MainApp.bus().register(this); if (sHandlerThread == null) { sHandlerThread = new HandlerThread(IobCobCalculatorPlugin.class.getSimpleName()); @@ -140,7 +157,7 @@ public class IobCobCalculatorPlugin implements PluginBase { private static int indexNewerThan(long time) { for (int index = 0; index < bucketed_data.size(); index++) { - if (bucketed_data.get(index).timeIndex < time) + if (bucketed_data.get(index).date < time) return index - 1; } return -1; @@ -156,14 +173,103 @@ public class IobCobCalculatorPlugin implements PluginBase { private void loadBgData() { //log.debug("Locking loadBgData"); synchronized (dataLock) { - onNewProfile(new EventNewBasalProfile(null, "IobCobCalculator init")); - bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (new Date().getTime() - 60 * 60 * 1000L * (24 + dia)), false); + onNewProfile(null); + bgReadings = MainApp.getDbHelper().getBgreadingsDataFromTime((long) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)), false); log.debug("BG data loaded. Size: " + bgReadings.size()); } //log.debug("Releasing loadBgData"); } - public void createBucketedData() { + private boolean isAbout5minData() { + synchronized (dataLock) { + if (bgReadings == null || bgReadings.size() < 3) { + return true; + } + long totalDiff = 0; + for (int i = 1; i < bgReadings.size(); ++i) { + long bgTime = bgReadings.get(i).date; + long lastbgTime = bgReadings.get(i - 1).date; + long diff = lastbgTime - bgTime; + totalDiff += diff; + if (diff > 30 * 1000 && diff < 270 * 1000) { // 0:30 - 4:30 + log.debug("Interval detection: values: " + bgReadings.size() + " diff: " + (diff / 1000) + "sec is5minData: " + false); + return false; + } + } + double intervals = totalDiff / (5 * 60 * 1000d); + double variability = Math.abs(intervals - Math.round(intervals)); + boolean is5mindata = variability < 0.02; + log.debug("Interval detection: values: " + bgReadings.size() + " variability: " + variability + " is5minData: " + is5mindata); + return is5mindata; + } + } + + private void createBucketedData() { + if (isAbout5minData()) + createBucketedData5min(); + else + createBucketedDataRecalculated(); + } + + @Nullable + private BgReading findNewer(long time) { + BgReading lastFound = bgReadings.get(0); + if (lastFound.date < time) return null; + for (int i = 1; i < bgReadings.size(); ++i) { + if (bgReadings.get(i).date > time) continue; + lastFound = bgReadings.get(i); + if (bgReadings.get(i).date < time) break; + } + return lastFound; + } + + @Nullable + private BgReading findOlder(long time) { + BgReading lastFound = bgReadings.get(bgReadings.size() - 1); + if (lastFound.date > time) return null; + for (int i = bgReadings.size() - 2; i >=0 ; --i) { + if (bgReadings.get(i).date < time) continue; + lastFound = bgReadings.get(i); + if (bgReadings.get(i).date > time) break; + } + return lastFound; + } + + private void createBucketedDataRecalculated() { + synchronized (dataLock) { + if (bgReadings == null || bgReadings.size() < 3) { + bucketed_data = null; + return; + } + + bucketed_data = new ArrayList<>(); + long currentTime = bgReadings.get(0).date + 5 * 60 * 1000 - bgReadings.get(0).date % (5 * 60 * 1000) - 5 * 60 * 1000L; + //log.debug("First reading: " + new Date(currentTime).toLocaleString()); + + while (true) { + // test if current value is older than current time + BgReading newer = findNewer(currentTime); + BgReading older = findOlder(currentTime); + if (newer == null || older == null) + break; + + double bgDelta = newer.value - older.value; + long timeDiffToNew = newer.date - currentTime; + + double currentBg = newer.value - (double) timeDiffToNew / (newer.date - older.date) * bgDelta; + BgReading newBgreading = new BgReading(); + newBgreading.date = currentTime; + newBgreading.value = Math.round(currentBg); + bucketed_data.add(newBgreading); + //log.debug("BG: " + newBgreading.value + " (" + new Date(newBgreading.date).toLocaleString() + ") Prev: " + older.value + " (" + new Date(older.date).toLocaleString() + ") Newer: " + newer.value + " (" + new Date(newer.date).toLocaleString() + ")"); + currentTime -= 5 * 60 * 1000L; + + } + } + } + + + public void createBucketedData5min() { //log.debug("Locking createBucketedData"); synchronized (dataLock) { if (bgReadings == null || bgReadings.size() < 3) { @@ -175,8 +281,8 @@ public class IobCobCalculatorPlugin implements PluginBase { bucketed_data.add(bgReadings.get(0)); int j = 0; for (int i = 1; i < bgReadings.size(); ++i) { - long bgTime = bgReadings.get(i).getTimeIndex(); - long lastbgTime = bgReadings.get(i - 1).getTimeIndex(); + 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; @@ -193,14 +299,14 @@ public class IobCobCalculatorPlugin implements PluginBase { nextbgTime = lastbgTime - 5 * 60 * 1000; j++; BgReading newBgreading = new BgReading(); - newBgreading.timeIndex = nextbgTime; + 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.timeIndex).toString() + " " + newBgreading.value); + //log.error("******************************************************************************************************* Adding:" + new Date(newBgreading.date).toString() + " " + newBgreading.value); elapsed_minutes = elapsed_minutes - 5; lastbg = nextbg; @@ -209,16 +315,16 @@ public class IobCobCalculatorPlugin implements PluginBase { j++; BgReading newBgreading = new BgReading(); newBgreading.value = bgReadings.get(i).value; - newBgreading.timeIndex = bgTime; + newBgreading.date = bgTime; bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value); + //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.timeIndex = bgTime; + newBgreading.date = bgTime; bucketed_data.add(newBgreading); - //log.error("******************************************************************************************************* Copying:" + new Date(newBgreading.timeIndex).toString() + " " + newBgreading.value); + //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"); @@ -229,35 +335,30 @@ public class IobCobCalculatorPlugin implements PluginBase { //log.debug("Releasing createBucketedData"); } - public void calculateSensitivityData() { + private void calculateSensitivityData() { + if (MainApp.getConfigBuilder() == null) + return; // app still initializing + if (MainApp.getConfigBuilder().getProfile() == null) + return; // app still initializing //log.debug("Locking calculateSensitivityData"); + long oldestTimeWithData = oldestDataAvailable(); + synchronized (dataLock) { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile() != null ? ConfigBuilderPlugin.getActiveProfile().getProfile() : null; - if (profile == null || profile.getIsf(NSProfile.secondsFromMidnight()) == null || profile.getIc(NSProfile.secondsFromMidnight()) == null) { - log.debug("calculateSensitivityData: No profile available"); - return; - } - - if (ConfigBuilderPlugin.getActiveTreatments() == null) { - log.debug("calculateSensitivityData: No treatments plugin"); - return; - } - - TreatmentsInterface treatmentsInterface = ConfigBuilderPlugin.getActiveTreatments(); 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).timeIndex); + 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).timeIndex; + long bgTime = bucketed_data.get(i).date; bgTime = roundUpTime(bgTime); + Profile profile = MainApp.getConfigBuilder().getProfile(bgTime); AutosensData existing; if ((existing = autosensDataTable.get(bgTime)) != null) { @@ -265,11 +366,14 @@ public class IobCobCalculatorPlugin implements PluginBase { continue; } - int secondsFromMidnight = NSProfile.secondsFromMidnight(bgTime); - double sens = NSProfile.toMgdl(profile.getIsf(secondsFromMidnight), profile.getUnits()); + double sens = Profile.toMgdl(profile.getIsf(bgTime), profile.getUnits()); AutosensData autosensData = new AutosensData(); autosensData.time = bgTime; + if (previous != null) + autosensData.activeCarbsList = new ArrayList<>(previous.activeCarbsList); + else + autosensData.activeCarbsList = new ArrayList<>(); //console.error(bgTime , bucketed_data[i].glucose); double bg; @@ -282,25 +386,36 @@ public class IobCobCalculatorPlugin implements PluginBase { } delta = (bg - bucketed_data.get(i + 1).value); - IobTotal iob = calulateFromTreatmentsAndTemps(bgTime); + IobTotal iob = calculateFromTreatmentsAndTemps(bgTime); double bgi = -iob.activity * sens * 5; double deviation = delta - bgi; - List recentTreatments = treatmentsInterface.getTreatments5MinBack(bgTime); + List recentTreatments = MainApp.getConfigBuilder().getTreatments5MinBackFromHistory(bgTime); for (int ir = 0; ir < recentTreatments.size(); ir++) { autosensData.carbsFromBolus += recentTreatments.get(ir).carbs; + autosensData.activeCarbsList.add(new AutosensData.CarbsInPast(recentTreatments.get(ir))); } + // if we are absorbing carbs if (previous != null && previous.cob > 0) { + // calculate sum of min carb impact from all active treatments + double totalMinCarbsImpact = 0d; + for (int ii = 0; ii < autosensData.activeCarbsList.size(); ++ii) { + AutosensData.CarbsInPast c = autosensData.activeCarbsList.get(ii); + totalMinCarbsImpact += c.min5minCarbImpact; + } + // 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(secondsFromMidnight) / sens; + // but always assume at least 3mg/dL/5m (default) absorption per active treatment + double ci = Math.max(deviation, totalMinCarbsImpact); + 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.substractAbosorbedCarbs(); } + autosensData.removeOldCarbs(bgTime); autosensData.cob += autosensData.carbsFromBolus; autosensData.deviation = deviation; autosensData.bgi = bgi; @@ -310,12 +425,15 @@ public class IobCobCalculatorPlugin implements PluginBase { if (autosensData.cob <= 0) { if (Math.abs(deviation) < Constants.DEVIATION_TO_BE_EQUAL) { autosensData.pastSensitivity += "="; + autosensData.nonEqualDeviation = true; } else if (deviation > 0) { autosensData.pastSensitivity += "+"; + autosensData.nonEqualDeviation = true; } else { autosensData.pastSensitivity += "-"; + autosensData.nonEqualDeviation = true; } - autosensData.calculateWithDeviation = true; + autosensData.nonCarbsDeviation = true; } else { autosensData.pastSensitivity += "C"; } @@ -323,69 +441,112 @@ public class IobCobCalculatorPlugin implements PluginBase { previous = autosensData; autosensDataTable.put(bgTime, autosensData); - log.debug(autosensData.log(bgTime)); + autosensData.autosensRatio = detectSensitivity(oldestTimeWithData, bgTime).ratio; + 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(); + public static long oldestDataAvailable() { + long now = System.currentTimeMillis(); + + long oldestDataAvailable = MainApp.getConfigBuilder().oldestDataAvailable(); + long getBGDataFrom = Math.max(oldestDataAvailable, (long) (now - 60 * 60 * 1000L * (24 + MainApp.getConfigBuilder().getProfile().getDia()))); + log.debug("Limiting data to oldest available temps: " + new Date(oldestDataAvailable).toString()); + return getBGDataFrom; + } + + public static IobTotal calculateFromTreatmentsAndTempsSynchronized(long time) { + synchronized (dataLock) { + return calculateFromTreatmentsAndTemps(time); + } + } + + public static IobTotal calculateFromTreatmentsAndTemps(long time) { + long now = System.currentTimeMillis(); time = roundUpTime(time); if (time < now && iobTable.get(time) != null) { - //log.debug(">>> Cache hit"); + //og.debug(">>> calculateFromTreatmentsAndTemps Cache hit " + new Date(time).toLocaleString()); return iobTable.get(time); } else { - //log.debug(">>> Cache miss " + new Date(time).toLocaleString()); + //log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString()); } - IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getCalculationToTime(time).round(); - IobTotal basalIob = ConfigBuilderPlugin.getActiveTempBasals().getCalculationToTime(time).round(); -/* - if (basalIob.basaliob > 0) { - log.debug(new Date(time).toLocaleString() + " basaliob: " + basalIob.basaliob ); - } -*/ + IobTotal bolusIob = MainApp.getConfigBuilder().getCalculationToTimeTreatments(time).round(); + IobTotal basalIob = MainApp.getConfigBuilder().getCalculationToTimeTempBasals(time).round(); + IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round(); - if (time < new Date().getTime()) { + if (time < System.currentTimeMillis()) { iobTable.put(time, iobTotal); } return iobTotal; } + @Nullable 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).timeIndex < time) - return bucketed_data.get(index).timeIndex; + if (bucketed_data.get(index).date < time) + return bucketed_data.get(index).date; } return null; } - 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; + public static BasalData getBasalData(long time) { + long now = System.currentTimeMillis(); + 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(">>> getBasalData Cache miss " + new Date(time).toLocaleString()); } else { - //log.debug(">>> Cache miss " + new Date(time).toLocaleString()); - return null; + //log.debug(">>> getBasalData Cache hit " + new Date(time).toLocaleString()); + } + return retval; + } + + @Nullable + public static AutosensData getAutosensData(long time) { + synchronized (dataLock) { + long now = System.currentTimeMillis(); + 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(">>> getAutosensData Cache hit " + data.log(time)); + return data; + } else { + //log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString()); + return null; + } } } + @Nullable 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) { + if (data.time < System.currentTimeMillis() - 5 * 60 * 1000) { return null; } else { return data; @@ -393,129 +554,31 @@ public class IobCobCalculatorPlugin implements PluginBase { } public static IobTotal[] calculateIobArrayInDia() { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); // predict IOB out to DIA plus 30m - long time = new Date().getTime(); + long time = System.currentTimeMillis(); + time = roundUpTime(time); 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); + IobTotal iob = calculateFromTreatmentsAndTempsSynchronized(t); array[pos] = iob; pos++; } return array; } - public static AutosensResult detectSensitivity(long fromTime) { - //log.debug("Locking detectSensitivity"); + public static AutosensResult detectSensitivityWithLock(long fromTime, long toTime) { 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 = NSProfile.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); - - if (ConfigBuilderPlugin.getActiveProfile() == null || ConfigBuilderPlugin.getActiveProfile().getProfile() == null) { - log.debug("No profile available"); - return new AutosensResult(); - } - - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - - Double sens = profile.getIsf(NSProfile.secondsFromMidnight()); - - if (sens == null || profile.getMaxDailyBasal() == 0) { - log.debug("No profile available"); - return new AutosensResult(); - } - - 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) / NSProfile.toMgdl(sens, profile.getUnits()); - sensResult = "Excess insulin sensitivity detected"; - } else if (pResistant > 0) { // resistant - basalOff = pResistant * (60 / 5) / NSProfile.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(NSProfile.toMgdl(sens, profile.getUnits()) / ratio); - if (ratio != 1) { - log.debug("ISF adjusted from " + NSProfile.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; + return detectSensitivity(fromTime, toTime); } - //log.debug("Releasing detectSensitivity"); } + private static AutosensResult detectSensitivity(long fromTime, long toTime) { + return ConfigBuilderPlugin.getActiveSensitivity().detectSensitivity(fromTime, toTime); + } public static JSONArray convertToJSONArray(IobTotal[] iobArray) { JSONArray array = new JSONArray(); @@ -539,17 +602,52 @@ public class IobCobCalculatorPlugin implements PluginBase { @Subscribe public void onNewProfile(EventNewBasalProfile ev) { - if (MainApp.getConfigBuilder().getActiveProfile() == null) - return; - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (profile != null) { - dia = profile.getDia(); - } - if (ev.newNSProfile == null) { // on init no need of reset + if (MainApp.getConfigBuilder() == null) + return; // app still initializing + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) + return; // app still initializing + dia = profile.getDia(); + if (ev == null) { // on init no need of reset return; } synchronized (dataLock) { - log.debug("Invalidating cached data because of new profile from " + ev.from + ". IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); + 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(); + } + }); + } + + @Subscribe + public void onStatusEvent(EventPreferenceChange ev) { + if (ev.isChanged(R.string.key_openapsama_autosens_period) || + ev.isChanged(R.string.key_age) || + ev.isChanged(R.string.key_absorption_maxtime) + ) { + synchronized (dataLock) { + log.debug("Invalidating cached data because of preference change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); + iobTable = new LongSparseArray<>(); + autosensDataTable = new LongSparseArray<>(); + } + sHandler.post(new Runnable() { + @Override + public void run() { + calculateSensitivityData(); + } + }); + } + } + + @Subscribe + public void onStatusEvent(EventConfigBuilderChange ev) { + synchronized (dataLock) { + log.debug("Invalidating cached data because of configuration change. IOB: " + iobTable.size() + " Autosens: " + autosensDataTable.size() + " records"); iobTable = new LongSparseArray<>(); autosensDataTable = new LongSparseArray<>(); } @@ -570,7 +668,9 @@ public class IobCobCalculatorPlugin implements PluginBase { log.debug("Invalidating cached data to: " + new Date(time).toLocaleString()); for (int index = iobTable.size() - 1; index >= 0; index--) { if (iobTable.keyAt(index) > time) { - log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString()); + if (Config.logAutosensData) + if (Config.logAutosensData) + log.debug("Removing from iobTable: " + new Date(iobTable.keyAt(index)).toLocaleString()); iobTable.removeAt(index); } else { break; @@ -578,12 +678,22 @@ public class IobCobCalculatorPlugin implements PluginBase { } for (int index = autosensDataTable.size() - 1; index >= 0; index--) { if (autosensDataTable.keyAt(index) > time) { - log.debug("Removing from autosensDataTable: " + new Date(autosensDataTable.keyAt(index)).toLocaleString()); + 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 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/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 de295d8a6e..2fb143517b 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 @@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.Loop; import android.app.Activity; import android.os.Bundle; -import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,10 +18,11 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.Loop.events.EventLoopSetLastRunGui; import info.nightscout.androidaps.plugins.Loop.events.EventLoopUpdateGui; -public class LoopFragment extends Fragment implements View.OnClickListener { +public class LoopFragment extends SubscriberFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(LoopFragment.class); private static LoopPlugin loopPlugin; @@ -61,18 +61,6 @@ public class LoopFragment extends Fragment implements View.OnClickListener { return view; } - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - } - @Override public void onClick(View view) { switch (view.getId()) { @@ -110,7 +98,8 @@ public class LoopFragment extends Fragment implements View.OnClickListener { } - void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { 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 f6d319dd7f..6e459a03b2 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 @@ -10,8 +10,11 @@ import android.os.Handler; import android.os.HandlerThread; import android.support.v7.app.NotificationCompat; +import com.crashlytics.android.answers.Answers; +import com.crashlytics.android.answers.CustomEvent; import com.squareup.otto.Subscribe; +import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,7 +35,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. @@ -163,7 +169,7 @@ public class LoopPlugin implements PluginBase { if (loopSuspendedTill == 0) return 0; - long now = new Date().getTime(); + long now = System.currentTimeMillis(); long msecDiff = loopSuspendedTill - now; if (loopSuspendedTill <= now) { // time exceeded @@ -178,7 +184,7 @@ public class LoopPlugin implements PluginBase { if (loopSuspendedTill == 0) return false; - long now = new Date().getTime(); + long now = System.currentTimeMillis(); if (loopSuspendedTill <= now) { // time exceeded suspendTo(0L); @@ -192,7 +198,7 @@ public class LoopPlugin implements PluginBase { if (loopSuspendedTill == 0) return false; - long now = new Date().getTime(); + long now = System.currentTimeMillis(); if (loopSuspendedTill <= now) { // time exceeded suspendTo(0L); @@ -205,7 +211,7 @@ public class LoopPlugin implements PluginBase { public void invoke(String initiator, boolean allowNotification) { try { if (Config.logFunctionCalls) - log.debug("invoke"); + log.debug("invoke from " + initiator); ConstraintsInterface constraintsInterface = MainApp.getConfigBuilder(); if (!constraintsInterface.isLoopEnabled()) { log.debug(MainApp.sResources.getString(R.string.loopdisabled)); @@ -230,6 +236,12 @@ public class LoopPlugin implements PluginBase { return; } + if (configBuilder.getProfile() == null) { + log.debug(MainApp.sResources.getString(R.string.noprofileselected)); + MainApp.bus().post(new EventLoopSetLastRunGui(MainApp.sResources.getString(R.string.noprofileselected))); + return; + } + // Check if pump info is loaded if (configBuilder.getBaseBasalRate() < 0.01d) return; @@ -256,7 +268,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; @@ -267,6 +279,7 @@ public class LoopPlugin implements PluginBase { @Override public void run() { final PumpEnactResult applyResult = configBuilder.applyAPSRequest(resultAfterConstraints); + Answers.getInstance().logCustom(new CustomEvent("APSRequest")); if (applyResult.enacted || applyResult.success) { lastRun.setByPump = applyResult; lastRun.lastEnact = lastRun.lastAPSRun; @@ -316,7 +329,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/NSClientInternal/NSClientInternalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/NSClientInternalFragment.java index c3e8c777c6..164e9902df 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,12 +28,13 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventPreferenceChange; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; 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 View.OnClickListener, CompoundButton.OnCheckedChangeListener { +public class NSClientInternalFragment extends SubscriberFragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(NSClientInternalFragment.class); static NSClientInternalPlugin nsClientInternalPlugin; @@ -58,8 +59,6 @@ public class NSClientInternalFragment extends Fragment implements View.OnClickLi private CheckBox autoscrollCheckbox; private CheckBox pausedCheckbox; - String status = ""; - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -119,7 +118,7 @@ public class NSClientInternalFragment extends Fragment implements View.OnClickLi builder.setMessage("Clear queue? All data in queue will be lost!"); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - getPlugin().queue().clearQueue(); + UploadQueue.clearQueue(); updateGUI(); Answers.getInstance().logCustom(new CustomEvent("NSClientClearQueue")); } @@ -152,36 +151,25 @@ public class NSClientInternalFragment extends Fragment implements View.OnClickLi } } - @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 EventNSClientUpdateGUI ev) { updateGUI(); } - private void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { @Override public void run() { - logTextView.setText(getPlugin().textLog); + NSClientInternalPlugin.updateLog(); + logTextView.setText(NSClientInternalPlugin.textLog); if (getPlugin().autoscroll) { logScrollview.fullScroll(ScrollView.FOCUS_DOWN); } urlTextView.setText(getPlugin().url()); - Spanned queuetext = Html.fromHtml(MainApp.sResources.getString(R.string.queue) + " " + getPlugin().queue().size() + ""); + Spanned queuetext = Html.fromHtml(MainApp.sResources.getString(R.string.queue) + " " + UploadQueue.size() + ""); queueTextView.setText(queuetext); statusTextView.setText(getPlugin().status); } 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 07c34cda8c..b33d1cb2c3 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 @@ -9,17 +9,16 @@ import android.os.HandlerThread; import android.os.IBinder; import android.text.Html; import android.text.Spanned; -import android.text.TextUtils; import com.squareup.otto.Subscribe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -35,29 +34,28 @@ import info.nightscout.utils.ToastUtils; public class NSClientInternalPlugin implements PluginBase { private static Logger log = LoggerFactory.getLogger(NSClientInternalPlugin.class); - boolean fragmentEnabled = true; - boolean fragmentVisible = true; + private boolean fragmentEnabled = true; + private boolean fragmentVisible = true; static public Handler handler; - static private HandlerThread handlerThread; - public List listLog = new ArrayList(); - public Spanned textLog = Html.fromHtml(""); + private static List listLog = new ArrayList<>(); + static Spanned textLog = Html.fromHtml(""); public boolean paused = false; - public boolean autoscroll = true; + boolean autoscroll = true; public String status = ""; public NSClientService nsClientService = null; - public NSClientInternalPlugin() { + NSClientInternalPlugin() { MainApp.bus().register(this); paused = SP.getBoolean(R.string.key_nsclientinternal_paused, false); autoscroll = SP.getBoolean(R.string.key_nsclientinternal_autoscroll, true); if (handler == null) { - handlerThread = new HandlerThread(NSClientInternalPlugin.class.getSimpleName() + "Handler"); + HandlerThread handlerThread = new HandlerThread(NSClientInternalPlugin.class.getSimpleName() + "Handler"); handlerThread.start(); handler = new Handler(handlerThread.getLooper()); } @@ -115,7 +113,7 @@ public class NSClientInternalPlugin implements PluginBase { @Override public boolean showInList(int type) { - return true; + return !Config.NSCLIENT; } @Override @@ -128,7 +126,7 @@ public class NSClientInternalPlugin implements PluginBase { if (type == GENERAL) this.fragmentVisible = fragmentVisible; } - ServiceConnection mConnection = new ServiceConnection() { + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { log.debug("Service is disconnected"); @@ -161,45 +159,44 @@ public class NSClientInternalPlugin implements PluginBase { MainApp.bus().post(new EventNSClientUpdateGUI()); } - public void clearLog() { + synchronized void clearLog() { handler.post(new Runnable() { @Override public void run() { - listLog = new ArrayList(); - updateLog(); + listLog = new ArrayList<>(); + MainApp.bus().post(new EventNSClientUpdateGUI()); } }); } - private void addToLog(final EventNSClientNewLog ev) { + private synchronized void addToLog(final EventNSClientNewLog ev) { handler.post(new Runnable() { @Override public void run() { - SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); listLog.add(ev); // remove the first line if log is too large if (listLog.size() >= Constants.MAX_LOG_LINES) { listLog.remove(0); } - updateLog(); + MainApp.bus().post(new EventNSClientUpdateGUI()); } }); } - private void updateLog() { + static synchronized void updateLog() { try { - Spanned newTextLog = Html.fromHtml(""); - for (EventNSClientNewLog log : listLog) { - newTextLog = (Spanned) TextUtils.concat(newTextLog, log.toHtml()); + StringBuilder newTextLog = new StringBuilder(); + List temporaryList = new ArrayList<>(listLog); + for (EventNSClientNewLog log : temporaryList) { + newTextLog.append(log.toPreparedHtml()); } - textLog = newTextLog; - MainApp.bus().post(new EventNSClientUpdateGUI()); + textLog = Html.fromHtml(newTextLog.toString()); } catch (OutOfMemoryError e) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), "Out of memory!\nStop using this phone !!!", R.raw.error); } } - public void resend(String reason) { + void resend(String reason) { if (nsClientService != null) nsClientService.resend(reason); } 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 d2696dce11..76a2855478 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 @@ -50,7 +50,7 @@ public class UploadQueue { public void run() { log.debug("QUEUE adding: " + dbr.data); MainApp.getDbHelper().create(dbr); - NSClientInternalPlugin plugin = (NSClientInternalPlugin) MainApp.getSpecificPlugin(NSClientInternalPlugin.class); + NSClientInternalPlugin plugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); if (plugin != null) { plugin.resend("newdata"); } @@ -113,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/BroadcastAckAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAckAlarm.java new file mode 100644 index 0000000000..216fa3d19a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAckAlarm.java @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSAlarm; +import info.nightscout.utils.SP; + +/** + * Created by mike on 11.06.2017. + */ + +public class BroadcastAckAlarm { + private static Logger log = LoggerFactory.getLogger(BroadcastAckAlarm.class); + + public static void handleClearAlarm(NSAlarm originalAlarm, Context context, long silenceTimeInMsec) { + + Bundle bundle = new Bundle(); + bundle.putInt("level", originalAlarm.getLevel()); + bundle.putString("group", originalAlarm.getGroup()); + bundle.putLong("silenceTime", silenceTimeInMsec); + Intent intent = new Intent(Intents.ACTION_ACK_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putInt("level", originalAlarm.getLevel()); + bundle.putString("group", originalAlarm.getGroup()); + bundle.putLong("silenceTime", silenceTimeInMsec); + intent = new Intent(Intents.ACTION_ACK_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAlarm.java new file mode 100644 index 0000000000..0fee6600bd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAlarm.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; + +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; + +/** + * Created by mike on 26.06.2016. + */ +public class BroadcastAlarm { + private static Logger log = LoggerFactory.getLogger(BroadcastAlarm.class); + + public static void handleAlarm(JSONObject alarm, Context context) { + Bundle bundle = new Bundle(); + bundle.putString("data", alarm.toString()); + Intent intent = new Intent(Intents.ACTION_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("data", alarm.toString()); + intent = new Intent(Intents.ACTION_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAnnouncement.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAnnouncement.java new file mode 100644 index 0000000000..9b133c2551 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastAnnouncement.java @@ -0,0 +1,44 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; + +/** + * Created by mike on 26.06.2016. + */ +public class BroadcastAnnouncement { + private static Logger log = LoggerFactory.getLogger(BroadcastAnnouncement.class); + + public static void handleAnnouncement(JSONObject announcement, Context context) { + Bundle bundle = new Bundle(); + bundle.putString("data", announcement.toString()); + Intent intent = new Intent(Intents.ACTION_ANNOUNCEMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("data", announcement.toString()); + intent = new Intent(Intents.ACTION_ANNOUNCEMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastCals.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastCals.java index 58a24e825c..7580a00088 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastCals.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastCals.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import org.json.JSONArray; import org.slf4j.Logger; @@ -11,7 +12,10 @@ import org.slf4j.LoggerFactory; import java.util.List; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; /** * Created by mike on 26.06.2016. @@ -19,16 +23,24 @@ import info.nightscout.androidaps.Services.Intents; public class BroadcastCals { private static Logger log = LoggerFactory.getLogger(BroadcastCals.class); - public void handleNewCal(JSONArray cals, Context context, boolean isDelta) { + public static void handleNewCal(JSONArray cals, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("cals", cals.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_CAL); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("CAL " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("cals", cals.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_CAL); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastClearAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastClearAlarm.java new file mode 100644 index 0000000000..23406837a7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastClearAlarm.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; + +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; + +/** + * Created by mike on 26.06.2016. + */ +public class BroadcastClearAlarm { + private static Logger log = LoggerFactory.getLogger(BroadcastClearAlarm.class); + + public static void handleClearAlarm(JSONObject clearalarm, Context context) { + Bundle bundle = new Bundle(); + bundle.putString("data", clearalarm.toString()); + Intent intent = new Intent(Intents.ACTION_CLEAR_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("data", clearalarm.toString()); + intent = new Intent(Intents.ACTION_CLEAR_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastDeviceStatus.java index 64fd72b36a..a912fc5d3c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastDeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastDeviceStatus.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import org.json.JSONArray; import org.json.JSONObject; @@ -12,34 +13,58 @@ import org.slf4j.LoggerFactory; import java.util.List; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; public class BroadcastDeviceStatus { private static Logger log = LoggerFactory.getLogger(BroadcastDeviceStatus.class); - public void handleNewDeviceStatus(JSONObject status, Context context, boolean isDelta) { + public static void handleNewDeviceStatus(JSONObject status, Context context, boolean isDelta) { Bundle bundle = new Bundle(); bundle.putString("devicestatus", status.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("DEVICESTATUS " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("devicestatus", status.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } - public void handleNewDeviceStatus(JSONArray statuses, Context context, boolean isDelta) { - Bundle bundle = new Bundle(); - bundle.putString("devicestatuses", statuses.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + public static void handleNewDeviceStatus(JSONArray statuses, Context context, boolean isDelta) { - log.debug("DEVICESTATUS " + x.size() + " receivers"); + List splitted = BroadcastTreatment.splitArray(statuses); + for (JSONArray part: splitted) { + Bundle bundle = new Bundle(); + bundle.putString("devicestatuses", part.toString()); + bundle.putBoolean("delta", isDelta); + Intent intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + } + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + splitted = BroadcastTreatment.splitArray(statuses); + for (JSONArray part : splitted) { + Bundle bundle = new Bundle(); + bundle.putString("devicestatuses", part.toString()); + bundle.putBoolean("delta", isDelta); + Intent intent = new Intent(Intents.ACTION_NEW_DEVICESTATUS); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastMbgs.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastMbgs.java index 33669e1852..a715747791 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastMbgs.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastMbgs.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import org.json.JSONArray; import org.slf4j.Logger; @@ -11,7 +12,10 @@ import org.slf4j.LoggerFactory; import java.util.List; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; /** * Created by mike on 26.06.2016. @@ -19,16 +23,24 @@ import info.nightscout.androidaps.Services.Intents; public class BroadcastMbgs { private static Logger log = LoggerFactory.getLogger(BroadcastMbgs.class); - public void handleNewMbg(JSONArray mbgs, Context context, boolean isDelta) { + public static void handleNewMbg(JSONArray mbgs, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("mbgs", mbgs.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_MBG); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("MBG " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("mbgs", mbgs.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_MBG); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } } 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..3802b09657 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 @@ -4,14 +4,18 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; +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.ProfileStore; +import info.nightscout.utils.SP; /** @@ -20,18 +24,25 @@ 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 static 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); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("PROFILE " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("profile", profile.getData().toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_PROFILE); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastQueueStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastQueueStatus.java index ed2b01a27c..abc49be18a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastQueueStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastQueueStatus.java @@ -5,13 +5,18 @@ import android.content.Intent; import android.os.Bundle; import android.os.PowerManager; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; /** * Created by mike on 28.02.2016. */ public class BroadcastQueueStatus { - public void handleNewStatus(int size, Context context) { + public static void handleNewStatus(int size, Context context) { + + if(!SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) return; + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "sendQueue"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastSgvs.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastSgvs.java index 81a2621a77..d4193f3cb7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastSgvs.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastSgvs.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import org.json.JSONArray; import org.json.JSONObject; @@ -12,7 +13,10 @@ import org.slf4j.LoggerFactory; import java.util.List; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; /** * Created by mike on 22.02.2016. @@ -20,30 +24,45 @@ import info.nightscout.androidaps.Services.Intents; public class BroadcastSgvs { private static Logger log = LoggerFactory.getLogger(BroadcastSgvs.class); - public void handleNewSgv(JSONObject sgv, Context context, boolean isDelta) { + public static void handleNewSgv(JSONObject sgv, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("sgv", sgv.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_SGV); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("SGV " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("sgv", sgv.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_SGV); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } - public void handleNewSgv(JSONArray sgvs, Context context, boolean isDelta) { + public static void handleNewSgv(JSONArray sgvs, Context context, boolean isDelta) { Bundle bundle = new Bundle(); bundle.putString("sgvs", sgvs.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_SGV); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("SGV " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("sgvs", sgvs.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_SGV); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java index b99950c89b..7c6862cb14 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastStatus.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +13,11 @@ import org.slf4j.LoggerFactory; import java.util.List; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSStatus; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; +import info.nightscout.utils.SP; /** * Created by mike on 24.02.2016. @@ -22,14 +25,15 @@ import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientServ public class BroadcastStatus { private static Logger log = LoggerFactory.getLogger(BroadcastStatus.class); - public void handleNewStatus(NSStatus status, Context context, boolean isDelta) { + public static void handleNewStatus(NSSettingsStatus status, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); try { bundle.putString("nsclientversionname", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionName); bundle.putInt("nsclientversioncode", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); - }; + } bundle.putString("nightscoutversionname", NSClientService.nightscoutVersionName); bundle.putInt("nightscoutversioncode", NSClientService.nightscoutVersionCode); bundle.putString("status", status.getData().toString()); @@ -37,9 +41,24 @@ public class BroadcastStatus { Intent intent = new Intent(Intents.ACTION_NEW_STATUS); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("STATUS: " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + try { + bundle.putString("nsclientversionname", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionName); + bundle.putInt("nsclientversioncode", MainApp.instance().getPackageManager().getPackageInfo(MainApp.instance().getPackageName(), 0).versionCode); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + bundle.putString("nightscoutversionname", NSClientService.nightscoutVersionName); + bundle.putInt("nightscoutversioncode", NSClientService.nightscoutVersionCode); + bundle.putString("status", status.getData().toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_STATUS); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java index 9d1abe43e3..0d998a2bcd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java @@ -4,6 +4,8 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.os.TransactionTooLargeException; +import android.support.v4.content.LocalBroadcastManager; import org.json.JSONArray; import org.json.JSONException; @@ -11,10 +13,15 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.List; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; +import info.nightscout.utils.SP; +import info.nightscout.utils.ToastUtils; /** * Created by mike on 20.02.2016. @@ -22,86 +29,173 @@ import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; public class BroadcastTreatment { private static Logger log = LoggerFactory.getLogger(BroadcastTreatment.class); - public void handleNewTreatment(NSTreatment treatment, Context context, boolean isDelta) { + public static void handleNewTreatment(NSTreatment treatment, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("treatment", treatment.getData().toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("TREAT_ADD " + treatment.getEventType() + " " + x.size() + " receivers"); + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("treatment", treatment.getData().toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_NEW_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } - public void handleNewTreatment(JSONArray treatments, Context context, boolean isDelta) { - Bundle bundle = new Bundle(); - bundle.putString("treatments", treatments.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + public static void handleNewTreatment(JSONArray treatments, Context context, boolean isDelta) { - log.debug("TREAT_ADD " + treatments.length() + " " + x.size() + " receivers"); + List splitted = splitArray(treatments); + for (JSONArray part: splitted) { + Bundle bundle = new Bundle(); + bundle.putString("treatments", part.toString()); + bundle.putBoolean("delta", isDelta); + Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + } + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)){ + splitted = splitArray(treatments); + for (JSONArray part: splitted) { + Bundle bundle = new Bundle(); + bundle.putString("treatments", part.toString()); + bundle.putBoolean("delta", isDelta); + Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } } public void handleChangedTreatment(JSONObject treatment, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("treatment", treatment.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - try { - log.debug("TREAT_CHANGE " + treatment.getString("_id") + " " + x.size() + " receivers"); - } catch (JSONException e) {} + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("treatment", treatment.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } - public void handleChangedTreatment(JSONArray treatments, Context context, boolean isDelta) { - Bundle bundle = new Bundle(); - bundle.putString("treatments", treatments.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + public static void handleChangedTreatment(JSONArray treatments, Context context, boolean isDelta) { - log.debug("TREAT_CHANGE " + treatments.length() + " " + x.size() + " receivers"); + List splitted = splitArray(treatments); + for (JSONArray part : splitted) { + Bundle bundle = new Bundle(); + bundle.putString("treatments", part.toString()); + bundle.putBoolean("delta", isDelta); + Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + } + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + splitted = splitArray(treatments); + for (JSONArray part : splitted) { + Bundle bundle = new Bundle(); + bundle.putString("treatments", part.toString()); + bundle.putBoolean("delta", isDelta); + Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } } - public void handleRemovedTreatment(JSONObject treatment, Context context, boolean isDelta) { + public static void handleRemovedTreatment(JSONObject treatment, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("treatment", treatment.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - try { - log.debug("TREAT_REMOVE " + treatment.getString("_id") + " " + x.size() + " receivers"); - } catch (JSONException e) {} + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("treatment", treatment.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } - public void handleRemovedTreatment(JSONArray treatments, Context context, boolean isDelta) { + public static void handleRemovedTreatment(JSONArray treatments, Context context, boolean isDelta) { + Bundle bundle = new Bundle(); bundle.putString("treatments", treatments.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); - List x = context.getPackageManager().queryBroadcastReceivers(intent, 0); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - log.debug("TREAT_REMOVE " + treatments.length() + " treatments " + x.size() + " receivers"); + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("treatments", treatments.toString()); + bundle.putBoolean("delta", isDelta); + intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } } + + public static List splitArray(JSONArray array) { + List ret = new ArrayList<>(); + try { + int size = array.length(); + int count = 0; + JSONArray newarr = null; + for (int i = 0; i < size; i++) { + if (count == 0) { + if (newarr != null) { + ret.add(newarr); + } + newarr = new JSONArray(); + count = 200; + } + newarr.put(array.get(i)); + --count; + } + if (newarr != null && newarr.length() > 0) { + ret.add(newarr); + } + } catch (JSONException e) { + e.printStackTrace(); + ret = new ArrayList<>(); + ret.add(array); + } + return ret; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastUrgentAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastUrgentAlarm.java new file mode 100644 index 0000000000..c332be03af --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastUrgentAlarm.java @@ -0,0 +1,43 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; + +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.utils.SP; + +/** + * Created by mike on 26.06.2016. + */ +public class BroadcastUrgentAlarm { + private static Logger log = LoggerFactory.getLogger(BroadcastUrgentAlarm.class); + + public static void handleUrgentAlarm(JSONObject urgentalarm, Context context) { + Bundle bundle = new Bundle(); + bundle.putString("data", urgentalarm.toString()); + Intent intent = new Intent(Intents.ACTION_URGENT_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); + + if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + bundle = new Bundle(); + bundle.putString("data", urgentalarm.toString()); + intent = new Intent(Intents.ACTION_URGENT_ALARM); + intent.putExtras(bundle); + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + context.sendBroadcast(intent); + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/AlarmAck.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/AlarmAck.java new file mode 100644 index 0000000000..109331b34b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/AlarmAck.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.data; + +/** + * Created by mike on 11.06.2017. + */ + +public class AlarmAck { + public Integer level = null; + public String group = null; + public Long silenceTime = null; +} 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/NSAlarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSAlarm.java new file mode 100644 index 0000000000..f7a7f79303 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSAlarm.java @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.data; + +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Created by mike on 11.06.2017. + */ + +public class NSAlarm { + JSONObject data; + + public NSAlarm(JSONObject data) { + this.data = data; + } + + public int getLevel() { + int retval = 0; + if (data.has("level")) { + try { + retval = data.getInt("level"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return retval; + } + + public String getGroup() { + String retval = "N/A"; + if (data.has("group")) { + try { + retval = data.getString("group"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return retval; + } + + public String getTile() { + String retval = "N/A"; + if (data.has("title")) { + try { + retval = data.getString("title"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return retval; + } + + public String getMessage() { + String retval = "N/A"; + if (data.has("message")) { + try { + retval = data.getString("message"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return retval; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java new file mode 100644 index 0000000000..8ce3fc87e2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSDeviceStatus.java @@ -0,0 +1,387 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.data; + +import android.text.Html; +import android.text.Spanned; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import info.nightscout.androidaps.R; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.Round; +import info.nightscout.utils.SP; + +/** + * Created by mike on 25.06.2017. + */ + +/* +{ + "_id": "594fdcec327b83c81b6b8c0f", + "device": "openaps://Sony D5803", + "pump": { + "battery": { + "percent": 100 + }, + "status": { + "status": "normal", + "timestamp": "2017-06-25T15:50:14Z" + }, + "extended": { + "Version": "1.5-ac98852-2017.06.25", + "PumpIOB": 1.13, + "LastBolus": "25. 6. 2017 17:25:00", + "LastBolusAmount": 0.3, + "BaseBasalRate": 0.4, + "ActiveProfile": "2016 +30%" + }, + "reservoir": 109, + "clock": "2017-06-25T15:55:10Z" + }, + "openaps": { + "suggested": { + "temp": "absolute", + "bg": 115.9, + "tick": "+5", + "eventualBG": 105, + "snoozeBG": 105, + "predBGs": { + "IOB": [116, 114, 112, 110, 109, 107, 106, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 107] + }, + "COB": 0, + "IOB": -0.035, + "reason": "COB: 0, Dev: -18, BGI: 0.43, ISF: 216, Target: 99; Eventual BG 105 > 99 but Min. Delta -2.60 < Exp. Delta 0.1; setting current basal of 0.4 as temp. Suggested rate is same as profile rate, no temp basal is active, doing nothing", + "timestamp": "2017-06-25T15:55:10Z" + }, + "iob": { + "iob": -0.035, + "basaliob": -0.035, + "activity": -0.0004, + "time": "2017-06-25T15:55:10Z" + } + }, + "uploaderBattery": 93, + "created_at": "2017-06-25T15:55:10Z", + "NSCLIENT_ID": 1498406118857 +} + */ +public class NSDeviceStatus { + + private static NSDeviceStatus instance = null; + + public static NSDeviceStatus getInstance() { + if (instance == null) + instance = new NSDeviceStatus(); + return instance; + } + + private JSONObject data = null; + + public NSDeviceStatus() { + } + + public NSDeviceStatus setData(JSONObject obj) { + this.data = obj; + updatePumpData(obj); + updateOpenApsData(obj); + updateUploaderData(obj); + return this; + } + + public String getDevice() { + try { + if (data.has("device")) { + String device = data.getString("device"); + if (device.startsWith("openaps://")) { + device = device.substring(10); + return device; + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + return ""; + } + + public static class Levels { + static int URGENT = 2; + static int WARN = 1; + static int INFO = 0; + int LOW = -1; + int LOWEST = -2; + static int NONE = -3; + } + + // ***** PUMP DATA ****** + + static DeviceStatusPumpData deviceStatusPumpData = null; + + public Spanned getExtendedPumpStatus() { + if (deviceStatusPumpData.extended != null) + return deviceStatusPumpData.extended; + return Html.fromHtml(""); + } + + public Spanned getPumpStatus() { + //String[] ALL_STATUS_FIELDS = {"reservoir", "battery", "clock", "status", "device"}; + + if (deviceStatusPumpData == null) + return Html.fromHtml(""); + + StringBuilder string = new StringBuilder(); + // test warning level + int level = Levels.INFO; + long now = System.currentTimeMillis(); + if (deviceStatusPumpData.clock + NSSettingsStatus.getInstance().extendedPumpSettings("urgentClock") * 60 * 1000L < now) + level = Levels.URGENT; + else if (deviceStatusPumpData.reservoir < NSSettingsStatus.getInstance().extendedPumpSettings("urgentRes")) + level = Levels.URGENT; + else if (deviceStatusPumpData.isPercent && deviceStatusPumpData.percent < NSSettingsStatus.getInstance().extendedPumpSettings("urgentBattP")) + level = Levels.URGENT; + else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < NSSettingsStatus.getInstance().extendedPumpSettings("urgentBattV")) + level = Levels.URGENT; + else if (deviceStatusPumpData.clock + NSSettingsStatus.getInstance().extendedPumpSettings("warnClock") < now) + level = Levels.WARN; + else if (deviceStatusPumpData.reservoir < NSSettingsStatus.getInstance().extendedPumpSettings("warnRes")) + level = Levels.WARN; + else if (deviceStatusPumpData.isPercent && deviceStatusPumpData.percent < NSSettingsStatus.getInstance().extendedPumpSettings("warnBattP")) + level = Levels.WARN; + else if (!deviceStatusPumpData.isPercent && deviceStatusPumpData.voltage < NSSettingsStatus.getInstance().extendedPumpSettings("warnBattV")) + level = Levels.WARN; + + string.append(""); + if (level == Levels.WARN) string.append("yellow\">"); + if (level == Levels.URGENT) string.append("red\">"); + + String fields = NSSettingsStatus.getInstance().pumpExtentendedSettingsFields(); + + if (fields.contains("reservoir")) { + string.append((int) deviceStatusPumpData.reservoir).append("U "); + } + + if (fields.contains("battery") && deviceStatusPumpData.isPercent) { + string.append(deviceStatusPumpData.percent).append("% "); + } + if (fields.contains("battery") && !deviceStatusPumpData.isPercent) { + string.append(Round.roundTo(deviceStatusPumpData.voltage, 0.001d)).append(" "); + } + + if (fields.contains("clock")) { + string.append(DateUtil.minAgo(deviceStatusPumpData.clock)).append(" "); + } + + if (fields.contains("status")) { + string.append(deviceStatusPumpData.status).append(" "); + } + + if (fields.contains("device")) { + string.append(getDevice()).append(" "); + } + + + string.append(""); // color + + return Html.fromHtml(string.toString()); + } + + static class DeviceStatusPumpData { + long clock = 0L; + boolean isPercent = false; + int percent = 0; + double voltage = 0; + + String status = "N/A"; + double reservoir = 0d; + + Spanned extended = null; + } + + public void updatePumpData(JSONObject object) { + try { + JSONObject pump = data != null && data.has("pump") ? data.getJSONObject("pump") : new JSONObject(); + + long clock = 0L; + if (pump.has("clock")) + clock = DateUtil.fromISODateString(pump.getString("clock")).getTime(); + // check if this is new data + if (clock == 0 || deviceStatusPumpData != null && clock < deviceStatusPumpData.clock) + return; + // create new status and process data + deviceStatusPumpData = new DeviceStatusPumpData(); + deviceStatusPumpData.clock = clock; + if (pump.has("status") && pump.getJSONObject("status").has("status")) + deviceStatusPumpData.status = pump.getJSONObject("status").getString("status"); + if (pump.has("reservoir")) + deviceStatusPumpData.reservoir = pump.getDouble("reservoir"); + if (pump.has("battery") && pump.getJSONObject("battery").has("percent")) { + deviceStatusPumpData.isPercent = true; + deviceStatusPumpData.percent = pump.getJSONObject("battery").getInt("percent"); + } else if (pump.has("battery") && pump.getJSONObject("battery").has("voltage")) { + deviceStatusPumpData.isPercent = false; + deviceStatusPumpData.voltage = pump.getJSONObject("battery").getDouble("voltage"); + } + if (pump.has("extended")) { + JSONObject extendedJson = pump.getJSONObject("extended"); + StringBuilder exteneded = new StringBuilder(); + Iterator keys = extendedJson.keys(); + while (keys.hasNext()) { + String key = (String) keys.next(); + String value = extendedJson.getString(key); + exteneded.append("").append(key).append(": ").append(value).append("
"); + } + deviceStatusPumpData.extended = Html.fromHtml(exteneded.toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + + // ********* OpenAPS data *********** + + static DeviceStatusOpenAPSData deviceStatusOpenAPSData = new DeviceStatusOpenAPSData(); + + static class DeviceStatusOpenAPSData { + long clockSuggested = 0L; + long clockEnacted = 0L; + + JSONObject suggested = null; + JSONObject enacted = null; + } + + public void updateOpenApsData(JSONObject object) { + try { + JSONObject openaps = object.has("openaps") ? object.getJSONObject("openaps") : new JSONObject(); + JSONObject suggested = openaps.has("suggested") ? openaps.getJSONObject("suggested") : new JSONObject(); + JSONObject enacted = openaps.has("enacted") ? openaps.getJSONObject("enacted") : new JSONObject(); + + long clock = 0L; + if (suggested.has("timestamp")) + clock = DateUtil.fromISODateString(suggested.getString("timestamp")).getTime(); + // check if this is new data + if (clock != 0 && clock > deviceStatusOpenAPSData.clockSuggested) { + deviceStatusOpenAPSData.suggested = suggested; + deviceStatusOpenAPSData.clockSuggested = clock; + } + + clock = 0L; + if (enacted.has("timestamp")) + clock = DateUtil.fromISODateString(enacted.getString("timestamp")).getTime(); + // check if this is new data + if (clock != 0 && clock > deviceStatusOpenAPSData.clockEnacted) { + deviceStatusOpenAPSData.enacted = enacted; + deviceStatusOpenAPSData.clockEnacted = clock; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public Spanned getOpenApsStatus() { + StringBuilder string = new StringBuilder(); + // test warning level + int level = Levels.INFO; + long now = System.currentTimeMillis(); + if (deviceStatusOpenAPSData.clockSuggested != 0 && deviceStatusOpenAPSData.clockSuggested + SP.getInt(R.string.key_nsalarm_urgent_staledatavalue, 16) * 60 * 1000L < now) + level = Levels.URGENT; + else if (deviceStatusOpenAPSData.clockSuggested != 0 && deviceStatusOpenAPSData.clockSuggested + SP.getInt(R.string.key_nsalarm_staledatavalue, 16) * 60 * 1000L < now) + level = Levels.WARN; + + string.append(""); + if (level == Levels.WARN) string.append("yellow\">"); + if (level == Levels.URGENT) string.append("red\">"); + + if (deviceStatusOpenAPSData.clockSuggested != 0) { + string.append(DateUtil.minAgo(deviceStatusOpenAPSData.clockSuggested)).append(" "); + } + string.append(""); // color + + return Html.fromHtml(string.toString()); + } + + public Spanned getExtendedOpenApsStatus() { + StringBuilder string = new StringBuilder(); + + try { + if (deviceStatusOpenAPSData.enacted != null && deviceStatusOpenAPSData.clockEnacted != deviceStatusOpenAPSData.clockSuggested) + string.append("").append(DateUtil.minAgo(deviceStatusOpenAPSData.clockEnacted)).append(" ").append(deviceStatusOpenAPSData.enacted.getString("reason")).append("
"); + if (deviceStatusOpenAPSData.suggested != null) + string.append("").append(DateUtil.minAgo(deviceStatusOpenAPSData.clockSuggested)).append(" ").append(deviceStatusOpenAPSData.suggested.getString("reason")).append("
"); + return Html.fromHtml(string.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + return Html.fromHtml(""); + } + + // ********* Uploader data *********** + + public static HashMap uploaders = new HashMap<>(); + + static class Uploader { + long clock = 0L; + int battery = 0; + } + + public void updateUploaderData(JSONObject object) { + try { + + long clock = 0L; + if (object.has("created_at")) + clock = DateUtil.fromISODateString(object.getString("created_at")).getTime(); + String device = getDevice(); + Integer battery = null; + if (object.has("uploaderBattery")) + battery = object.getInt("uploaderBattery"); + else if (object.has("uploader")) { + if (object.getJSONObject("uploader").has("battery")) + battery = object.getJSONObject("uploader").getInt("battery"); + } + Uploader uploader = uploaders.get(device); + // check if this is new data + if (clock != 0 && (uploader != null && clock > uploader.clock || uploader == null)) { + if (uploader == null) + uploader = new Uploader(); + uploader.battery = battery; + uploader.clock = clock; + uploaders.put(device, uploader); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public String getUploaderStatus() { + Iterator iter = uploaders.entrySet().iterator(); + int minBattery = 100; + while(iter.hasNext()) { + Map.Entry pair = (Map.Entry) iter.next(); + Uploader uploader = (Uploader) pair.getValue(); + if (minBattery > uploader.battery) + minBattery = uploader.battery; + } + + return minBattery + "%"; + } + + public Spanned getExtendedUploaderStatus() { + StringBuilder string = new StringBuilder(); + + Iterator iter = uploaders.entrySet().iterator(); + while(iter.hasNext()) { + Map.Entry pair = (Map.Entry) iter.next(); + Uploader uploader = (Uploader) pair.getValue(); + String device = (String) pair.getKey(); + string.append("").append(device).append(": ").append(uploader.battery).append("%
"); + } + + return Html.fromHtml(string.toString()); + } + +} 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 eb320ebfdb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSProfile.java +++ /dev/null @@ -1,494 +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 Constants.defaultDIA; - } -/* - 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 null; - } - - 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 int 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/plugins/NSClientInternal/data/NSSettingsStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSettingsStatus.java new file mode 100644 index 0000000000..c2c3aa036f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSettingsStatus.java @@ -0,0 +1,361 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.data; + +import android.support.annotation.Nullable; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Date; +import java.util.Objects; + +/* + { + "status": "ok", + "name": "Nightscout", + "version": "0.10.0-dev-20170423", + "versionNum": 1000, + "serverTime": "2017-06-12T07:46:56.006Z", + "apiEnabled": true, + "careportalEnabled": true, + "boluscalcEnabled": true, + "head": "96ee154", + "settings": { + "units": "mmol", + "timeFormat": 24, + "nightMode": false, + "editMode": true, + "showRawbg": "always", + "customTitle": "Bara's CGM", + "theme": "colors", + "alarmUrgentHigh": true, + "alarmUrgentHighMins": [30, 60, 90, 120], + "alarmHigh": true, + "alarmHighMins": [30, 60, 90, 120], + "alarmLow": true, + "alarmLowMins": [15, 30, 45, 60], + "alarmUrgentLow": true, + "alarmUrgentLowMins": [15, 30, 45], + "alarmUrgentMins": [30, 60, 90, 120], + "alarmWarnMins": [30, 60, 90, 120], + "alarmTimeagoWarn": true, + "alarmTimeagoWarnMins": 15, + "alarmTimeagoUrgent": true, + "alarmTimeagoUrgentMins": 30, + "language": "cs", + "scaleY": "linear", + "showPlugins": "careportal boluscalc food bwp cage sage iage iob cob basal ar2 delta direction upbat rawbg", + "showForecast": "ar2", + "focusHours": 3, + "heartbeat": 60, + "baseURL": "http:\/\/barascgm.sysop.cz:82", + "authDefaultRoles": "readable", + "thresholds": { + "bgHigh": 252, + "bgTargetTop": 180, + "bgTargetBottom": 72, + "bgLow": 71 + }, + "DEFAULT_FEATURES": ["bgnow", "delta", "direction", "timeago", "devicestatus", "upbat", "errorcodes", "profile"], + "alarmTypes": ["predict"], + "enable": ["careportal", "boluscalc", "food", "bwp", "cage", "sage", "iage", "iob", "cob", "basal", "ar2", "rawbg", "pushover", "bgi", "pump", "openaps", "pushover", "treatmentnotify", "bgnow", "delta", "direction", "timeago", "devicestatus", "upbat", "profile", "ar2"] + }, + "extendedSettings": { + "pump": { + "fields": "reservoir battery clock", + "urgentBattP": 26, + "warnBattP": 51 + }, + "openaps": { + "enableAlerts": true + }, + "cage": { + "alerts": true, + "display": "days", + "urgent": 96, + "warn": 72 + }, + "sage": { + "alerts": true, + "urgent": 336, + "warn": 168 + }, + "iage": { + "alerts": true, + "urgent": 150, + "warn": 120 + }, + "basal": { + "render": "default" + }, + "profile": { + "history": true, + "multiple": true + }, + "devicestatus": { + "advanced": true + } + }, + "activeProfile": "2016 +30%" + } + */ +public class NSSettingsStatus { + private static NSSettingsStatus instance = null; + + public static NSSettingsStatus getInstance() { + if (instance == null) + instance = new NSSettingsStatus(); + return instance; + } + + private JSONObject data = null; + + public NSSettingsStatus() { + } + + public NSSettingsStatus setData(JSONObject obj) { + this.data = obj; + return this; + } + + public String getName() { + return getStringOrNull("name"); + } + + public String getVersion() { + return getStringOrNull("version"); + } + + public Integer getVersionNum() { + return getIntegerOrNull("versionNum"); + } + + public Date getServerTime() { + return getDateOrNull("versionNum"); + } + + public boolean getApiEnabled() { + return getBooleanOrNull("apiEnabled"); + } + + public boolean getCareportalEnabled() { + return getBooleanOrNull("careportalEnabled"); + } + + public boolean getBoluscalcEnabled() { + return getBooleanOrNull("boluscalcEnabled"); + } + + public String getHead() { + return getStringOrNull("head"); + } + + public String getSettings() { + return getStringOrNull("settings"); + } + + public JSONObject getExtendedSettings() { + try { + String extended = getStringOrNull("extendedSettings"); + if (extended != null) + return new JSONObject(extended); + + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + + } + + public String getActiveProfile() { + return getStringOrNull("activeProfile"); + } + + // "bgHigh": 252, + // "bgTargetTop": 180, + // "bgTargetBottom": 72, + // "bgLow": 71 + @Nullable + public Double getThreshold(String what) { + try { + if (data == null) + return null; + String settings = getSettings(); + if (settings != null) { + JSONObject settingsO = new JSONObject(settings); + if (settingsO.has("thresholds")) { + JSONObject tObject = settingsO.getJSONObject("thresholds"); + if (tObject.has(what)) { + Double result = tObject.getDouble(what); + return result; + } + } + if (settingsO.has("alarmTimeagoWarnMins") && Objects.equals(what, "alarmTimeagoWarnMins")){ + Double result = settingsO.getDouble(what); + return result; + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + private String getStringOrNull(String key) { + String ret = null; + if(data == null) return null; + if (data.has(key)) { + try { + ret = data.getString(key); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return ret; + } + + private Integer getIntegerOrNull(String key) { + Integer ret = null; + if (data.has(key)) { + try { + ret = data.getInt(key); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return ret; + } + + private Long getLongOrNull(String key) { + Long ret = null; + if (data.has(key)) { + try { + ret = data.getLong(key); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return ret; + } + + private Date getDateOrNull(String key) { + Date ret = null; + if (data.has(key)) { + try { + ret = new Date(data.getString(key)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return ret; + } + + private boolean getBooleanOrNull(String key) { + boolean ret = false; + if (data.has(key)) { + try { + ret = data.getBoolean(key); + } catch (JSONException e) { + e.printStackTrace(); + } + } + return ret; + } + + // ***** PUMP STATUS ****** + + public JSONObject getData() { + return data; + } + + /* + , warnClock: sbx.extendedSettings.warnClock || 30 + , urgentClock: sbx.extendedSettings.urgentClock || 60 + , warnRes: sbx.extendedSettings.warnRes || 10 + , urgentRes: sbx.extendedSettings.urgentRes || 5 + , warnBattV: sbx.extendedSettings.warnBattV || 1.35 + , urgentBattV: sbx.extendedSettings.urgentBattV || 1.3 + , warnBattP: sbx.extendedSettings.warnBattP || 30 + , urgentBattP: sbx.extendedSettings.urgentBattP || 20 + , enableAlerts: sbx.extendedSettings.enableAlerts || false + */ + + public double extendedPumpSettings(String setting) { + try { + JSONObject pump = extentendedPumpSettings(); + switch (setting) { + case "warnClock": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "urgentClock": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "warnRes": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "urgentRes": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "warnBattV": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "urgentBattV": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "warnBattP": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + case "urgentBattP": + return pump != null && pump.has(setting) ? pump.getDouble(setting) : 30; + } + } catch (JSONException e) { + e.printStackTrace(); + } + return 0d; + } + + + @Nullable + public JSONObject extentendedPumpSettings() { + try { + JSONObject extended = getExtendedSettings(); + if(extended == null) return null; + if (extended.has("pump")) { + JSONObject pump = extended.getJSONObject("pump"); + return pump; + } + } catch (JSONException e) { + e.printStackTrace(); + } + return null; + } + + public boolean pumpExtentendedSettingsEnabledAlerts() { + try { + JSONObject pump = extentendedPumpSettings(); + if (pump != null && pump.has("enableAlerts")) { + return pump.getBoolean("enableAlerts"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return false; + } + + public String pumpExtentendedSettingsFields() { + try { + JSONObject pump = extentendedPumpSettings(); + if (pump != null && pump.has("fields")) { + return pump.getString("fields"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return ""; + } + + public boolean openAPSEnabledAlerts() { + try { + JSONObject pump = extentendedPumpSettings(); + if (pump != null && pump.has("openaps")) { + return pump.getBoolean("enableAlerts"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return false; + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java index c8666f4306..78ddc7a8f7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java @@ -24,7 +24,7 @@ public class NSSgv { } } return ret; - }; + } private Integer getIntegerOrNull(String key) { Integer ret = null; @@ -36,7 +36,7 @@ public class NSSgv { } } return ret; - }; + } private Long getLongOrNull(String key) { Long ret = null; @@ -48,7 +48,7 @@ public class NSSgv { } } return ret; - }; + } public JSONObject getData () { return data; } public Integer getMgdl () { return getIntegerOrNull("mgdl"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSStatus.java deleted file mode 100644 index fe20e90b1d..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSStatus.java +++ /dev/null @@ -1,105 +0,0 @@ -package info.nightscout.androidaps.plugins.NSClientInternal.data; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.Date; - -/** - { - status: 'ok' - , name: env.name - , version: env.version - , versionNum: versionNum (for ver 1.2.3 contains 10203) - , serverTime: new Date().toISOString() - , apiEnabled: apiEnabled - , careportalEnabled: apiEnabled && env.settings.enable.indexOf('careportal') > -1 - , boluscalcEnabled: apiEnabled && env.settings.enable.indexOf('boluscalc') > -1 - , head: env.head - , settings: env.settings - , extendedSettings: ctx.plugins && ctx.plugins.extendedClientSettings ? ctx.plugins.extendedClientSettings(env.extendedSettings) : {} - , activeProfile ..... calculated from treatments or missing - } - */ -public class NSStatus { - private JSONObject data; - - public NSStatus(JSONObject obj) { - this.data = obj; - } - - public String getName () { return getStringOrNull("name"); } - public String getVersion () { return getStringOrNull("version"); } - public Integer getVersionNum () { return getIntegerOrNull("versionNum"); } - public Date getServerTime () { return getDateOrNull("versionNum"); } - public boolean getApiEnabled () { return getBooleanOrNull("apiEnabled"); } - public boolean getCareportalEnabled () { return getBooleanOrNull("careportalEnabled"); } - public boolean getBoluscalcEnabled () { return getBooleanOrNull("boluscalcEnabled"); } - public String getHead () { return getStringOrNull("head"); } - public String getSettings () { return getStringOrNull("settings"); } - public String getExtendedSettings () { return getStringOrNull("extendedSettings"); } - public String getActiveProfile () { return getStringOrNull("activeProfile"); } - - private String getStringOrNull(String key) { - String ret = null; - if (data.has(key)) { - try { - ret = data.getString(key); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ret; - }; - - private Integer getIntegerOrNull(String key) { - Integer ret = null; - if (data.has(key)) { - try { - ret = data.getInt(key); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ret; - }; - - private Long getLongOrNull(String key) { - Long ret = null; - if (data.has(key)) { - try { - ret = data.getLong(key); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ret; - }; - - private Date getDateOrNull(String key) { - Date ret = null; - if (data.has(key)) { - try { - ret = new Date(data.getString(key)); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ret; - }; - - private boolean getBooleanOrNull(String key) { - boolean ret = false; - if (data.has(key)) { - try { - ret = data.getBoolean(key); - } catch (JSONException e) { - e.printStackTrace(); - } - } - return ret; - }; - - public JSONObject getData () { return data; } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSTreatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSTreatment.java index 7430caf600..1b48f27e2f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSTreatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSTreatment.java @@ -25,7 +25,7 @@ public class NSTreatment { } } return ret; - }; + } private Double getDoubleOrNull(String key) { Double ret = null; @@ -37,7 +37,7 @@ public class NSTreatment { } } return ret; - }; + } private Integer getIntegerOrNull(String key) { Integer ret = null; @@ -49,7 +49,7 @@ public class NSTreatment { } } return ret; - }; + } private Long getLongOrNull(String key) { Long ret = null; @@ -61,7 +61,7 @@ public class NSTreatment { } } return ret; - }; + } private Date getDateOrNull(String key) { Date ret = null; @@ -73,7 +73,7 @@ public class NSTreatment { } } return ret; - }; + } public String getAction() { return action; } public JSONObject getData() { return data; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java index 7f576fde7e..7caafbd28a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/events/EventNSClientNewLog.java @@ -22,9 +22,16 @@ public class EventNSClientNewLog { this.logText = logText; } - public Spanned toHtml() { - SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); - Spanned line = Html.fromHtml(timeFormat.format(date) + " " + action + " " + logText + "
"); - return line; + SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); + + public StringBuilder toPreparedHtml() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(timeFormat.format(date)); + stringBuilder.append(" "); + stringBuilder.append(action); + stringBuilder.append(" "); + stringBuilder.append(logText); + stringBuilder.append("
"); + return stringBuilder; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/AckAlarmReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/AckAlarmReceiver.java new file mode 100644 index 0000000000..6bdf824b7c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/AckAlarmReceiver.java @@ -0,0 +1,64 @@ +package info.nightscout.androidaps.plugins.NSClientInternal.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.PowerManager; + +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.db.DbRequest; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; +import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; +import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; +import info.nightscout.utils.SP; + +public class AckAlarmReceiver extends BroadcastReceiver { + private static Logger log = LoggerFactory.getLogger(AckAlarmReceiver.class); + + + @Override + public void onReceive(Context context, Intent intent) { + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + AckAlarmReceiver.class.getSimpleName()); + NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); + 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(); + if (bundles == null) return; + if (!bundles.containsKey("level")) return; + if (!bundles.containsKey("group")) return; + if (!bundles.containsKey("silenceTime")) return; + + AlarmAck ack = new AlarmAck(); + ack.level = bundles.getInt("level"); + ack.group = bundles.getString("group"); + ack.silenceTime = bundles.getLong("silenceTime"); + + NSClientService nsClientService = nsClientInternalPlugin.nsClientService; + if (nsClientService != null) + nsClientService.sendAlarmAck(ack); + + } finally { + wakeLock.release(); + } + } +} 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 91fca44d12..3546a1d5e0 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 @@ -19,6 +19,8 @@ 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.androidaps.plugins.NSClientInternal.data.AlarmAck; +import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; import info.nightscout.utils.SP; public class DBAccessReceiver extends BroadcastReceiver { @@ -29,8 +31,8 @@ public class DBAccessReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - "sendQueue"); - NSClientInternalPlugin nsClientInternalPlugin = (NSClientInternalPlugin) MainApp.getSpecificPlugin(NSClientInternalPlugin.class); + DBAccessReceiver.class.getSimpleName()); + NSClientInternalPlugin nsClientInternalPlugin = MainApp.getSpecificPlugin(NSClientInternalPlugin.class); if (!nsClientInternalPlugin.isEnabled(PluginBase.GENERAL)) { return; } @@ -61,7 +63,7 @@ public class DBAccessReceiver extends BroadcastReceiver { data = new JSONObject(); } // mark by id - Long nsclientid = new Date().getTime(); + Long nsclientid = System.currentTimeMillis(); try { data.put("NSCLIENT_ID", nsclientid); } catch (JSONException e) { 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 a90c3b51c7..cbc18acbca 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; @@ -29,6 +27,7 @@ import java.util.Date; 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; @@ -39,17 +38,20 @@ 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.NSUpdateAck; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAlarm; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAnnouncement; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastCals; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastClearAlarm; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastDeviceStatus; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastMbgs; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastProfile; 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.plugins.NSClientInternal.data.NSCal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastUrgentAlarm; +import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSStatus; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; @@ -57,7 +59,6 @@ import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientS 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.Services.ExecutionService; import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; import io.socket.client.IO; @@ -65,15 +66,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; @@ -89,7 +89,7 @@ public class NSClientService extends Service { static public String nsURL = ""; private String nsAPISecret = ""; private String nsDevice = ""; - private Integer nsHours = 24; + private Integer nsHours = 48; public long lastResendTime = 0; @@ -102,7 +102,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()); } @@ -156,6 +156,7 @@ public class NSClientService extends Service { ev.isChanged(R.string.key_nsclientinternal_api_secret) || ev.isChanged(R.string.key_nsclientinternal_paused) ) { + latestDateInReceivedData = 0; destroy(); initialize(); } @@ -164,6 +165,7 @@ public class NSClientService extends Service { @Subscribe public void onStatusEvent(EventConfigBuilderChange ev) { if (nsEnabled != MainApp.getSpecificPlugin(NSClientInternalPlugin.class).isEnabled(PluginBase.GENERAL)) { + latestDateInReceivedData = 0; destroy(); initialize(); } @@ -175,14 +177,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; @@ -194,7 +188,7 @@ public class NSClientService extends Service { nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString(); MainApp.bus().post(new EventNSClientStatus("Initializing")); - if (((NSClientInternalPlugin)MainApp.getSpecificPlugin(NSClientInternalPlugin.class)).paused) { + if (MainApp.getSpecificPlugin(NSClientInternalPlugin.class).paused) { MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "paused")); MainApp.bus().post(new EventNSClientStatus("Paused")); } else if (!nsEnabled) { @@ -213,6 +207,10 @@ public class NSClientService extends Service { MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "do connect")); mSocket.connect(); mSocket.on("dataUpdate", onDataUpdate); + mSocket.on("announcement", onAnnouncement); + mSocket.on("alarm", onAlarm); + mSocket.on("urgent_alarm", onUrgentAlarm); + mSocket.on("clear_alarm", onClearAlarm); } catch (URISyntaxException | RuntimeException e) { MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "Wrong URL syntax")); MainApp.bus().post(new EventNSClientStatus("Wrong URL syntax")); @@ -309,6 +307,99 @@ public class NSClientService extends Service { } }; + private Emitter.Listener onAnnouncement = new Emitter.Listener() { +/* +{ +"level":0, +"title":"Announcement", +"message":"test", +"plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true}, +"group":"Announcement", +"isAnnouncement":true, +"key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da" +} + */ + @Override + public void call(final Object... args) { + JSONObject data = (JSONObject) args[0]; + if (Config.detailedLog) + try { + MainApp.bus().post(new EventNSClientNewLog("ANNOUNCEMENT", data.has("message") ? data.getString("message") : "received")); + } catch (JSONException e) { + e.printStackTrace(); + } + BroadcastAnnouncement.handleAnnouncement(data, getApplicationContext()); + log.debug(data.toString()); + } + }; + + private Emitter.Listener onAlarm = new Emitter.Listener() { +/* +{ +"level":1, +"title":"Warning HIGH", +"message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g", +"eventName":"high", +"plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, +"pushoverSound":"climb", +"debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, +"group":"default", +"key":"simplealarms_1" +} + */ + @Override + public void call(final Object... args) { + if (Config.detailedLog) + MainApp.bus().post(new EventNSClientNewLog("ALARM", "received")); + JSONObject data = (JSONObject) args[0]; + BroadcastAlarm.handleAlarm(data, getApplicationContext()); + log.debug(data.toString()); + } + }; + + private Emitter.Listener onUrgentAlarm = new Emitter.Listener() { +/* +{ +"level":2, +"title":"Urgent HIGH", +"message":"BG Now: 5.2 -0.1 → mmol\/L\nRaw BG: 5 mmol\/L Čistý\nBG 15m: 5 mmol\/L\nIOB: 0.00U\nCOB: 0g", +"eventName":"high", +"plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, +"pushoverSound":"persistent", +"debug":{"lastSGV":5.2,"thresholds":{"bgHigh":80,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, +"group":"default", +"key":"simplealarms_2" +} + */ + @Override + public void call(final Object... args) { + JSONObject data = (JSONObject) args[0]; + if (Config.detailedLog) + MainApp.bus().post(new EventNSClientNewLog("URGENTALARM", "received")); + BroadcastUrgentAlarm.handleUrgentAlarm(data, getApplicationContext()); + log.debug(data.toString()); + } + }; + + private Emitter.Listener onClearAlarm = new Emitter.Listener() { +/* +{ +"clear":true, +"title":"All Clear", +"message":"default - Urgent was ack'd", +"group":"default" +} + */ + @Override + public void call(final Object... args) { + if (Config.detailedLog) + MainApp.bus().post(new EventNSClientNewLog("CLEARALARM", "received")); + JSONObject data = (JSONObject) args[0]; + BroadcastClearAlarm.handleClearAlarm(data, getApplicationContext()); + log.debug(data.toString()); + } + }; + private Emitter.Listener onDataUpdate = new Emitter.Listener() { @Override public void call(final Object... args) { @@ -320,10 +411,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 @@ -332,12 +421,10 @@ public class NSClientService extends Service { MainApp.bus().post(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full"))); if (data.has("profiles")) { - JSONArray profiles = (JSONArray) data.getJSONArray("profiles"); + JSONArray profiles = 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")); } @@ -345,34 +432,18 @@ public class NSClientService extends Service { if (data.has("status")) { JSONObject status = data.getJSONObject("status"); - NSStatus nsStatus = new NSStatus(status); + NSSettingsStatus nsSettingsStatus = NSSettingsStatus.getInstance().setData(status); if (!status.has("versionNum")) { - if (status.getInt("versionNum") < 900) { + if (status.getInt("versionNum") < Config.SUPPORTEDNSVERSION) { MainApp.bus().post(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!")); } } else { - nightscoutVersionName = status.getString("version"); - nightscoutVersionCode = status.getInt("versionNum"); + nightscoutVersionName = nsSettingsStatus.getVersion(); + nightscoutVersionCode = nsSettingsStatus.getVersionNum(); } + BroadcastStatus.handleNewStatus(nsSettingsStatus, MainApp.instance().getApplicationContext(), isDelta); - 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' @@ -394,18 +465,16 @@ public class NSClientService extends Service { } // If new profile received or change detected broadcast it - if (broadcastProfile && nsProfile != null) { - BroadcastProfile bp = new BroadcastProfile(); - bp.handleNewTreatment(nsProfile, MainApp.instance().getApplicationContext(), isDelta); + if (broadcastProfile && profileStore != null) { + BroadcastProfile.handleNewTreatment(profileStore, MainApp.instance().getApplicationContext(), isDelta); MainApp.bus().post(new EventNSClientNewLog("PROFILE", "broadcasting")); } if (data.has("treatments")) { - JSONArray treatments = (JSONArray) data.getJSONArray("treatments"); + JSONArray treatments = data.getJSONArray("treatments"); JSONArray removedTreatments = new JSONArray(); JSONArray updatedTreatments = new JSONArray(); JSONArray addedTreatments = new JSONArray(); - BroadcastTreatment bt = new BroadcastTreatment(); if (treatments.length() > 0) MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments")); for (Integer index = 0; index < treatments.length(); index++) { @@ -415,33 +484,31 @@ public class NSClientService extends Service { // remove from upload queue if Ack is failing UploadQueue.removeID(jsonTreatment); //Find latest date in treatment - if (treatment.getMills() != null && treatment.getMills() < new Date().getTime()) + if (treatment.getMills() != null && treatment.getMills() < System.currentTimeMillis()) if (treatment.getMills() > latestDateInReceivedData) 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() > System.currentTimeMillis() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only removedTreatments.put(jsonTreatment); } } if (removedTreatments.length() > 0) { - bt.handleRemovedTreatment(removedTreatments, MainApp.instance().getApplicationContext(), isDelta); + BroadcastTreatment.handleRemovedTreatment(removedTreatments, MainApp.instance().getApplicationContext(), isDelta); } if (updatedTreatments.length() > 0) { - bt.handleChangedTreatment(updatedTreatments, MainApp.instance().getApplicationContext(), isDelta); + BroadcastTreatment.handleChangedTreatment(updatedTreatments, MainApp.instance().getApplicationContext(), isDelta); } if (addedTreatments.length() > 0) { - bt.handleNewTreatment(addedTreatments, MainApp.instance().getApplicationContext(), isDelta); + BroadcastTreatment.handleNewTreatment(addedTreatments, MainApp.instance().getApplicationContext(), isDelta); } } if (data.has("devicestatus")) { - BroadcastDeviceStatus bds = new BroadcastDeviceStatus(); - JSONArray devicestatuses = (JSONArray) data.getJSONArray("devicestatus"); + JSONArray devicestatuses = data.getJSONArray("devicestatus"); if (devicestatuses.length() > 0) { MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " devicestatuses")); for (Integer index = 0; index < devicestatuses.length(); index++) { @@ -449,13 +516,11 @@ public class NSClientService extends Service { // remove from upload queue if Ack is failing UploadQueue.removeID(jsonStatus); } - // send only last record - bds.handleNewDeviceStatus(devicestatuses.getJSONObject(devicestatuses.length() - 1), MainApp.instance().getApplicationContext(), isDelta); + BroadcastDeviceStatus.handleNewDeviceStatus(devicestatuses, MainApp.instance().getApplicationContext(), isDelta); } } if (data.has("mbgs")) { - BroadcastMbgs bmbg = new BroadcastMbgs(); - JSONArray mbgs = (JSONArray) data.getJSONArray("mbgs"); + JSONArray mbgs = data.getJSONArray("mbgs"); if (mbgs.length() > 0) MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + mbgs.length() + " mbgs")); for (Integer index = 0; index < mbgs.length(); index++) { @@ -463,27 +528,21 @@ public class NSClientService extends Service { // remove from upload queue if Ack is failing UploadQueue.removeID(jsonMbg); } - bmbg.handleNewMbg(mbgs, MainApp.instance().getApplicationContext(), isDelta); + BroadcastMbgs.handleNewMbg(mbgs, MainApp.instance().getApplicationContext(), isDelta); } if (data.has("cals")) { - BroadcastCals bc = new BroadcastCals(); - JSONArray cals = (JSONArray) data.getJSONArray("cals"); + JSONArray cals = data.getJSONArray("cals"); if (cals.length() > 0) 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)); } - bc.handleNewCal(cals, MainApp.instance().getApplicationContext(), isDelta); + BroadcastCals.handleNewCal(cals, MainApp.instance().getApplicationContext(), isDelta); } if (data.has("sgvs")) { - BroadcastSgvs bs = new BroadcastSgvs(); - String units = nsProfile != null ? nsProfile.getUnits() : "mg/dl"; - JSONArray sgvs = (JSONArray) data.getJSONArray("sgvs"); + JSONArray sgvs = data.getJSONArray("sgvs"); if (sgvs.length() > 0) MainApp.bus().post(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs")); for (Integer index = 0; index < sgvs.length(); index++) { @@ -494,11 +553,11 @@ public class NSClientService extends Service { // remove from upload queue if Ack is failing UploadQueue.removeID(jsonSgv); //Find latest date in sgv - if (sgv.getMills() != null && sgv.getMills() < new Date().getTime()) + if (sgv.getMills() != null && sgv.getMills() < System.currentTimeMillis()) if (sgv.getMills() > latestDateInReceivedData) latestDateInReceivedData = sgv.getMills(); } - bs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta); + BroadcastSgvs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta); } MainApp.bus().post(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData))); } catch (JSONException e) { @@ -578,6 +637,12 @@ public class NSClientService extends Service { } } + public void sendAlarmAck(AlarmAck alarmAck) { + if (!isConnected || !hasWriteAuth) return; + mSocket.emit("ack", alarmAck.level, alarmAck.group, alarmAck.silenceTime); + MainApp.bus().post(new EventNSClientNewLog("ALARMACK ", alarmAck.level + " " + alarmAck.group + " " + alarmAck.silenceTime)); + } + @Subscribe public void onStatusEvent(NSAddAck ack) { if (ack.nsClientID != null) { @@ -610,17 +675,17 @@ public class NSClientService extends Service { public void run() { 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"); + if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) { + log.debug("Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec"); return; } - lastResendTime = new Date().getTime(); + lastResendTime = System.currentTimeMillis(); 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/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java index 4ce3cd61b5..66696ac9b8 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 @@ -11,17 +11,18 @@ 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.IobTotal; import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.db.TempBasal; +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.IobTotal; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.Profile; import info.nightscout.utils.SP; public class DetermineBasalAdapterAMAJS { @@ -189,7 +190,7 @@ public class DetermineBasalAdapterAMAJS { } - public void setData(NSProfile profile, + public void setData(Profile profile, double maxIob, double maxBasal, double minBg, @@ -207,15 +208,15 @@ public class DetermineBasalAdapterAMAJS { mProfile = new V8Object(mV8rt); mProfile.add("max_iob", maxIob); - mProfile.add("dia", profile.getDia()); + mProfile.add("dia", Math.min(profile.getDia(), 3d)); mProfile.add("type", "current"); mProfile.add("max_daily_basal", profile.getMaxDailyBasal()); mProfile.add("max_basal", maxBasal); 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); @@ -227,12 +228,12 @@ 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(System.currentTimeMillis()); + if (tempBasal != null) { mCurrentTemp.add("minutesrunning", tempBasal.getRealDuration()); } @@ -244,7 +245,7 @@ public class DetermineBasalAdapterAMAJS { mGlucoseStatus = new V8Object(mV8rt); mGlucoseStatus.add("glucose", glucoseStatus.glucose); - if(SP.getBoolean("always_use_shortavg", false)){ + if (SP.getBoolean("always_use_shortavg", false)) { mGlucoseStatus.add("delta", glucoseStatus.short_avgdelta); } else { mGlucoseStatus.add("delta", glucoseStatus.delta); 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..c2a55ff894 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; @@ -46,7 +43,7 @@ public class DetermineBasalResultAMA extends APSResult { } if (result.contains("duration")) { duration = result.getInteger("duration"); - changeRequested = changeRequested; + //changeRequested as above } else { duration = -1; changeRequested = false; @@ -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 c480ebfe3c..419a55f057 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,11 +20,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; 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 { +public class OpenAPSAMAFragment extends SubscriberFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(OpenAPSAMAFragment.class); private static OpenAPSAMAPlugin openAPSAMAPlugin; @@ -81,18 +82,6 @@ public class OpenAPSAMAFragment 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); - } - @Subscribe public void onStatusEvent(final EventOpenAPSUpdateGui ev) { updateGUI(); @@ -103,7 +92,8 @@ public class OpenAPSAMAFragment extends Fragment implements View.OnClickListener updateResultGUI(ev.text); } - void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { 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 ee8caea6b4..53bcfcf1ec 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 @@ -12,6 +12,7 @@ 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.TempTarget; import info.nightscout.androidaps.interfaces.APSInterface; @@ -21,12 +22,11 @@ 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; @@ -56,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; } @@ -132,9 +132,16 @@ 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 (profile == null) { + MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected))); + if (Config.logAPSResult) + log.debug(MainApp.instance().getString(R.string.noprofileselected)); + return; + } + if (!isEnabled(PluginBase.APS)) { MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled))); if (Config.logAPSResult) @@ -149,38 +156,13 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { return; } - if (profile == null || profile.getIc(NSProfile.secondsFromMidnight()) == null || profile.getIsf(NSProfile.secondsFromMidnight()) == null || profile.getBasal(NSProfile.secondsFromMidnight()) == 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; - Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL; - Double targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL; - if (!units.equals(Constants.MGDL)) { - maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL; - minBgDefault = Constants.MIN_BG_DEFAULT_MMOL; - targetBgDefault = Constants.TARGET_BG_DEFAULT_MMOL; - } - - Date now = new Date(); - 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(profile.getTargetLow(), units); + double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); + double targetBg = (minBg + maxBg) / 2; minBg = Round.roundTo(minBg, 0.1d); maxBg = Round.roundTo(maxBg, 0.1d); @@ -191,7 +173,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { 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); @@ -201,15 +183,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(System.currentTimeMillis()); + 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]); } @@ -217,19 +196,16 @@ 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; - long oldestDataAvailable = MainApp.getConfigBuilder().getActiveTempBasals().oldestDataAvaialable(); - 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(getBGDataFrom, null); - lastAutosensResult = IobCobCalculatorPlugin.detectSensitivity(getBGDataFrom); + if (MainApp.getConfigBuilder().isAMAModeEnabled()) { + lastAutosensResult = IobCobCalculatorPlugin.detectSensitivityWithLock(IobCobCalculatorPlugin.oldestDataAvailable(), System.currentTimeMillis()); } else { lastAutosensResult = new AutosensResult(); } @@ -241,7 +217,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(); @@ -251,7 +227,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; @@ -261,6 +237,8 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface { determineBasalAdapterAMAJS.release(); + Date now = new Date(); + try { determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now)); } catch (JSONException e) { @@ -289,7 +267,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 ee0a00b802..dc4d2ee70d 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,13 @@ 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 { @@ -45,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 { @@ -106,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(" + @@ -216,7 +217,7 @@ public class DetermineBasalAdapterMAJS { } - public void setData(NSProfile profile, + public void setData(Profile profile, double maxIob, double maxBasal, double minBg, @@ -230,19 +231,19 @@ public class DetermineBasalAdapterMAJS { String units = profile.getUnits(); mProfile.add("max_iob", maxIob); - mProfile.add("dia", profile.getDia()); + mProfile.add("dia", Math.min(profile.getDia(), 3d)); mProfile.add("type", "current"); mProfile.add("max_daily_basal", profile.getMaxDailyBasal()); mProfile.add("max_basal", maxBasal); 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 @@ -252,7 +253,7 @@ public class DetermineBasalAdapterMAJS { mIobData.add("hightempinsulin", iobData.hightempinsulin); mGlucoseStatus.add("glucose", glucoseStatus.glucose); - if(SP.getBoolean("always_use_shortavg", false)){ + if (SP.getBoolean("always_use_shortavg", false)) { mGlucoseStatus.add("delta", glucoseStatus.short_avgdelta); } else { mGlucoseStatus.add("delta", glucoseStatus.delta); @@ -264,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/DetermineBasalResultMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java index cb0e67249f..a0cd1a75b0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java @@ -41,7 +41,7 @@ public class DetermineBasalResultMA extends APSResult { } if (result.contains("duration")) { duration = result.getInteger("duration"); - changeRequested = changeRequested; + //changeRequested as above } else { duration = -1; changeRequested = false; 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 16249dffc3..90bfc301b1 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,11 +18,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; 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 { +public class OpenAPSMAFragment extends SubscriberFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(OpenAPSMAFragment.class); private static OpenAPSMAPlugin openAPSMAPlugin; @@ -75,18 +76,6 @@ public class OpenAPSMAFragment 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); - } - @Subscribe public void onStatusEvent(final EventOpenAPSUpdateGui ev) { updateGUI(); @@ -97,7 +86,8 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener updateResultGUI(ev.text); } - void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { @@ -123,7 +113,7 @@ public class OpenAPSMAFragment extends Fragment implements View.OnClickListener }); } - void updateResultGUI(final String text) { + private void updateResultGUI(final String text) { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { 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 1e7bec7471..95f1235161 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; @@ -133,9 +130,16 @@ 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 (profile == null) { + MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.noprofileselected))); + if (Config.logAPSResult) + log.debug(MainApp.instance().getString(R.string.noprofileselected)); + return; + } + if (!isEnabled(PluginBase.APS)) { MainApp.bus().post(new EventOpenAPSUpdateResultGui(MainApp.instance().getString(R.string.openapsma_disabled))); if (Config.logAPSResult) @@ -150,53 +154,28 @@ 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; - Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL; - Double targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL; - if (!units.equals(Constants.MGDL)) { - maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL; - minBgDefault = Constants.MIN_BG_DEFAULT_MMOL; - targetBgDefault = Constants.TARGET_BG_DEFAULT_MMOL; - } - Date now = new Date(); 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(profile.getTargetLow(), units); + double maxBg = Profile.toMgdl(profile.getTargetHigh(), units); + double targetBg = (minBg + maxBg) / 2; 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); @@ -204,23 +183,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(System.currentTimeMillis()); + 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; @@ -235,7 +211,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/CalibrationDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/CalibrationDialog.java index d13243e66a..fdc58e92f4 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 @@ -9,7 +9,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; -import android.widget.Button; import android.widget.TextView; import com.crashlytics.android.answers.Answers; @@ -24,18 +23,16 @@ 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.utils.PlusMinusEditText; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.utils.NumberPicker; import info.nightscout.utils.SafeParse; import info.nightscout.utils.XdripCalibrations; public class CalibrationDialog extends DialogFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(CalibrationDialog.class); - Button okButton; - PlusMinusEditText bgText; + NumberPicker bgNumber; TextView unitsView; - TextView bgView; Context context; @@ -49,6 +46,12 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis this.context = context; } + @Override + public void onDetach() { + super.onDetach(); + this.context = null; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -57,24 +60,21 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - okButton = (Button) view.findViewById(R.id.overview_calibration_okbutton); - okButton.setOnClickListener(this); + view.findViewById(R.id.ok).setOnClickListener(this); + view.findViewById(R.id.cancel).setOnClickListener(this); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - Double bg = profile != null ? NSProfile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits()) : 0d; + String units = MainApp.getConfigBuilder().getProfileUnits(); + Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units); - String units = Constants.MGDL; - if (profile != null) - units = profile.getUnits(); + bgNumber = (NumberPicker) view.findViewById(R.id.overview_calibration_bg); if (units.equals(Constants.MMOL)) - bgText = new PlusMinusEditText(view, R.id.overview_calibration_bg, R.id.overview_calibration_bg_plus, R.id.overview_calibration_bg_minus, bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false); + bgNumber.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false); else - bgText = new PlusMinusEditText(view, R.id.overview_calibration_bg, R.id.overview_calibration_bg_plus, R.id.overview_calibration_bg_minus, bg, 0d, 500d, 1d, new DecimalFormat("0"), false); + bgNumber.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false); unitsView = (TextView) view.findViewById(R.id.overview_calibration_units); unitsView.setText(units); - bgView = (TextView) view.findViewById(R.id.overview_calibration_bg); return view; } @@ -82,12 +82,15 @@ public class CalibrationDialog extends DialogFragment implements View.OnClickLis @Override public void onClick(View view) { switch (view.getId()) { - case R.id.overview_calibration_okbutton: - final Double bg = SafeParse.stringToDouble(this.bgView.getText().toString());; + case R.id.ok: + final Double bg = SafeParse.stringToDouble(bgNumber.getText()); XdripCalibrations.confirmAndSendCalibration(bg, context); dismiss(); Answers.getInstance().logCustom(new CustomEvent("Calibration")); break; + case R.id.cancel: + dismiss(); + break; } } } 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 352c158c1e..1179841098 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 @@ -29,7 +29,7 @@ import info.nightscout.utils.SafeParse; public class EditQuickWizardDialog extends DialogFragment implements View.OnClickListener { QuickWizard.QuickWizardEntry entry = new QuickWizard().newEmptyItem(); - QuickWizard quickWizard = ((OverviewPlugin) MainApp.getSpecificPlugin(OverviewPlugin.class)).quickWizard; + QuickWizard quickWizard = MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard; EditText buttonEdit; EditText carbsEdit; 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 8144d39ff5..e2edb1e76a 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 @@ -20,24 +20,24 @@ import com.crashlytics.android.answers.Answers; import com.crashlytics.android.answers.CustomEvent; import java.text.DecimalFormat; +import java.util.Objects; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.DetailedBolusInfo; 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.NumberPicker; import info.nightscout.utils.PlusMinusEditText; import info.nightscout.utils.SafeParse; public class NewTreatmentDialog extends DialogFragment implements OnClickListener { - Button okButton; - Button cancelButton; - TextView insulin; - TextView carbs; - - PlusMinusEditText editCarbs; - PlusMinusEditText editInsulin; + NumberPicker editCarbs; + NumberPicker editInsulin; Handler mHandler; public static HandlerThread mHandlerThread; @@ -51,42 +51,34 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.overview_newtreatment_dialog, null, false); + View view = inflater.inflate(R.layout.overview_newtreatment_dialog, container, false); - okButton = (Button) view.findViewById(R.id.ok); - okButton.setOnClickListener(this); - cancelButton = (Button) view.findViewById(R.id.cancel); - cancelButton.setOnClickListener(this); + view.findViewById(R.id.ok).setOnClickListener(this); + view.findViewById(R.id.cancel).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); - editCarbs = new PlusMinusEditText(view, R.id.treatments_newtreatment_carbsamount, R.id.treatments_newtreatment_carbsamount_plus, R.id.treatments_newtreatment_carbsamount_minus, 0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); - editInsulin = new PlusMinusEditText(view, R.id.treatments_newtreatment_insulinamount, R.id.treatments_newtreatment_insulinamount_plus, R.id.treatments_newtreatment_insulinamount_minus, 0d, 0d, maxInsulin, MainApp.getConfigBuilder().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false); + editCarbs = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_carbsamount); + editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount); + + editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); + editInsulin.setParams(0d, 0d, maxInsulin, MainApp.getConfigBuilder().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false); return view; } - @Override - public void onResume() { - super.onResume(); - if (getDialog() != null) - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - @Override public void onClick(View view) { switch (view.getId()) { 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,11 +87,11 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene confirmMessage += getString(R.string.bolus) + ": " + insulinAfterConstraints + "U"; confirmMessage += "\n" + getString(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - if (insulinAfterConstraints - insulin != 0 || carbsAfterConstraints != carbs) + if (insulinAfterConstraints - insulin != 0 || !Objects.equals(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); @@ -113,7 +105,14 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene mHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = pump.deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), 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)); 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 0d7590e501..bda03a8a27 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 @@ -21,7 +21,6 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.EditText; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; @@ -42,35 +41,34 @@ import java.util.Date; 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.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.db.DatabaseHelper; +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.events.EventRefreshOverview; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; 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.NumberPicker; 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; -public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { +public class WizardDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener, Spinner.OnItemSelectedListener { private static Logger log = LoggerFactory.getLogger(WizardDialog.class); - Button wizardDialogDeliverButton; - TextView correctionInput; - TextView carbsInput; - TextView bgInput; + Button okButton; TextView bg; TextView bgInsulin; TextView bgUnits; @@ -83,8 +81,6 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co CheckBox basalIobCheckbox; TextView correctionInsulin; TextView total; - TextView totalInsulin; - EditText carbTimeEdit; Spinner profileSpinner; CheckBox superbolusCheckbox; TextView superbolus; @@ -97,10 +93,10 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co TextView cob; TextView cobInsulin; - PlusMinusEditText editBg; - PlusMinusEditText editCarbs; - PlusMinusEditText editCorr; - PlusMinusEditText editCarbTime; + NumberPicker editBg; + NumberPicker editCarbs; + NumberPicker editCorr; + NumberPicker editCarbTime; Integer calculatedCarbs = 0; Double calculatedTotalInsulin = 0d; @@ -125,11 +121,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co this.context = context; } - @Override + @Override + public void onDetach() { + super.onDetach(); + this.context = null; + } + + @Override public void onResume() { super.onResume(); - if (getDialog() != null) - getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); MainApp.bus().register(this); } @@ -146,7 +146,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co activity.runOnUiThread(new Runnable() { @Override public void run() { - if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(new Date().getTime() - 11 * 60 * 1000L))) { + if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(System.currentTimeMillis() - 11 * 60 * 1000L))) { cobLayout.setVisibility(View.VISIBLE); cobAvailable = true; } else { @@ -193,8 +193,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); - wizardDialogDeliverButton = (Button) view.findViewById(R.id.treatments_wizard_deliverButton); - wizardDialogDeliverButton.setOnClickListener(this); + okButton = (Button) view.findViewById(R.id.ok); + okButton.setOnClickListener(this); + view.findViewById(R.id.cancel).setOnClickListener(this); bg = (TextView) view.findViewById(R.id.treatments_wizard_bg); bgInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bginsulin); @@ -205,16 +206,14 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co 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);; + 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); @@ -232,22 +231,21 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co 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); + editCarbTime = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbtimeinput); + editCorr = (NumberPicker) view.findViewById(R.id.treatments_wizard_correctioninput); + editCarbs = (NumberPicker) view.findViewById(R.id.treatments_wizard_carbsinput); + editBg = (NumberPicker) view.findViewById(R.id.treatments_wizard_bginput); superbolusCheckbox.setVisibility(SP.getBoolean(R.string.key_usesuperbolus, false) ? View.VISIBLE : View.GONE); Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit); Double maxCorrection = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit); - editBg = new PlusMinusEditText(view, R.id.treatments_wizard_bginput, R.id.treatments_wizard_bginput_plus, R.id.treatments_wizard_bginput_minus, 0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false); - editCarbs = new PlusMinusEditText(view, R.id.treatments_wizard_carbsinput, R.id.treatments_wizard_carbsinput_plus, R.id.treatments_wizard_carbsinput_minus, 0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false); - editCorr = new PlusMinusEditText(view, R.id.treatments_wizard_correctioninput, R.id.treatments_wizard_correctioninput_plus, R.id.treatments_wizard_correctioninput_minus, 0d, -maxCorrection, maxCorrection, 0.05d, new DecimalFormat("0.00"), false); - editCarbTime = new PlusMinusEditText(view, R.id.treatments_wizard_carbtimeinput, R.id.treatments_wizard_carbtime_plus, R.id.treatments_wizard_carbtime_minus, 0d, -60d, 60d, 5d, new DecimalFormat("0"), false); + editBg.setParams(0d, 0d, 500d, 0.1d, new DecimalFormat("0.0"), false, textWatcher); + editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher); + double bolusstep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; + editCorr.setParams(0d, -maxCorrection, maxCorrection, bolusstep, new DecimalFormat("0.00"), false, textWatcher); + editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false); initDialog(); return view; @@ -261,19 +259,19 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { calculateInsulin(); - wizardDialogDeliverButton.setVisibility(View.VISIBLE); + okButton.setVisibility(View.VISIBLE); } @Override public void onNothingSelected(AdapterView parent) { ToastUtils.showToastInUiThread(context, MainApp.sResources.getString(R.string.noprofileselected)); - wizardDialogDeliverButton.setVisibility(View.GONE); + okButton.setVisibility(View.GONE); } @Override public void onClick(View view) { switch (view.getId()) { - case R.id.treatments_wizard_deliverButton: + case R.id.ok: if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { DecimalFormat formatNumber2decimalplaces = new DecimalFormat("0.00"); String confirmMessage = getString(R.string.entertreatmentquestion); @@ -295,8 +293,8 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co 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 Double bg = SafeParse.stringToDouble(editBg.getText()); + final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); final boolean useSuperBolus = superbolusCheckbox.isChecked(); AlertDialog.Builder builder = new AlertDialog.Builder(context); @@ -313,24 +311,26 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co 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)); + activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + MainApp.bus().post(new EventRefreshOverview("WizardDialog")); } + pump.cancelTempBasal(true); result = pump.setTempBasalAbsolute(0d, 120); if (!result.success) { OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror), result.comment, null); } } - result = pump.deliverTreatmentFromBolusWizard( - MainApp.getConfigBuilder().getActiveInsulin(), - context, - finalInsulinAfterConstraints, - finalCarbsAfterConstraints, - bg, - "Manual", - carbTime, - boluscalcJSON - ); + 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); } @@ -345,11 +345,15 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co dismiss(); } break; + case R.id.cancel: + 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)); @@ -357,14 +361,14 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co } ArrayList profileList; - profileList = profile.getProfileList(); + profileList = profileStore.getProfileList(); ArrayAdapter adapter = new ArrayAdapter(getContext(), 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); } @@ -374,13 +378,13 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co 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; @@ -390,71 +394,64 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co bg.setText(lastBg.valueToUnitsToString(units) + " ISF: " + DecimalFormatter.to1Decimal(sens)); bgInsulin.setText(DecimalFormatter.to2Decimal(bgDiff / sens) + "U"); - bgInput.removeTextChangedListener(textWatcher); + editBg.removeTextChangedListener(textWatcher); //bgInput.setText(lastBg.valueToUnitsToString(units)); editBg.setValue(lastBg.valueToUnits(units)); - bgInput.addTextChangedListener(textWatcher); + editBg.addTextChangedListener(textWatcher); } else { bg.setText(""); bgInsulin.setText(""); - bgInput.removeTextChangedListener(textWatcher); + editBg.removeTextChangedListener(textWatcher); //bgInput.setText(""); editBg.setValue(0d); - bgInput.addTextChangedListener(textWatcher); + editBg.addTextChangedListener(textWatcher); } // 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"); - totalInsulin.setText(""); - wizardDialogDeliverButton.setVisibility(Button.INVISIBLE); - // COB only if AMA is selected - if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(new Date().getTime() - 11 * 60 * 1000L))) { + if (ConfigBuilderPlugin.getActiveAPS() instanceof OpenAPSAMAPlugin && ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(System.currentTimeMillis() - 11 * 60 * 1000L))) { cobLayout.setVisibility(View.VISIBLE); cobAvailable = true; } else { cobLayout.setVisibility(View.GONE); cobAvailable = false; } + calculateInsulin(); } 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()); - Integer c_carbs = SafeParse.stringToInt(carbsInput.getText().toString()); - Double c_correction = SafeParse.stringToDouble(correctionInput.getText().toString()); + Double c_bg = SafeParse.stringToDouble(editBg.getText()); + Integer c_carbs = SafeParse.stringToInt(editCarbs.getText()); + Double c_correction = SafeParse.stringToDouble(editCorr.getText()); Double corrAfterConstraint = MainApp.getConfigBuilder().applyBolusConstraints(c_correction); if (c_correction - corrAfterConstraint != 0) { // c_correction != corrAfterConstraint doesn't work - correctionInput.removeTextChangedListener(textWatcher); - correctionInput.setText(""); - correctionInput.addTextChangedListener(textWatcher); + editCorr.removeTextChangedListener(textWatcher); + editCorr.setValue(0d); + editCorr.addTextChangedListener(textWatcher); //wizardDialogDeliverButton.setVisibility(Button.GONE); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.bolusconstraintapplied)); return; } Integer carbsAfterConstraint = MainApp.getConfigBuilder().applyCarbsConstraints(c_carbs); if (c_carbs - carbsAfterConstraint != 0) { - carbsInput.removeTextChangedListener(textWatcher); - carbsInput.setText(""); - carbsInput.addTextChangedListener(textWatcher); + editCarbs.removeTextChangedListener(textWatcher); + editCarbs.setValue(0d); + editCarbs.addTextChangedListener(textWatcher); //wizardDialogDeliverButton.setVisibility(Button.GONE); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.carbsconstraintapplied)); return; @@ -465,7 +462,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co // COB Double c_cob = 0d; if (cobAvailable && cobCheckbox.isChecked()) { - if (ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(new Date().getTime() - 11 * 60 * 1000L))) { + if (ConfigBuilderPlugin.getActiveAPS().getLastAPSResult() != null && ConfigBuilderPlugin.getActiveAPS().getLastAPSRun().after(new Date(System.currentTimeMillis() - 11 * 60 * 1000L))) { try { c_cob = SafeParse.stringToDouble(ConfigBuilderPlugin.getActiveAPS().getLastAPSResult().json().getString("COB")); } catch (JSONException e) { @@ -488,14 +485,6 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co correctionInsulin.setText(DecimalFormatter.to2Decimal(wizard.insulinFromCorrection) + "U"); calculatedTotalInsulin = wizard.calculatedTotalInsulin; - if (calculatedTotalInsulin <= 0) { - total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); - totalInsulin.setText(""); - } else { - total.setText(""); - totalInsulin.setText(DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U"); - } - calculatedCarbs = carbsAfterConstraint; // Superbolus @@ -509,7 +498,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co // 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(""); } @@ -530,10 +519,11 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Co if (calculatedTotalInsulin > 0d || calculatedCarbs > 0d) { String insulinText = calculatedTotalInsulin > 0d ? (DecimalFormatter.to2Decimal(calculatedTotalInsulin) + "U") : ""; String carbsText = calculatedCarbs > 0d ? (DecimalFormatter.to0Decimal(calculatedCarbs) + "g") : ""; - wizardDialogDeliverButton.setText(getString(R.string.send) + " " + insulinText + " " + carbsText); - wizardDialogDeliverButton.setVisibility(Button.VISIBLE); + total.setText(getString(R.string.result) + ": " + insulinText + " " + carbsText); + okButton.setVisibility(View.VISIBLE); } else { - wizardDialogDeliverButton.setVisibility(Button.INVISIBLE); + total.setText(getString(R.string.missing) + " " + DecimalFormatter.to0Decimal(wizard.carbsEquivalent) + "g"); + okButton.setVisibility(View.INVISIBLE); } boluscalcJSON = new JSONObject(); 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 3666573d0a..13b85e08fc 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 @@ -1,16 +1,30 @@ + package info.nightscout.androidaps.plugins.Overview; import java.util.Date; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSAlarm; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; +import info.nightscout.utils.SP; + +// Added by Rumen for debugging +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Created by mike on 03.12.2016. */ public class Notification { + private static Logger log = LoggerFactory.getLogger(Notification.class); + public static final int URGENT = 0; public static final int NORMAL = 1; public static final int LOW = 2; public static final int INFO = 3; + public static final int ANNOUNCEMENT = 4; public static final int PROFILE_SET_FAILED = 0; public static final int PROFILE_SET_OK = 1; @@ -21,10 +35,21 @@ public class Notification { public static final int FAILED_UDPATE_PROFILE = 6; public static final int BASAL_VALUE_BELOW_MINIMUM = 7; 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 = 11; - public static final int MISSING_SMS_PERMISSION = 12; + public static final int OLD_NS = 9; + public static final int INVALID_PHONE_NUMBER = 10; + public static final int APPROACHING_DAILY_LIMIT = 11; + public static final int NSCLIENT_NO_WRITE_PERMISSION = 12; + public static final int MISSING_SMS_PERMISSION = 13; + public static final int ISF_MISSING = 14; + public static final int IC_MISSING = 15; + public static final int BASAL_MISSING = 16; + public static final int TARGET_MISSING = 17; + public static final int NSANNOUNCEMENT = 18; + public static final int NSALARM = 19; + public static final int NSURGENTALARM = 20; + public static final int SHORT_DIA = 21; + public static final int TOAST_ALARM = 22; + public int id; public Date date; @@ -32,6 +57,9 @@ public class Notification { public int level; public Date validTo = new Date(0); + public NSAlarm nsAlarm = null; + public Integer soundId = null; + public Notification() { } @@ -48,7 +76,7 @@ public class Notification { this.date = new Date(); this.text = text; this.level = level; - this.validTo = new Date(new Date().getTime() + validMinutes * 60 * 1000L); + this.validTo = new Date(System.currentTimeMillis() + validMinutes * 60 * 1000L); } public Notification(int id, String text, int level) { @@ -58,4 +86,101 @@ public class Notification { this.level = level; this.validTo = new Date(0); } + + public Notification(NSAlarm nsAlarm) { + this.date = new Date(); + this.validTo = new Date(0); + this.nsAlarm = nsAlarm; + switch (nsAlarm.getLevel()) { + case 0: + this.id = NSANNOUNCEMENT; + this.level = ANNOUNCEMENT; + this.text = nsAlarm.getMessage(); + this.validTo = new Date(System.currentTimeMillis() + 60 * 60 * 1000L); + break; + case 1: + this.id = NSALARM; + this.level = NORMAL; + this.text = nsAlarm.getTile(); + if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata,false)) + this.soundId = R.raw.alarm; + break; + case 2: + this.id = NSURGENTALARM; + this.level = URGENT; + this.text = nsAlarm.getTile(); + if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false)) + this.soundId = R.raw.urgentalarm; + break; + } + } + + public boolean isEnabled() { + if (nsAlarm == null) + return true; + if (level == ANNOUNCEMENT) + return true; + if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) + { + return true; + } + if (level == URGENT && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_urgent_staledata, false)) + return true; + return false; + } + + boolean isAlarmForLow() { + BgReading bgReading = MainApp.getDbHelper().lastBg(); + if (bgReading == null) + return false; + Double threshold = NSSettingsStatus.getInstance().getThreshold("bgTargetTop"); + if (threshold == null) + return false; + if (bgReading.value <= threshold) + return true; + return false; + } + + boolean isAlarmForHigh() { + BgReading bgReading = MainApp.getDbHelper().lastBg(); + if (bgReading == null) + return false; + Double threshold = NSSettingsStatus.getInstance().getThreshold("bgTargetBottom"); + if (threshold == null) + return false; + if (bgReading.value >= threshold) + return true; + return false; + } + + static boolean isAlarmForStaleData(){ + if(SP.getLong("snoozedTo", 0L) != 0L){ + if(System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) { + //log.debug("Alarm is snoozed for next "+(SP.getLong("snoozedTo", 0L)-System.currentTimeMillis())/1000+" seconds"); + return false; + } + } + BgReading bgReading = MainApp.getDbHelper().lastBg(); + if (bgReading == null) + return false; + long bgReadingAgo = System.currentTimeMillis() - bgReading.date; + int bgReadingAgoMin = (int) (bgReadingAgo / (1000 * 60)); + // Added for testing + //bgReadingAgoMin = 20; + log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin); + Double threshold = NSSettingsStatus.getInstance().getThreshold("alarmTimeagoWarnMins"); + boolean openAPSEnabledAlerts = NSSettingsStatus.getInstance().openAPSEnabledAlerts(); + log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts); + // if no thresshold from Ns get it loccally + if(threshold == null) threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue,15D); + // No threshold of OpenAPS Alarm so using the one for BG + // Added OpenAPSEnabledAlerts to alarm check + if((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false))||(bgReadingAgoMin > threshold && openAPSEnabledAlerts)){ + return true; + } + //snoozing for threshold + SP.putLong("snoozedTo", (long) (bgReading.date+(threshold*1000*60L))); + //log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds"); + return false; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java index b4cb02e914..8c70d3eea6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.Overview; +import android.content.Intent; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,6 +11,12 @@ import java.util.Comparator; import java.util.Date; import java.util.List; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.Services.AlarmSoundService; +import info.nightscout.androidaps.plugins.Wear.WearPlugin; +//Added by Rumen for snooze time +import info.nightscout.utils.SP; /** * Created by mike on 03.12.2016. @@ -17,7 +25,7 @@ import java.util.List; public class NotificationStore { private static Logger log = LoggerFactory.getLogger(NotificationStore.class); public List store = new ArrayList(); - + public long snoozedUntil = 0L; public NotificationStore() { } @@ -41,26 +49,56 @@ public class NotificationStore { return; } } + if (n.soundId != null) { + Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); + alarm.putExtra("soundid", n.soundId); + MainApp.instance().startService(alarm); + } store.add(n); + + WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class); + if(wearPlugin!= null && wearPlugin.isEnabled()) { + wearPlugin.overviewNotification(n.id, "OverviewNotification:\n" + n.text); + } + Collections.sort(store, new NotificationComparator()); } - public void remove(int id) { + public boolean remove(int id) { for (int i = 0; i < store.size(); i++) { if (get(i).id == id) { + if (get(i).soundId != null) { + Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class); + MainApp.instance().stopService(alarm); + } store.remove(i); - return; + return true; } } + return false; } public void removeExpired() { for (int i = 0; i < store.size(); i++) { Notification n = get(i); - if (n.validTo.getTime() != 0 && n.validTo.getTime() < new Date().getTime()) { + if (n.validTo.getTime() != 0 && n.validTo.getTime() < System.currentTimeMillis()) { store.remove(i); i--; } } } + + public void snoozeTo(long timeToSnooze){ + log.debug("Snoozing alarm until: "+timeToSnooze); + SP.putLong("snoozedTo", timeToSnooze); + } + + public void unSnooze(){ + if(Notification.isAlarmForStaleData()){ + Notification notification = new Notification(Notification.NSALARM, MainApp.sResources.getString(R.string.nsalarm_staledata), Notification.URGENT); + SP.putLong("snoozedTo", System.currentTimeMillis()); + add(notification); + log.debug("Snoozed to current time and added back notification!"); + } + } } 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 ee0900c6e4..d871bd4c40 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,8 +2,9 @@ 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.Intent; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; @@ -16,23 +17,19 @@ 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.PopupMenu; 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; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.ImageButton; import android.widget.LinearLayout; -import android.widget.RelativeLayout; import android.widget.TextView; import com.crashlytics.android.answers.Answers; @@ -44,7 +41,7 @@ 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; @@ -58,6 +55,7 @@ import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -67,61 +65,71 @@ import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.PreferencesActivity; 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.EventAppExit; +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.EventRefreshOverview; 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.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastAckAlarm; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.CalibrationDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; import info.nightscout.androidaps.plugins.Overview.graphExtensions.AreaGraphSeries; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.DataPointWithLabelInterface; import info.nightscout.androidaps.plugins.Overview.graphExtensions.DoubleDataPoint; import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripPlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.TempTargetRangePlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.ImportExportPrefs; -import info.nightscout.utils.LogDialog; -import info.nightscout.utils.PasswordProtection; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.OKDialog; +import info.nightscout.utils.Profiler; import info.nightscout.utils.Round; import info.nightscout.utils.SP; import info.nightscout.utils.ToastUtils; - +//Added By Rumen for staledata alarm +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; public class OverviewFragment extends Fragment implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { private static Logger log = LoggerFactory.getLogger(OverviewFragment.class); @@ -132,44 +140,56 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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; + TextView pumpDeviceStatusView; + TextView openapsDeviceStatusView; + TextView uploaderDeviceStatusView; LinearLayout loopStatusLayout; LinearLayout pumpStatusLayout; GraphView bgGraph; GraphView iobGraph; + TextView iage; + TextView cage; + TextView sage; + TextView pbage; + CheckBox showPredictionView; CheckBox showBasalsView; CheckBox showIobView; CheckBox showCobView; CheckBox showDeviationsView; + CheckBox showRatiosView; RecyclerView notificationsView; LinearLayoutManager llm; LinearLayout acceptTempLayout; - Button cancelTempButton; Button treatmentButton; Button wizardButton; Button calibrationButton; Button acceptTempButton; Button quickWizardButton; + CheckBox lockScreen; + boolean smallWidth; boolean smallHeight; + public static boolean shorttextmode = false; private int rangeToDisplay = 6; // for graph @@ -202,54 +222,67 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, int screen_height = dm.heightPixels; smallWidth = screen_width < Constants.SMALL_WIDTH; smallHeight = screen_height < Constants.SMALL_HEIGHT; + boolean landscape = screen_height < screen_width; View view; - if(smallHeight){ + if (MainApp.sResources.getBoolean(R.bool.isTablet) && BuildConfig.NSCLIENTOLNY) { + view = inflater.inflate(R.layout.overview_fragment_nsclient_tablet, container, false); + } else if (BuildConfig.NSCLIENTOLNY) { + view = inflater.inflate(R.layout.overview_fragment_nsclient, container, false); + shorttextmode = true; + } else if (smallHeight || landscape) { 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){ + 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); + pumpDeviceStatusView = (TextView) view.findViewById(R.id.overview_pump); + openapsDeviceStatusView = (TextView) view.findViewById(R.id.overview_openaps); + uploaderDeviceStatusView = (TextView) view.findViewById(R.id.overview_uploader); 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); + bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph); 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); - cancelTempButton = (Button) view.findViewById(R.id.overview_canceltempbutton); - cancelTempButton.setOnClickListener(this); acceptTempButton = (Button) view.findViewById(R.id.overview_accepttempbutton); - acceptTempButton.setOnClickListener(this); + if (acceptTempButton != null) + 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); + if (calibrationButton != null) + calibrationButton.setOnClickListener(this); acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); @@ -258,42 +291,59 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, showIobView = (CheckBox) view.findViewById(R.id.overview_showiob); showCobView = (CheckBox) view.findViewById(R.id.overview_showcob); showDeviationsView = (CheckBox) view.findViewById(R.id.overview_showdeviations); + showRatiosView = (CheckBox) view.findViewById(R.id.overview_showratios); showPredictionView.setChecked(SP.getBoolean("showprediction", false)); - showBasalsView.setChecked(SP.getBoolean("showbasals", 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)); + showRatiosView.setChecked(SP.getBoolean("showratios", false)); showPredictionView.setOnCheckedChangeListener(this); showBasalsView.setOnCheckedChangeListener(this); showIobView.setOnCheckedChangeListener(this); showCobView.setOnCheckedChangeListener(this); showDeviationsView.setOnCheckedChangeListener(this); + showRatiosView.setOnCheckedChangeListener(this); notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications); notificationsView.setHasFixedSize(true); llm = new LinearLayoutManager(view.getContext()); notificationsView.setLayoutManager(llm); - - bgGraph.getGridLabelRenderer().setGridColor(Color.rgb(0x75, 0x75, 0x75)); + bgGraph.getGridLabelRenderer().setGridColor(MainApp.sResources.getColor(R.color.graphgrid)); bgGraph.getGridLabelRenderer().reloadStyles(); - iobGraph.getGridLabelRenderer().setGridColor(Color.rgb(0x75, 0x75, 0x75)); + 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); + rangeToDisplay = SP.getInt(R.string.key_rangetodisplay, 6); + bgGraph.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { rangeToDisplay += 6; rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; + SP.putInt(R.string.key_rangetodisplay, rangeToDisplay); updateGUI("rangeChange"); return false; } }); + lockScreen = (CheckBox) view.findViewById(R.id.overview_lockscreen); + if (lockScreen != null) { + lockScreen.setChecked(SP.getBoolean("lockscreen", false)); + lockScreen.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + SP.putBoolean("lockscreen", isChecked); + MainApp.bus().post(new EventSetWakeLock(isChecked)); + } + }); + } + return view; } @@ -301,7 +351,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @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)); @@ -328,34 +378,29 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { switch (buttonView.getId()) { case R.id.overview_showprediction: - SP.putBoolean("showprediction", showPredictionView.isChecked()); - scheduleUpdateGUI("onPredictionCheckedChanged"); - break; case R.id.overview_showbasals: - SP.putBoolean("showbasals", showBasalsView.isChecked()); - scheduleUpdateGUI("onBasalsCheckedChanged"); - break; case R.id.overview_showiob: - SP.putBoolean("showiob", showIobView.isChecked()); - scheduleUpdateGUI("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()); - scheduleUpdateGUI("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()); - scheduleUpdateGUI("onDeviationsCheckedChanged"); + break; + case R.id.overview_showratios: break; } + SP.putBoolean("showiob", showIobView.isChecked()); + SP.putBoolean("showprediction", showPredictionView.isChecked()); + SP.putBoolean("showbasals", showBasalsView.isChecked()); + SP.putBoolean("showcob", showCobView.isChecked()); + SP.putBoolean("showdeviations", showDeviationsView.isChecked()); + SP.putBoolean("showratios", showRatiosView.isChecked()); + scheduleUpdateGUI("onGraphCheckboxesCheckedChanged"); } @Override @@ -365,150 +410,150 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, activeloop.setFragmentEnabled(PluginBase.LOOP, false); activeloop.setFragmentVisible(PluginBase.LOOP, false); MainApp.getConfigBuilder().storeSettings(); - scheduleUpdateGUI("suspendmenu"); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(60); // upload 60 min, we don;t know real duration + 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(); - scheduleUpdateGUI("suspendmenu"); - ConfigBuilderPlugin.uploadOpenAPSOffline(0); + updateGUI("suspendmenu"); + NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.resume))) { activeloop.suspendTo(0L); - scheduleUpdateGUI("suspendmenu"); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(0); + NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.suspendloopfor1h))) { - activeloop.suspendTo(new Date().getTime() + 60L * 60 * 1000); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(60); + 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); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(120); + 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); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(180); + 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); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 10 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(600); + NSUpload.uploadOpenAPSOffline(600); return true; } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.disconnectpumpfor30m))) { - activeloop.suspendTo(new Date().getTime() + 30L * 60 * 1000); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 30L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 30); + PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 30, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(30); + 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); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 1 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 60); + PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 60, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(60); + 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); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 2 * 60); + PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 2 * 60, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(120); + 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); - scheduleUpdateGUI("suspendmenu"); + activeloop.suspendTo(System.currentTimeMillis() + 3 * 60L * 60 * 1000); + updateGUI("suspendmenu"); sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 3 * 60); + PumpEnactResult result = MainApp.getConfigBuilder().setTempBasalAbsolute(0d, 3 * 60, true); if (!result.success) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror)); } } }); - ConfigBuilderPlugin.uploadOpenAPSOffline(180); + NSUpload.uploadOpenAPSOffline(180); return true; } @@ -537,18 +582,6 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog(); treatmentDialogFragment.show(manager, "TreatmentDialog"); break; - case R.id.overview_canceltempbutton: - final PumpInterface pump = MainApp.getConfigBuilder(); - if (pump.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() { @@ -576,16 +609,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @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(); - MainApp.getConfigBuilder().uploadDeviceStatus(); - ObjectivesPlugin objectivesPlugin = (ObjectivesPlugin) MainApp.getSpecificPlugin(ObjectivesPlugin.class); + NSUpload.uploadDeviceStatus(); + ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); if (objectivesPlugin != null) { - objectivesPlugin.manualEnacts++; - objectivesPlugin.saveProgress(); + ObjectivesPlugin.manualEnacts++; + ObjectivesPlugin.saveProgress(); } } scheduleUpdateGUI("onClickAcceptTemp"); @@ -601,17 +635,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } void onClickQuickwizard() { - final BgReading actualBg = GlucoseStatus.actualBg(); - if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet - return; - final NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); + 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, false); + wizard.doCalc(profile, quickWizardEntry.carbs(), 0d, actualBg.valueToUnits(profile.getUnits()), 0d, true, true, false, false); final JSONObject boluscalcJSON = new JSONObject(); try { @@ -645,7 +676,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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)); @@ -656,8 +687,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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() { @@ -667,16 +698,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, sHandler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = pump.deliverTreatmentFromBolusWizard( - MainApp.getConfigBuilder().getActiveInsulin(), - 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)); @@ -732,13 +761,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } @Subscribe - public void onStatusEvent(final EventRefreshGui ev) { - scheduleUpdateGUI("EventRefreshGui"); + public void onStatusEvent(final EventRefreshOverview ev) { + scheduleUpdateGUI(ev.from); } @Subscribe public void onStatusEvent(final EventAutosensCalculationFinished ev) { - scheduleUpdateGUI("EventRefreshGui"); + scheduleUpdateGUI("EventAutosensCalculationFinished"); } @Subscribe @@ -746,39 +775,41 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, scheduleUpdateGUI("EventTreatmentChange"); } + @Subscribe + public void onStatusEvent(final EventCareportalEventChange ev) { + scheduleUpdateGUI("EventCareportalEventChange"); + } + @Subscribe public void onStatusEvent(final EventTempBasalChange ev) { scheduleUpdateGUI("EventTempBasalChange"); } @Subscribe - public void onStatusEvent(final EventNewBG ev) { - scheduleUpdateGUI("EventTempBasalChange"); + 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) { scheduleUpdateGUI("EventNewOpenLoopNotification"); } - @Subscribe - public void onStatusEvent(final EventNewBasalProfile ev) { - scheduleUpdateGUI("EventNewBasalProfile"); - } +// Handled by EventAutosensCalculationFinished +// @Subscribe +// public void onStatusEvent(final EventNewBasalProfile ev) { +// scheduleUpdateGUI("EventNewBasalProfile"); +// } @Subscribe - public void onStatusEvent(final EventTempTargetRangeChange ev) { - scheduleUpdateGUI("EventTempTargetRangeChange"); - } - - @Subscribe - public void onStatusEvent(final EventNewNotification n) { - updateNotifications(); - } - - @Subscribe - public void onStatusEvent(final EventDismissNotification n) { - updateNotifications(); + public void onStatusEvent(final EventTempTargetChange ev) { + scheduleUpdateGUI("EventTempTargetChange"); } @Subscribe @@ -799,19 +830,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, activity.runOnUiThread(new Runnable() { @Override public void run() { - acceptTempLayout.setVisibility(View.GONE); + if (acceptTempLayout != null) + acceptTempLayout.setVisibility(View.GONE); } }); } + private void clearNotification() { + NotificationManager notificationManager = + (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(Constants.notificationID); + } + private void updatePumpStatus(String status) { 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); } @@ -836,35 +872,74 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (scheduledUpdate != null) scheduledUpdate.cancel(false); Runnable task = new UpdateRunnable(); - final int msec = 400; + final int msec = 500; scheduledUpdate = worker.schedule(task, msec, TimeUnit.MILLISECONDS); } @SuppressLint("SetTextI18n") public void updateGUI(String from) { log.debug("updateGUI entered from: " + from); - updateNotifications(); - BgReading actualBG = GlucoseStatus.actualBg(); - BgReading lastBG = GlucoseStatus.lastBg(); + Date updateGUIStart = new Date(); - if (MainApp.getConfigBuilder() == null || MainApp.getConfigBuilder().getActiveProfile() == null || MainApp.getConfigBuilder().getActiveProfile().getProfile() == null) {// app not initialized yet + if (getActivity() == null) + return; + + if (timeView != null) { //must not exists + timeView.setText(DateUtil.timeString(new Date())); + } + if (MainApp.getConfigBuilder().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); } + 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(); - // Skip if not initialized yet - if (bgGraph == null) - return; + Profile profile = MainApp.getConfigBuilder().getProfile(); + String units = profile.getUnits(); - if (getActivity() == null) + if (units == null) { + pumpStatusView.setText(R.string.noprofileset); + pumpStatusLayout.setVisibility(View.VISIBLE); + loopStatusLayout.setVisibility(View.GONE); return; + } + + Double lowLine = SP.getDouble("low_mark", 0d); + Double highLine = SP.getDouble("high_mark", 0d); + + //Start with updating the BG as it is unaffected by loop. + // **** BG value **** + 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(units)); + arrowView.setText(lastBG.directionToSymbol()); + bgView.setTextColor(color); + arrowView.setTextColor(color); + GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); + if (glucoseStatus != null) { + deltaView.setText("Δ " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units); + if (avgdeltaView != null) + avgdeltaView.setText("øΔ15m: " + Profile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units) + + " øΔ40m: " + Profile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units)); + } else { + deltaView.setText("Δ " + MainApp.sResources.getString(R.string.notavailable)); + if (avgdeltaView != null) + avgdeltaView.setText(""); + } + } // open loop mode final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; @@ -872,7 +947,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, apsModeView.setVisibility(View.VISIBLE); 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.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setText(String.format(MainApp.sResources.getString(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend())); @@ -901,83 +976,120 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } // 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.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground)); - 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.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); - } + TempTarget tempTarget = MainApp.getConfigBuilder().getTempTargetFromHistory(System.currentTimeMillis()); + if (tempTarget != null) { + tempTargetView.setTextColor(Color.BLACK); + tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetBackground)); + tempTargetView.setVisibility(View.VISIBLE); + tempTargetView.setText(Profile.toTargetRangeString(tempTarget.low, tempTarget.high, Constants.MGDL, units)); } else { + tempTargetView.setTextColor(Color.WHITE); + tempTargetView.setBackgroundColor(MainApp.sResources.getColor(R.color.tempTargetDisabledBackground)); + tempTargetView.setText(Profile.toTargetRangeString(profile.getTargetLow(), profile.getTargetHigh(), units, units)); + tempTargetView.setVisibility(View.VISIBLE); + } + if (Config.NSCLIENT && tempTarget == null) { tempTargetView.setVisibility(View.GONE); } // **** Temp button **** - boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed - showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist - showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result - showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.changeRequested; // change is requested + if (acceptTempLayout != null) { + boolean showAcceptButton = !MainApp.getConfigBuilder().isClosedModeEnabled(); // Open mode needed + showAcceptButton = showAcceptButton && finalLastRun != null && finalLastRun.lastAPSRun != null; // aps result must exist + showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result + showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.changeRequested; // change is requested - if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) { - acceptTempLayout.setVisibility(View.VISIBLE); - acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); - } else { - acceptTempLayout.setVisibility(View.GONE); + if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) { + acceptTempLayout.setVisibility(View.VISIBLE); + acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); + } else { + acceptTempLayout.setVisibility(View.GONE); + } } // **** Calibration button **** - if (MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginBase.BGSOURCE) && profile != null && GlucoseStatus.actualBg() != null) { - calibrationButton.setVisibility(View.VISIBLE); - } else { - calibrationButton.setVisibility(View.GONE); + if (calibrationButton != 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()) { - cancelTempButton.setVisibility(View.VISIBLE); - cancelTempButton.setText(MainApp.instance().getString(R.string.cancel) + "\n" + activeTemp.toStringShort()); - runningTempView.setVisibility(View.VISIBLE); - runningTempView.setText(activeTemp.toString()); + final TemporaryBasal activeTemp = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()); + String basalText = ""; + if (shorttextmode) { + if (activeTemp != null) { + basalText = "T: " + activeTemp.toStringVeryShort(); + } else { + basalText = DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getProfile().getBasal()) + "U/h"; + } + baseBasalView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String fullText = MainApp.sResources.getString(R.string.virtualpump_basebasalrate_label) + ": " + DecimalFormatter.to2Decimal(MainApp.getConfigBuilder().getProfile().getBasal()) + "U/h\n"; + if (activeTemp != null) { + fullText += MainApp.sResources.getString(R.string.virtualpump_tempbasal_label) + ": " + activeTemp.toStringFull(); + } + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.basal), fullText, null); + } + }); + } else { - cancelTempButton.setVisibility(View.GONE); - runningTempView.setVisibility(View.GONE); + 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)"; + } + } + if (activeTemp != null) { + baseBasalView.setTextColor(MainApp.sResources.getColor(R.color.basal)); + } else { + baseBasalView.setTextColor(Color.WHITE); + } - if (pump.getPumpDescription().isTempBasalCapable) { - basalLayout.setVisibility(View.VISIBLE); - baseBasalView.setText(DecimalFormatter.to2Decimal(pump.getBaseBasalRate()) + " U/h"); - } else { - basalLayout.setVisibility(View.GONE); + baseBasalView.setText(basalText); + + final ExtendedBolus extendedBolus = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + String extendedBolusText = ""; + if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) { + extendedBolusText = extendedBolus.toString(); + } + if (extendedBolusView != null) { // must not exists in all layouts + if (shorttextmode) { + if (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses()) { + extendedBolusText = DecimalFormatter.to2Decimal(extendedBolus.absoluteRate()) + "U/h"; + } else { + extendedBolusText = ""; + } + extendedBolusView.setText(extendedBolusText); + extendedBolusView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.extendedbolus), extendedBolus.toString(), null); + } + }); + + } else { + extendedBolusView.setText(extendedBolusText); + } } - if (profile != null && profile.getActiveProfile() != null) { - activeProfileView.setText(profile.getActiveProfile()); - activeProfileView.setBackgroundColor(Color.GRAY); - } + activeProfileView.setText(MainApp.getConfigBuilder().getProfileName()); + activeProfileView.setBackgroundColor(Color.GRAY); activeProfileView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - 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 profileswitch = CareportalFragment.profileswitch; profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch); + newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); return true; } @@ -990,9 +1102,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public boolean onLongClick(View view) { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog(); - final OptionsToShow temptarget = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget, false, false, false, false, true, false, false, false, false, true); + final OptionsToShow temptarget = CareportalFragment.temptarget; temptarget.executeTempTarget = true; - newTTDialog.setOptions(temptarget); + newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget); newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); return true; } @@ -1005,7 +1117,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, quickWizardButton.setVisibility(View.VISIBLE); 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, false); + wizard.doCalc(profile, quickWizardEntry.carbs(), 0d, lastBG.valueToUnits(units), 0d, true, true, false, false); text += " " + DecimalFormatter.to2Decimal(wizard.calculatedTotalInsulin) + "U"; quickWizardButton.setText(text); if (wizard.calculatedTotalInsulin <= 0) @@ -1013,43 +1125,28 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } else quickWizardButton.setVisibility(View.GONE); - String units = profile.getUnits(); + // 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); + } + - Double lowLine = SP.getDouble("low_mark", 0d); - Double highLine = SP.getDouble("high_mark", 0d); if (lowLine < 1) { - lowLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units); + lowLine = Profile.fromMgdlToUnits(OverviewPlugin.bgTargetLow, units); } if (highLine < 1) { - highLine = NSProfile.fromMgdlToUnits(OverviewPlugin.bgTargetHigh, units); + 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)); - } else { - deltaView.setText("Δ " + MainApp.sResources.getString(R.string.notavailable)); - avgdeltaView.setText(""); - } + if (lastBG == null) { //left this here as it seems you want to exit at this point if it is null... - BgReading.units = profile.getUnits(); - } else return; - + } Integer flag = bgView.getPaintFlags(); if (actualBG == null) { flag |= Paint.STRIKE_THRU_TEXT_FLAG; @@ -1057,23 +1154,48 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, flag &= ~Paint.STRIKE_THRU_TEXT_FLAG; bgView.setPaintFlags(flag); - Long agoMsec = new Date().getTime() - lastBG.timeIndex; + Long agoMsec = System.currentTimeMillis() - 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(); + final IobTotal bolusIob = MainApp.getConfigBuilder().getLastCalculationTreatments().round(); + final IobTotal basalIob = MainApp.getConfigBuilder().getLastCalculationTempBasals().round(); + + if (shorttextmode) { + String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U"; + iobView.setText(iobtext); + iobView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U\n" + + getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U\n" + + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U\n"; + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.iob), iobtext, null); + } + }); + } else if (MainApp.sResources.getBoolean(R.bool.isTablet)) { + String iobtext = 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); + } else { + String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + + DecimalFormatter.to2Decimal(bolusIob.iob) + "/" + + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")"; + iobView.setText(iobtext); } - 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(System.currentTimeMillis()); + if (autosensData != null) + cobText = (int) autosensData.cob + " g"; + 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)) { @@ -1081,13 +1203,48 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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); } + getActivity().findViewById(R.id.overview_showprediction_label).setVisibility(View.GONE); + } + + // pump status from ns + if (pumpDeviceStatusView != null) { + pumpDeviceStatusView.setText(NSDeviceStatus.getInstance().getPumpStatus()); + pumpDeviceStatusView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.pump), NSDeviceStatus.getInstance().getExtendedPumpStatus(), null); + } + }); + } + + // OpenAPS status from ns + if (openapsDeviceStatusView != null) { + openapsDeviceStatusView.setText(NSDeviceStatus.getInstance().getOpenApsStatus()); + openapsDeviceStatusView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.openaps), NSDeviceStatus.getInstance().getExtendedOpenApsStatus(), null); + } + }); + } + + // Uploader status from ns + if (uploaderDeviceStatusView != null) { + uploaderDeviceStatusView.setText(NSDeviceStatus.getInstance().getUploaderStatus()); + uploaderDeviceStatusView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus(), null); + } + }); + } // ****** GRAPH ******* + //log.debug("updateGUI checkpoint 1"); // allign to hours Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(new Date().getTime()); + calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.MILLISECOND, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MINUTE, 0); @@ -1098,50 +1255,48 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, long fromTime; long endTime; if (showPrediction) { - int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - new Date().getTime()) / (60 * 60 * 1000)); + int predHours = (int) (Math.ceil(((DetermineBasalResultAMA) finalLastRun.constraintsProcessed).getLatestPredictionsTime() - System.currentTimeMillis()) / (60 * 60 * 1000)); predHours = Math.min(2, predHours); predHours = Math.max(0, predHours); - hoursToFetch = (int) (rangeToDisplay - predHours); - toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding + hoursToFetch = rangeToDisplay - predHours; + toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; endTime = toTime + predHours * 60 * 60 * 1000L; } else { hoursToFetch = rangeToDisplay; - toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding + toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - Graphview specific fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; endTime = toTime; } LineGraphSeries basalsLineSeries = null; + LineGraphSeries absoluteBasalsLineSeries = null; LineGraphSeries baseBasalsSeries = null; LineGraphSeries tempBasalsSeries = null; AreaGraphSeries areaSeries; LineGraphSeries seriesNow, seriesNow2; - PointsGraphSeries seriesInRage; - PointsGraphSeries seriesLow; - PointsGraphSeries seriesHigh; - PointsGraphSeries predSeries; - PointsWithLabelGraphSeries seriesTreatments; // **** TEMP BASALS graph **** Double maxBasalValueFound = 0d; - long now = new Date().getTime(); + long now = System.currentTimeMillis(); if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { List baseBasalArray = new ArrayList<>(); List tempBasalArray = new ArrayList<>(); List basalLineArray = new ArrayList<>(); + List absoluteBasalLineArray = new ArrayList<>(); double lastLineBasal = 0; + double lastAbsoluteLineBasal = 0; double lastBaseBasal = 0; double lastTempBasal = 0; - for (long time = fromTime; time < now; time += 5 * 60 * 1000L) { - TempBasal tb = MainApp.getConfigBuilder().getTempBasal(new Date(time)); - double baseBasalValue = profile.getBasal(NSProfile.secondsFromMidnight(new Date(time))); - double baseLineValue = baseBasalValue; + 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 (tb != null) { - tempBasalValue = tb.tempBasalConvertedToAbsolute(new Date(time)); + if (basalData.isTempBasalRunning) { + absoluteLineValue = tempBasalValue = basalData.tempBasalAbsolute; if (tempBasalValue != lastTempBasal) { tempBasalArray.add(new DataPoint(time, lastTempBasal)); tempBasalArray.add(new DataPoint(time, basal = tempBasalValue)); @@ -1163,31 +1318,37 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } - if (baseLineValue != lastLineBasal) { + if (baseBasalValue != lastLineBasal) { basalLineArray.add(new DataPoint(time, lastLineBasal)); - basalLineArray.add(new DataPoint(time, baseLineValue)); + basalLineArray.add(new DataPoint(time, baseBasalValue)); + } + if (absoluteLineValue != lastAbsoluteLineBasal) { + absoluteBasalLineArray.add(new DataPoint(time, lastAbsoluteLineBasal)); + absoluteBasalLineArray.add(new DataPoint(time, basal)); } - lastLineBasal = baseLineValue; + lastAbsoluteLineBasal = absoluteLineValue; + lastLineBasal = baseBasalValue; lastTempBasal = tempBasalValue; maxBasalValueFound = Math.max(maxBasalValueFound, basal); } basalLineArray.add(new DataPoint(now, lastLineBasal)); baseBasalArray.add(new DataPoint(now, lastBaseBasal)); tempBasalArray.add(new DataPoint(now, lastTempBasal)); + absoluteBasalLineArray.add(new DataPoint(now, lastAbsoluteLineBasal)); DataPoint[] baseBasal = new DataPoint[baseBasalArray.size()]; baseBasal = baseBasalArray.toArray(baseBasal); baseBasalsSeries = new LineGraphSeries<>(baseBasal); baseBasalsSeries.setDrawBackground(true); - baseBasalsSeries.setBackgroundColor(Color.argb(200, 0x3F, 0x51, 0xB5)); + 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(Color.argb(200, 0x03, 0xA9, 0xF4)); + tempBasalsSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.tempbasal)); tempBasalsSeries.setThickness(0); DataPoint[] basalLine = new DataPoint[basalLineArray.size()]; @@ -1199,11 +1360,23 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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; @@ -1212,26 +1385,42 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, FixedLineGraphSeries iobSeries; FixedLineGraphSeries cobSeries; BarGraphSeries devSeries; + LineGraphSeries ratioSeries; Double maxIobValueFound = 0d; Double maxCobValueFound = 0d; Double maxDevValueFound = 0d; + Double maxRatioValueFound = 0d; - if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked()) { + if (showIobView.isChecked() || showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { //Date start = new Date(); List iobArray = new ArrayList<>(); List cobArray = new ArrayList<>(); List devArray = new ArrayList<>(); + List ratioArray = new ArrayList<>(); + double lastIob = 0; + int lastCob = 0; for (long time = fromTime; time <= now; time += 5 * 60 * 1000L) { if (showIobView.isChecked()) { - IobTotal iob = IobCobCalculatorPlugin.calulateFromTreatmentsAndTemps(time); - iobArray.add(new DataPoint(time, iob.iob)); - maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob.iob)); + double iob = IobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(time).iob; + if (Math.abs(lastIob - iob) > 0.02) { + if (Math.abs(lastIob - iob) > 0.2) + iobArray.add(new DataPoint(time, lastIob)); + iobArray.add(new DataPoint(time, iob)); + maxIobValueFound = Math.max(maxIobValueFound, Math.abs(iob)); + lastIob = iob; + } } - if (showCobView.isChecked() || showDeviationsView.isChecked()) { + if (showCobView.isChecked() || showDeviationsView.isChecked() || showRatiosView.isChecked()) { AutosensData autosensData = IobCobCalculatorPlugin.getAutosensData(time); if (autosensData != null && showCobView.isChecked()) { - cobArray.add(new DataPoint(time, autosensData.cob)); - maxCobValueFound = Math.max(maxCobValueFound, autosensData.cob); + 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; // "=" @@ -1241,6 +1430,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, devArray.add(new DeviationDataPoint(time, autosensData.deviation, color)); maxDevValueFound = Math.max(maxDevValueFound, Math.abs(autosensData.deviation)); } + if (autosensData != null && showRatiosView.isChecked()) { + ratioArray.add(new DataPoint(time, autosensData.autosensRatio)); + maxRatioValueFound = Math.max(maxRatioValueFound, Math.abs(autosensData.autosensRatio)); + } } } //Profiler.log(log, "IOB processed", start); @@ -1253,18 +1446,49 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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; + Double maxByScale = null; + int graphsToShow = 0; + if (showIobView.isChecked()) { + if (maxByScale == null) maxByScale = maxIobValueFound; + graphsToShow++; } + if (showCobView.isChecked()) { + if (maxByScale == null) maxByScale = maxCobValueFound; + graphsToShow++; + } + if (showDeviationsView.isChecked()) { + if (maxByScale == null) maxByScale = maxDevValueFound; + graphsToShow++; + } + if (showRatiosView.isChecked()) { + if (maxByScale == null) maxByScale = maxRatioValueFound; + graphsToShow++; + } + + if (graphsToShow > 1) { + if (!maxByScale.equals(maxCobValueFound)) { + List cobArrayRescaled = new ArrayList<>(); + for (int ci = 0; ci < cobArray.size(); ci++) { + cobArrayRescaled.add(new DataPoint(cobArray.get(ci).getX(), cobArray.get(ci).getY() * maxByScale / maxCobValueFound / 2)); + } + cobArray = cobArrayRescaled; + } + if (!maxByScale.equals(maxDevValueFound)) { + List devArrayRescaled = new ArrayList<>(); + for (int ci = 0; ci < devArray.size(); ci++) { + devArrayRescaled.add(new DeviationDataPoint(devArray.get(ci).getX(), devArray.get(ci).getY() * maxByScale / maxDevValueFound, devArray.get(ci).color)); + } + devArray = devArrayRescaled; + } + if (!maxByScale.equals(maxRatioValueFound)) { + List ratioArrayRescaled = new ArrayList<>(); + for (int ci = 0; ci < ratioArray.size(); ci++) { + ratioArrayRescaled.add(new DataPoint(ratioArray.get(ci).getX(), (ratioArray.get(ci).getY() - 1) * maxByScale / maxRatioValueFound)); + } + ratioArray = ratioArrayRescaled; + } + } + // COB DataPoint[] cobData = new DataPoint[cobArray.size()]; cobData = cobArray.toArray(cobData); @@ -1284,39 +1508,49 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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.removeAllSeries(); + // RATIOS + DataPoint[] ratioData = new DataPoint[ratioArray.size()]; + ratioData = ratioArray.toArray(ratioData); + ratioSeries = new LineGraphSeries<>(ratioData); + ratioSeries.setColor(MainApp.sResources.getColor(R.color.ratio)); + ratioSeries.setThickness(3); - if (showIobView.isChecked()) { - iobGraph.addSeries(iobSeries); + iobGraph.getSeries().clear(); + + if (showIobView.isChecked() && iobData.length > 0) { + addSeriesWithoutInvalidate(iobSeries, iobGraph); } if (showCobView.isChecked() && cobData.length > 0) { - iobGraph.addSeries(cobSeries); + addSeriesWithoutInvalidate(cobSeries, iobGraph); } if (showDeviationsView.isChecked() && devData.length > 0) { - iobGraph.addSeries(devSeries); + addSeriesWithoutInvalidate(devSeries, iobGraph); + } + if (showRatiosView.isChecked() && ratioData.length > 0) { + addSeriesWithoutInvalidate(ratioSeries, iobGraph); } iobGraph.setVisibility(View.VISIBLE); } else { iobGraph.setVisibility(View.GONE); } + //log.debug("updateGUI checkpoint 3"); // remove old data from graph bgGraph.getSecondScale().getSeries().clear(); - bgGraph.removeAllSeries(); + bgGraph.getSeries().clear(); + //log.debug("updateGUI checkpoint 4"); - // **** HIGH and LOW targets graph **** + // **** Area **** DoubleDataPoint[] areaDataPoints = new DoubleDataPoint[]{ new DoubleDataPoint(fromTime, lowLine, highLine), new DoubleDataPoint(endTime, lowLine, highLine) }; - bgGraph.addSeries(areaSeries = new AreaGraphSeries<>(areaDataPoints)); + areaSeries = new AreaGraphSeries<>(areaDataPoints); + addSeriesWithoutInvalidate(areaSeries, bgGraph); areaSeries.setColor(0); areaSeries.setDrawBackground(true); - areaSeries.setBackgroundColor(Color.argb(40, 0, 255, 0)); + areaSeries.setBackgroundColor(MainApp.sResources.getColor(R.color.inrangebackground)); // set manual x bounds to have nice steps bgGraph.getViewport().setMaxX(endTime); @@ -1330,130 +1564,109 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, 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 lowArray = new ArrayList<>(); - List highArray = new ArrayList<>(); + List bgListArray = new ArrayList<>(); - if (bgReadingsArray.size() == 0) + if (bgReadingsArray.size() == 0) { return; + } Iterator it = bgReadingsArray.iterator(); Double maxBgValue = 0d; while (it.hasNext()) { BgReading bg = it.next(); if (bg.value > maxBgValue) maxBgValue = bg.value; - if (bg.valueToUnits(units) < lowLine) - lowArray.add(bg); - else if (bg.valueToUnits(units) > highLine) - highArray.add(bg); - else - inRangeArray.add(bg); + bgListArray.add(bg); } - maxBgValue = NSProfile.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[] low = new BgReading[lowArray.size()]; - BgReading[] high = new BgReading[highArray.size()]; - inRange = inRangeArray.toArray(inRange); - low = lowArray.toArray(low); - high = highArray.toArray(high); - - - if (inRange.length > 0) { - bgGraph.addSeries(seriesInRage = new PointsGraphSeries<>(inRange)); - seriesInRage.setShape(PointsGraphSeries.Shape.POINT); - seriesInRage.setSize(5); - seriesInRage.setColor(MainApp.sResources.getColor(R.color.inrange)); - } - - if (low.length > 0) { - bgGraph.addSeries(seriesLow = new PointsGraphSeries<>(low)); - seriesLow.setShape(PointsGraphSeries.Shape.POINT); - seriesLow.setSize(5); - seriesLow.setColor(MainApp.sResources.getColor(R.color.low)); - } - - if (high.length > 0) { - bgGraph.addSeries(seriesHigh = new PointsGraphSeries<>(high)); - seriesHigh.setShape(PointsGraphSeries.Shape.POINT); - seriesHigh.setSize(5); - seriesHigh.setColor(MainApp.sResources.getColor(R.color.high)); - } - 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(MainApp.sResources.getColor(R.color.prediction)); - } + bgListArray.addAll(predArray); } - // **** NOW line **** - DataPoint[] nowPoints = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxBgValue) - }; - bgGraph.addSeries(seriesNow = new LineGraphSeries<>(nowPoints)); - seriesNow.setDrawDataPoints(false); - DataPoint[] nowPoints2 = new DataPoint[]{ - new DataPoint(now, 0), - new DataPoint(now, maxIobValueFound) - }; - iobGraph.addSeries(seriesNow2 = new LineGraphSeries<>(nowPoints2)); - 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); + maxBgValue = Profile.fromMgdlToUnits(maxBgValue, units); + maxBgValue = units.equals(Constants.MGDL) ? Round.roundTo(maxBgValue, 40d) + 80 : Round.roundTo(maxBgValue, 2d) + 4; + if (highLine > maxBgValue) maxBgValue = highLine; + Integer numOfVertLines = units.equals(Constants.MGDL) ? (int) (maxBgValue / 40 + 1) : (int) (maxBgValue / 2 + 1); + DataPointWithLabelInterface[] bg = new DataPointWithLabelInterface[bgListArray.size()]; + bg = bgListArray.toArray(bg); + if (bg.length > 0) { + addSeriesWithoutInvalidate(new PointsWithLabelGraphSeries<>(bg), bgGraph); + } + + //log.debug("updateGUI checkpoint 6"); // Treatments - List treatments = MainApp.getConfigBuilder().getActiveTreatments().getTreatments(); - List filteredTreatments = new ArrayList(); + List filteredTreatments = new ArrayList<>(); + + List treatments = MainApp.getConfigBuilder().getTreatmentsFromHistory(); for (int tx = 0; tx < treatments.size(); tx++) { Treatment t = treatments.get(tx); - if (t.getTimeIndex() < fromTime || t.getTimeIndex() > now) continue; - t.setYValue(bgReadingsArray); + if (t.getX() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); filteredTreatments.add(t); } - Treatment[] treatmentsArray = new Treatment[filteredTreatments.size()]; + + //log.debug("updateGUI checkpoint 7"); + // ProfileSwitch + List profileSwitches = MainApp.getConfigBuilder().getProfileSwitchesFromHistory().getList(); + + for (int tx = 0; tx < profileSwitches.size(); tx++) { + DataPointWithLabelInterface t = profileSwitches.get(tx); + if (t.getX() < fromTime || t.getX() > endTime) continue; + filteredTreatments.add(t); + } + + //log.debug("updateGUI checkpoint 8"); + // Extended bolus + if (!pump.isFakingTempsByExtendedBoluses()) { + List extendedBoluses = MainApp.getConfigBuilder().getExtendedBolusesFromHistory().getList(); + + for (int tx = 0; tx < extendedBoluses.size(); tx++) { + DataPointWithLabelInterface t = extendedBoluses.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + if (t.getDuration() == 0) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); + filteredTreatments.add(t); + } + } + + //log.debug("updateGUI checkpoint 9"); + // Careportal + List careportalEvents = MainApp.getDbHelper().getCareportalEventsFromTime(fromTime, true); + + for (int tx = 0; tx < careportalEvents.size(); tx++) { + DataPointWithLabelInterface t = careportalEvents.get(tx); + if (t.getX() + t.getDuration() < fromTime || t.getX() > endTime) continue; + t.setY(getNearestBg((long) t.getX(), bgReadingsArray)); + filteredTreatments.add(t); + } + + DataPointWithLabelInterface[] treatmentsArray = new DataPointWithLabelInterface[filteredTreatments.size()]; treatmentsArray = filteredTreatments.toArray(treatmentsArray); if (treatmentsArray.length > 0) { - 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); bgGraph.getViewport().setMinY(0); bgGraph.getViewport().setYAxisBoundsManual(true); - bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfHorizLines); + bgGraph.getGridLabelRenderer().setNumVerticalLabels(numOfVertLines); // set second scale if (pump.getPumpDescription().isTempBasalCapable && showBasalsView.isChecked()) { + bgGraph.getSecondScale().setMinY(0); + bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); bgGraph.getSecondScale().addSeries(baseBasalsSeries); bgGraph.getSecondScale().addSeries(tempBasalsSeries); bgGraph.getSecondScale().addSeries(basalsLineSeries); - bgGraph.getSecondScale().setMinY(0); - bgGraph.getSecondScale().setMaxY(maxBgValue / lowLine * maxBasalValueFound * 1.2d); + bgGraph.getSecondScale().addSeries(absoluteBasalsLineSeries); } bgGraph.getSecondScale().setLabelFormatter(new LabelFormatter() { @Override @@ -1467,11 +1680,55 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } }); + //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); + Profiler.log(log, from, updateGUIStart); } + public double getNearestBg(long date, List bgReadingsArray) { + double bg = 0; + String units = MainApp.getConfigBuilder().getProfileUnits(); + for (int r = bgReadingsArray.size() - 1; r >= 0; r--) { + BgReading reading = bgReadingsArray.get(r); + if (reading.date > date) continue; + bg = Profile.fromMgdlToUnits(reading.value, units); + break; + } + return bg; + } + + void addSeriesWithoutInvalidate(Series s, GraphView graph) { + s.onGraphViewAttached(graph); + graph.getSeries().add(s); + } + + //Notifications - public static class RecyclerViewAdapter extends RecyclerView.Adapter { + static class RecyclerViewAdapter extends RecyclerView.Adapter { List notificationsList; @@ -1482,14 +1739,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, @Override public NotificationsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.overview_notification_item, viewGroup, false); - NotificationsViewHolder notificationsViewHolder = new NotificationsViewHolder(v); - return notificationsViewHolder; + return new NotificationsViewHolder(v); } @Override public void onBindViewHolder(NotificationsViewHolder holder, int position) { Notification notification = notificationsList.get(position); holder.dismiss.setTag(notification); + if(Objects.equals(notification.text, MainApp.sResources.getString(R.string.nsalarm_staledata))) + holder.dismiss.setText("snooze"); holder.text.setText(notification.text); holder.time.setText(DateUtil.timeString(notification.date)); if (notification.level == Notification.URGENT) @@ -1500,6 +1758,8 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationLow)); else if (notification.level == Notification.INFO) holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationInfo)); + else if (notification.level == Notification.ANNOUNCEMENT) + holder.cv.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.notificationAnnouncement)); } @Override @@ -1512,7 +1772,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, super.onAttachedToRecyclerView(recyclerView); } - public static class NotificationsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + static class NotificationsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { CardView cv; TextView time; TextView text; @@ -1533,6 +1793,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, switch (v.getId()) { case R.id.notification_dismiss: MainApp.bus().post(new EventDismissNotification(notification.id)); + if (notification.nsAlarm != null) { + BroadcastAckAlarm.handleClearAlarm(notification.nsAlarm, MainApp.instance().getApplicationContext(), 60 * 60 * 1000L); + } + // Adding current time to snooze if we got staleData + log.debug("Notification text is: "+notification.text); + if(notification.text.equals(MainApp.sResources.getString(R.string.nsalarm_staledata))){ + NotificationStore nstore = getPlugin().notificationStore; + long msToSnooze = SP.getInt("nsalarm_staledatavalue",15)*60*1000L; + log.debug("snooze nsalarm_staledatavalue in minutes is "+SP.getInt("nsalarm_staledatavalue",15)+"\n in ms is: "+msToSnooze+" currentTimeMillis is: "+System.currentTimeMillis()); + nstore.snoozeTo(System.currentTimeMillis()+(SP.getInt("nsalarm_staledatavalue",15)*60*1000L)); + } break; } } @@ -1547,6 +1818,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, public void run() { NotificationStore nstore = getPlugin().notificationStore; nstore.removeExpired(); + nstore.unSnooze(); if (nstore.store.size() > 0) { RecyclerViewAdapter adapter = new RecyclerViewAdapter(nstore.store); notificationsView.setAdapter(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 b513d68dac..30148f94c2 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 @@ -7,6 +7,7 @@ import org.json.JSONException; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; @@ -17,8 +18,8 @@ import info.nightscout.utils.SP; */ public class OverviewPlugin implements PluginBase { - public static Double bgTargetLow = 80d; - public static Double bgTargetHigh = 180d; + public static double bgTargetLow = 80d; + public static double bgTargetHigh = 180d; public QuickWizard quickWizard = new QuickWizard(); @@ -99,11 +100,13 @@ public class OverviewPlugin implements PluginBase { @Subscribe public void onStatusEvent(final EventNewNotification n) { notificationStore.add(n.notification); + MainApp.bus().post(new EventRefreshOverview("EventNewNotification")); } @Subscribe public void onStatusEvent(final EventDismissNotification n) { - notificationStore.remove(n.id); + if (notificationStore.remove(n.id)) + MainApp.bus().post(new EventRefreshOverview("EventDismissNotification")); } } 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/activities/QuickWizardListActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/activities/QuickWizardListActivity.java index ef2ebe240c..9fc731b4f5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/activities/QuickWizardListActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/activities/QuickWizardListActivity.java @@ -124,7 +124,7 @@ public class QuickWizardListActivity extends AppCompatActivity implements View.O llm = new LinearLayoutManager(this); recyclerView.setLayoutManager(llm); - RecyclerViewAdapter adapter = new RecyclerViewAdapter(((OverviewPlugin) MainApp.getSpecificPlugin(OverviewPlugin.class)).quickWizard, getSupportFragmentManager()); + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard, getSupportFragmentManager()); recyclerView.setAdapter(adapter); adButton = (Button) findViewById(R.id.overview_quickwizardactivity_add_button); @@ -164,7 +164,7 @@ public class QuickWizardListActivity extends AppCompatActivity implements View.O activity.runOnUiThread(new Runnable() { @Override public void run() { - RecyclerViewAdapter adapter = new RecyclerViewAdapter(((OverviewPlugin) MainApp.getSpecificPlugin(OverviewPlugin.class)).quickWizard, getSupportFragmentManager()); + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getSpecificPlugin(OverviewPlugin.class).quickWizard, getSupportFragmentManager()); recyclerView.swapAdapter(adapter, false); } }); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java new file mode 100644 index 0000000000..519341172d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/events/EventSetWakeLock.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.Overview.events; + +/** + * Created by mike on 02.07.2017. + */ + +public class EventSetWakeLock { + public boolean lock = false; + + public EventSetWakeLock(boolean val) { + lock = val; + } +} 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/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/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java index c8ba40369d..881e472a1d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/graphExtensions/TimeAsXAxisLabelFormatter.java @@ -23,10 +23,8 @@ public class TimeAsXAxisLabelFormatter extends DefaultLabelFormatter { public String formatLabel(double value, boolean isValueX) { if (isValueX) { // format as date - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis((long) value); DateFormat dateFormat = new SimpleDateFormat(mFormat); - return dateFormat.format(calendar.getTimeInMillis()); + return dateFormat.format((long) value); } else { return super.formatLabel(value, isValueX); } 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 78e7791c2d..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Persistentnotification/PersistentNotificationFragment.java +++ /dev/null @@ -1,12 +0,0 @@ -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 index 6acd7a810c..68d1ed487a 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 @@ -11,34 +11,32 @@ import android.support.v7.app.NotificationCompat; import com.squareup.otto.Subscribe; -import java.util.Date; - import info.nightscout.androidaps.Constants; 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; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; 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; @@ -56,7 +54,7 @@ public class PersistentNotificationPlugin implements PluginBase{ @Override public String getFragmentClass() { - return PersistentNotificationFragment.class.getName(); + return null; } @Override @@ -98,17 +96,17 @@ public class PersistentNotificationPlugin implements PluginBase{ @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); @@ -117,18 +115,20 @@ public class PersistentNotificationPlugin implements PluginBase{ String line1 = ctx.getString(R.string.noprofile); - if (MainApp.getConfigBuilder().getActiveProfile() == null) return; - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + + if (MainApp.getConfigBuilder().getActiveProfileInterface() == null || MainApp.getConfigBuilder().getProfile() == null) + return; + String units = MainApp.getConfigBuilder().getProfileUnits(); - BgReading lastBG = GlucoseStatus.lastBg(); + BgReading lastBG = DatabaseHelper.lastBg(); GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if(profile != null && lastBG != null) { - line1 = lastBG.valueToUnitsToString(profile.getUnits()); + if (lastBG != null) { + line1 = lastBG.valueToUnitsToString(units); if (glucoseStatus != null) { - line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, profile.getUnits()) - + " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, profile.getUnits()); + line1 += " Δ" + deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + + " avgΔ" + deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units); } else { line1 += " " + ctx.getString(R.string.old_data) + @@ -138,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(System.currentTimeMillis()); 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)"; @@ -159,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); @@ -193,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; @@ -240,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(); @@ -256,7 +258,7 @@ public class PersistentNotificationPlugin implements PluginBase{ } @Subscribe - public void onStatusEvent(final EventRefreshGui ev) { + public void onStatusEvent(final EventRefreshOverview ev) { updateNotification(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java index 7ae97a17b5..c7d7333aba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfileFragment.java @@ -33,13 +33,17 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; +import info.nightscout.androidaps.events.EventNewBasalProfile; +import info.nightscout.androidaps.events.EventProfileSwitchChange; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.SafeParse; -public class CircadianPercentageProfileFragment extends Fragment { +public class CircadianPercentageProfileFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfileFragment.class); private static CircadianPercentageProfilePlugin circadianPercentageProfilePlugin = new CircadianPercentageProfilePlugin(); @@ -74,6 +78,50 @@ public class CircadianPercentageProfileFragment extends Fragment { static Boolean percentageViewHint = true; static Boolean timeshiftViewHint = true; + TextWatcher textWatch = new TextWatcher() { + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + + if (percentageView.testValidity()) { + if (SafeParse.stringToInt(percentageView.getText().toString()) == 0) { + circadianPercentageProfilePlugin.percentage = 100; + } else { + circadianPercentageProfilePlugin.percentage = SafeParse.stringToInt(percentageView.getText().toString()); + } + updateProfileInfo(); + } + if (timeshiftView.testValidity()) { + circadianPercentageProfilePlugin.timeshift = SafeParse.stringToInt(timeshiftView.getText().toString()); + updateProfileInfo(); + } + if (diaView.testValidity()) { + circadianPercentageProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString()); + updateProfileInfo(); + } + if (targethighView.testValidity()) { + circadianPercentageProfilePlugin.targetLow = SafeParse.stringToDouble(targetlowView.getText().toString()); + updateProfileInfo(); + } + if (targetlowView.testValidity()) { + circadianPercentageProfilePlugin.targetHigh = SafeParse.stringToDouble(targethighView.getText().toString()); + updateProfileInfo(); + } + circadianPercentageProfilePlugin.storeSettings(); + updateProfileInfo(); + } + }; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -105,16 +153,6 @@ public class CircadianPercentageProfileFragment extends Fragment { layout.findViewById(R.id.circadianpercentageprofile_baseprofilebasal_layout).setVisibility(View.GONE); } - - mgdlView.setChecked(circadianPercentageProfilePlugin.mgdl); - mmolView.setChecked(circadianPercentageProfilePlugin.mmol); - diaView.setText(circadianPercentageProfilePlugin.dia.toString()); - targetlowView.setText(circadianPercentageProfilePlugin.targetLow.toString()); - targethighView.setText(circadianPercentageProfilePlugin.targetHigh.toString()); - percentageView.setText("" + circadianPercentageProfilePlugin.percentage); - timeshiftView.setText("" + circadianPercentageProfilePlugin.timeshift); - updateProfileInfo(); - mgdlView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -140,9 +178,9 @@ public class CircadianPercentageProfileFragment extends Fragment { @Override public void onClick(View view) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - 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 profileswitch = CareportalFragment.profileswitch; profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch); + newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); } }); @@ -265,49 +303,6 @@ public class CircadianPercentageProfileFragment extends Fragment { } }); - TextWatcher textWatch = new TextWatcher() { - - @Override - public void afterTextChanged(Editable s) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, - int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, - int before, int count) { - - if (percentageView.testValidity()) { - if (SafeParse.stringToInt(percentageView.getText().toString()) == 0) { - circadianPercentageProfilePlugin.percentage = 100; - } else { - circadianPercentageProfilePlugin.percentage = SafeParse.stringToInt(percentageView.getText().toString()); - } - updateProfileInfo(); - } - if (timeshiftView.testValidity()) { - circadianPercentageProfilePlugin.timeshift = SafeParse.stringToInt(timeshiftView.getText().toString()); - updateProfileInfo(); - } - if (diaView.testValidity()) { - circadianPercentageProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString()); - updateProfileInfo(); - } - if (targethighView.testValidity()) { - circadianPercentageProfilePlugin.targetLow = SafeParse.stringToDouble(targetlowView.getText().toString()); - updateProfileInfo(); - } - if (targetlowView.testValidity()) { - circadianPercentageProfilePlugin.targetHigh = SafeParse.stringToDouble(targethighView.getText().toString()); - updateProfileInfo(); - } - circadianPercentageProfilePlugin.storeSettings(); - updateProfileInfo(); - } - }; diaView.addTextChangedListener(textWatch); targetlowView.addTextChangedListener(textWatch); @@ -315,11 +310,39 @@ public class CircadianPercentageProfileFragment extends Fragment { percentageView.addTextChangedListener(textWatch); timeshiftView.addTextChangedListener(textWatch); - onStatusEvent(null); + updateGUI(); + + onStatusEvent(new EventInitializationChanged()); return layout; } + public void updateGUI() { + updateProfileInfo(); + + diaView.removeTextChangedListener(textWatch); + targetlowView.removeTextChangedListener(textWatch); + targethighView.removeTextChangedListener(textWatch); + percentageView.removeTextChangedListener(textWatch); + timeshiftView.removeTextChangedListener(textWatch); + + mgdlView.setChecked(circadianPercentageProfilePlugin.mgdl); + mmolView.setChecked(circadianPercentageProfilePlugin.mmol); + diaView.setText(circadianPercentageProfilePlugin.dia.toString()); + targetlowView.setText(circadianPercentageProfilePlugin.targetLow.toString()); + targethighView.setText(circadianPercentageProfilePlugin.targetHigh.toString()); + percentageView.setText("" + circadianPercentageProfilePlugin.percentage); + timeshiftView.setText("" + circadianPercentageProfilePlugin.timeshift); + + + diaView.addTextChangedListener(textWatch); + targetlowView.addTextChangedListener(textWatch); + targethighView.addTextChangedListener(textWatch); + percentageView.addTextChangedListener(textWatch); + timeshiftView.addTextChangedListener(textWatch); + + } + private void customSnackbar(View view, final String Msg, Object snackbarCaller) { if(mSnackBar!= null) mSnackBar.dismiss(); @@ -410,7 +433,6 @@ public class CircadianPercentageProfileFragment extends Fragment { if (i == 0) { copyprevbutton.setVisibility(View.INVISIBLE); - ; } else { final int j = i; //needs to be final to be passed to inner class. copyprevbutton.setOnClickListener(new View.OnClickListener() { @@ -461,15 +483,13 @@ public class CircadianPercentageProfileFragment extends Fragment { } basalEditDialog = null; - MainApp.bus().unregister(this); fl.requestFocusFromTouch(); } @Override public void onResume() { super.onResume(); - MainApp.bus().register(this); - onStatusEvent(null); + onStatusEvent(new EventInitializationChanged()); fl.requestFocusFromTouch(); } @@ -480,12 +500,29 @@ public class CircadianPercentageProfileFragment extends Fragment { activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) { + if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { profileswitchButton.setVisibility(View.GONE); + } else if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) { + profileswitchButton.setText(MainApp.instance().getText(R.string.activate_profile)); + profileswitchButton.setVisibility(View.VISIBLE); } else { + profileswitchButton.setText(MainApp.instance().getText(R.string.send_to_pump)); profileswitchButton.setVisibility(View.VISIBLE); } } }); } + + @Subscribe + public void onStatusEvent(final EventProfileSwitchChange e) { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + updateGUI(); + } + }); + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java index 5a8813bdf8..768cdf90e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java @@ -9,14 +9,20 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.text.DecimalFormat; + import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; 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; @@ -32,7 +38,8 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte 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; @@ -155,6 +162,55 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte createConvertedProfile(); } + public String externallySetParameters(int timeshift, int percentage) { + + String msg = ""; + + if (!fragmentEnabled){ + msg+= "NO CPP!" + "\n"; + } + + //check for validity + if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { + msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Percentage") + "\n"; + } + if (timeshift < 0 || timeshift > 23) { + msg+= String.format(MainApp.sResources.getString(R.string.openapsma_valueoutofrange), "Profile-Timeshift") + "\n"; + } + if(!SP.getBoolean("syncprofiletopump", false)){ + msg+= MainApp.sResources.getString(R.string.syncprofiletopump_title) + " " + MainApp.sResources.getString(R.string.cpp_sync_setting_missing) + "\n"; + } + final PumpInterface pump = MainApp.getConfigBuilder(); + final Profile profile = MainApp.getConfigBuilder().getProfile(); + + if (pump == null || profile == null || profile.getBasal() == null){ + msg+= MainApp.sResources.getString(R.string.cpp_notloadedplugins) + "\n"; + } + if(!"".equals(msg)) { + msg += MainApp.sResources.getString(R.string.cpp_valuesnotstored); + return msg; + } + + //store profile + this.timeshift= timeshift; + this.percentage = percentage; + storeSettings(); + + + //send profile to pumpe + new NewNSTreatmentDialog(); //init + NewNSTreatmentDialog.doProfileSwitch(this.getProfile(), this.getProfileName(), 0); + + //return formatted string + /*msg += "%: " + this.percentage + " h: +" + this.timeshift; + msg += "\n"; + msg += "\nBasal:\n" + basalString() + "\n"; + msg += "\nISF:\n" + isfString() + "\n"; + msg += "\nIC:\n" + isfString() + "\n";*/ + + return msg; + } + private void createConvertedProfile() { JSONObject json = new JSONObject(); JSONObject store = new JSONObject(); @@ -177,47 +233,54 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte int offset = -(timeshift % 24) + 24; JSONArray icArray = new JSONArray(); - for (int i = 0; i < 24; i++) { - icArray.put(new JSONObject().put("timeAsSeconds", i * 60 * 60).put("value", baseic[(offset + i) % 24] * 100d / percentage)); - } - profile.put("carbratio", icArray); - JSONArray isfArray = new JSONArray(); - for (int i = 0; i < 24; i++) { - isfArray.put(new JSONObject().put("timeAsSeconds", i * 60 * 60).put("value", baseisf[(offset + i) % 24] * 100d / percentage)); - } - profile.put("sens", isfArray); - JSONArray basalArray = new JSONArray(); for (int i = 0; i < 24; i++) { - basalArray.put(new JSONObject().put("timeAsSeconds", i * 60 * 60).put("value", basebasal[(offset + i) % 24] * percentage / 100d)); + String time; + DecimalFormat df = new DecimalFormat("00"); + time = df.format(i) + ":00"; + icArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", baseic[(offset + i) % 24] * 100d / percentage)); + isfArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", baseisf[(offset + i) % 24] * 100d / percentage)); + basalArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", basebasal[(offset + i) % 24] * percentage / 100d)); } + profile.put("carbratio", icArray); + profile.put("sens", isfArray); profile.put("basal", basalArray); - profile.put("target_low", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetLow))); - profile.put("target_high", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetHigh))); + profile.put("target_low", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", targetLow))); + profile.put("target_high", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", targetHigh))); profile.put("units", mgdl ? Constants.MGDL : Constants.MMOL); store.put(profileName, profile); } 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 getUnits() { + return mgdl ? Constants.MGDL : Constants.MMOL; + } + + @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); @@ -293,4 +356,11 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte return sb.toString(); } + public int getPercentage() { + return percentage; + } + + public int getTimeshift() { + return timeshift; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java index 86a983ae17..e491a41b1b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfileFragment.java @@ -24,12 +24,14 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.utils.SafeParse; import info.nightscout.utils.TimeListEdit; -public class LocalProfileFragment extends Fragment { +public class LocalProfileFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(LocalProfileFragment.class); private static LocalProfilePlugin localProfilePlugin = new LocalProfilePlugin(); @@ -72,7 +74,7 @@ public class LocalProfileFragment extends Fragment { layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE); } - onStatusEvent(null); + updateGUI(); mgdlView.setChecked(localProfilePlugin.mgdl); mmolView.setChecked(localProfilePlugin.mmol); @@ -101,9 +103,9 @@ public class LocalProfileFragment extends Fragment { @Override public void onClick(View view) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - 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 profileswitch = CareportalFragment.profileswitch; profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch); + newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); } }); @@ -129,34 +131,30 @@ public class LocalProfileFragment extends Fragment { diaView.addTextChangedListener(textWatch); - onStatusEvent(null); + updateGUI(); return layout; } - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - onStatusEvent(null); - } - @Subscribe public void onStatusEvent(final EventInitializationChanged e) { + updateGUI(); + } + + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) { + if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { profileswitchButton.setVisibility(View.GONE); + } else if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) { + profileswitchButton.setText(MainApp.instance().getText(R.string.activate_profile)); + profileswitchButton.setVisibility(View.VISIBLE); } else { + profileswitchButton.setText(MainApp.instance().getText(R.string.send_to_pump)); profileswitchButton.setVisibility(View.VISIBLE); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java index 6e822e5d43..8aca0a8dbc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileLocal/LocalProfilePlugin.java @@ -15,7 +15,7 @@ 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; /** @@ -27,9 +27,10 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface { 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}]"; + final private String DEFAULTARRAY = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]"; boolean mgdl; boolean mmol; @@ -230,12 +231,23 @@ 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 getUnits() { + return mgdl ? Constants.MGDL : Constants.MMOL; + } + + @Override + public String getProfileName() { + return convertedProfileName; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java index 028ef1ac45..007c3dfbdf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfileFragment.java @@ -12,24 +12,26 @@ import com.squareup.otto.Subscribe; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; import info.nightscout.utils.DecimalFormatter; -public class NSProfileFragment extends Fragment { +public class NSProfileFragment extends SubscriberFragment { private static NSProfilePlugin nsProfilePlugin = new NSProfilePlugin(); public static NSProfilePlugin getPlugin() { return nsProfilePlugin; } - private static TextView noProfile; - private static TextView units; - private static TextView dia; - private static TextView activeProfile; - private static TextView ic; - private static TextView isf; - private static TextView basal; - private static TextView target; + private TextView noProfile; + private TextView units; + private TextView dia; + private TextView activeProfile; + private TextView ic; + private TextView isf; + private TextView basal; + private TextView target; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -49,18 +51,6 @@ public class NSProfileFragment extends Fragment { return layout; } - @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 EventNSProfileUpdateGUI ev) { Activity activity = getActivity(); @@ -73,20 +63,23 @@ public class NSProfileFragment extends Fragment { }); } - private void updateGUI() { - if (nsProfilePlugin.profile == null) { + @Override + protected void updateGUI() { + 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/ProfileNS/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java index 5f29881b2a..758521d5a8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java @@ -1,8 +1,6 @@ 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; @@ -13,14 +11,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.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.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI; +import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorPlugin; import info.nightscout.utils.SP; /** @@ -37,7 +37,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 +53,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 +63,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 @@ -83,7 +83,7 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { @Override public boolean showInList(int type) { - return true; + return !Config.NSCLIENT; } @Override @@ -102,18 +102,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 = 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"); } @@ -121,14 +127,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; @@ -146,7 +150,17 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { @Nullable @Override - public NSProfile getProfile() { + public ProfileStore getProfile() { return profile; } + + @Override + public String getUnits() { + return profile != null ? profile.getUnits() : Constants.MGDL; + } + + @Override + public String getProfileName() { + return profile.getDefaultProfileName(); + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java index b183b28a0b..5cf36409b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfileFragment.java @@ -22,11 +22,13 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.Careportal.CareportalFragment; import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.utils.SafeParse; -public class SimpleProfileFragment extends Fragment { +public class SimpleProfileFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(SimpleProfileFragment.class); private static SimpleProfilePlugin simpleProfilePlugin = new SimpleProfilePlugin(); @@ -65,7 +67,7 @@ public class SimpleProfileFragment extends Fragment { layout.findViewById(R.id.simpleprofile_basalrate_label).setVisibility(View.GONE); } - onStatusEvent(null); + updateGUI(); mgdlView.setChecked(simpleProfilePlugin.mgdl); mmolView.setChecked(simpleProfilePlugin.mmol); @@ -99,9 +101,9 @@ public class SimpleProfileFragment extends Fragment { @Override public void onClick(View view) { NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog(); - 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 profileswitch = CareportalFragment.profileswitch; profileswitch.executeProfileSwitch = true; - newDialog.setOptions(profileswitch); + newDialog.setOptions(profileswitch, R.string.careportal_profileswitch); newDialog.show(getFragmentManager(), "NewNSTreatmentDialog"); } }); @@ -137,34 +139,30 @@ public class SimpleProfileFragment extends Fragment { targetlowView.addTextChangedListener(textWatch); targethighView.addTextChangedListener(textWatch); - onStatusEvent(null); + updateGUI(); return layout; } - @Override - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); - onStatusEvent(null); - } - @Subscribe public void onStatusEvent(final EventInitializationChanged e) { + updateGUI(); + } + + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { @Override public void run() { - if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) { + if (!MainApp.getConfigBuilder().isInitialized() || MainApp.getConfigBuilder().isSuspended()) { profileswitchButton.setVisibility(View.GONE); + } else if (!MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) { + profileswitchButton.setText(MainApp.instance().getText(R.string.activate_profile)); + profileswitchButton.setVisibility(View.VISIBLE); } else { + profileswitchButton.setText(MainApp.instance().getText(R.string.send_to_pump)); profileswitchButton.setVisibility(View.VISIBLE); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java index aac4a05798..e02f4918c2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileSimple/SimpleProfilePlugin.java @@ -15,7 +15,7 @@ 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; /** @@ -27,7 +27,7 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { private static boolean fragmentEnabled = false; private static boolean fragmentVisible = true; - private static NSProfile convertedProfile = null; + private static ProfileStore convertedProfile = null; boolean mgdl; boolean mmol; @@ -183,22 +183,32 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface { json.put("defaultProfile", "SimpleProfile"); json.put("store", store); profile.put("dia", dia); - profile.put("carbratio", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", ic))); - profile.put("sens", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", isf))); - profile.put("basal", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", basal))); - profile.put("target_low", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetLow))); - profile.put("target_high", new JSONArray().put(new JSONObject().put("timeAsSeconds", 0).put("value", targetHigh))); + profile.put("carbratio", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", ic))); + profile.put("sens", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", isf))); + profile.put("basal", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", basal))); + profile.put("target_low", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", targetLow))); + profile.put("target_high", new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", targetHigh))); profile.put("units", mgdl ? Constants.MGDL : Constants.MMOL); store.put("SimpleProfile", profile); } 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 getUnits() { + return mgdl ? Constants.MGDL : Constants.MMOL; + } + + @Override + public String getProfileName() { + return "SimpleProfile"; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java index c7ae887731..87c635cbef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java @@ -24,17 +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.plugins.Common.SubscriberFragment; 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.activities.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.activities.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 { +public class DanaRFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(DanaRFragment.class); private static DanaRPlugin danaRPlugin; @@ -155,18 +157,6 @@ public class DanaRFragment extends Fragment { 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(); @@ -197,39 +187,45 @@ public class DanaRFragment extends Fragment { updateGUI(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange s) { + updateGUI(); + } + // GUI functions - private void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null && basaBasalRateView != null) activity.runOnUiThread(new Runnable() { @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(); + Long agoMsec = System.currentTimeMillis() - 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(); + Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime(); double agoHours = agoMsec / 60d / 60d / 1000d; if (agoHours < 6) // max 6h back - lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(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(System.currentTimeMillis()).toStringFull()); } else { tempBasalView.setText(""); } - if (getPlugin().isExtendedBoluslInProgress()) { - extendedBolusView.setText(getPlugin().getExtendedBolus().toString()); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString()); } else { extendedBolusView.setText(""); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index dd3fb86837..bc5b23ad92 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -4,9 +4,7 @@ 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,32 +22,36 @@ 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; import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.DanaRInterface; 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.plugins.PumpDanaR.Services.ExecutionService; -import info.nightscout.androidaps.plugins.ProfileNS.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. */ -public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface { +public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { private static Logger log = LoggerFactory.getLogger(DanaRPlugin.class); @Override @@ -61,46 +63,39 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf 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.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; @@ -109,7 +104,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf pumpDescription.isRefillingCapable = true; } - ServiceConnection mConnection = new ServiceConnection() { + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { log.debug("Service is disconnected"); @@ -118,7 +113,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(); } }; @@ -133,12 +128,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(); } } @@ -158,7 +150,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; } @@ -217,14 +209,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 @@ -235,23 +232,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; @@ -276,17 +257,16 @@ 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; 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); + Double profileValue = profile.getBasal((Integer) (h * basalIncrement)); if (profileValue == null) return true; if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) { log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue); @@ -298,7 +278,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Date lastDataTime() { - return getDanaRPump().lastConnection; + return pump.lastConnection; } @Override @@ -310,84 +290,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(InsulinInterface insulinType, 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(insulinType); + detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { + Treatment t = new Treatment(); 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 = System.currentTimeMillis(); + 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; @@ -405,9 +334,9 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf // This is called from APS @Override - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { // 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 < System.currentTimeMillis()) { doConnect("setTempBasalAbsolute old data"); } @@ -423,13 +352,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(); @@ -448,11 +377,14 @@ 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 (Config.logPumpActions) + log.debug("setTempBasalAbsolute: Calculated percent rate: " + percentRate); + // 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(); @@ -462,26 +394,24 @@ 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) { - result.success = true; - result.percent = percentRate; - result.absolute = getTempBasalAbsoluteRate(); - result.enacted = false; - result.duration = ((Double) getTempBasalRemainingMinutes()).intValue(); - result.isPercent = true; - result.isTempCancel = false; - if (Config.logPumpActions) - log.debug("setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); - return result; - } else { - if (Config.logPumpActions) - log.debug("setTempBasalAbsolute: Stopping temp basal (doLowTemp || doHighTemp)"); - result = cancelRealTempBasal(); - // Check for proper result - if (!result.success) { - log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doLowTemp || doHighTemp)"); + TemporaryBasal running = MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()); + if (Config.logPumpActions) + log.debug("setTempBasalAbsolute: currently running: " + running.toString()); + if (running.percentRate == percentRate) { + if (force) { + cancelTempBasal(true); + } else { + 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; } } @@ -493,7 +423,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(); @@ -510,21 +440,21 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf Double extendedRateToSet = absoluteRate - getBaseBasalRate(); extendedRateToSet = configBuilderPlugin.applyBasalConstraints(extendedRateToSet); // needs to be rounded to 0.1 - extendedRateToSet = Round.roundTo(extendedRateToSet, 0.1d); + extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of halfhours // 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) @@ -566,14 +496,16 @@ 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.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: Correct value already set"); @@ -581,13 +513,14 @@ 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.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: OK"); @@ -605,31 +538,31 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); insulin = configBuilderPlugin.applyBolusConstraints(insulin); // needs to be rounded - insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); + int durationInHalfHours = Math.max(durationInMinutes / 30, 1); + insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep * (1 + durationInHalfHours % 1)); 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"); @@ -643,11 +576,13 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf } @Override - public PumpEnactResult cancelTempBasal() { - if (isRealTempBasalInProgress()) + public PumpEnactResult cancelTempBasal(boolean force) { + 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; @@ -658,12 +593,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); @@ -682,12 +617,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) @@ -719,48 +654,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 < System.currentTimeMillis()) { 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(System.currentTimeMillis()); if (tb != null) { - extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate()); - extended.put("TempBasalStart", tb.timeStart.toLocaleString()); + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - extended.put("IsExtended", tb.isExtended); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + 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 @@ -768,6 +710,15 @@ public class DanaRPlugin implements PluginBase, PumpInterface, ConstraintsInterf return pumpDescription; } + /** + * DanaR interface + */ + + @Override + public boolean loadHistory(byte type) { + return sExecutionService.loadHistory(type); + } + /** * Constraint interface */ @@ -796,9 +747,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"); } @@ -811,7 +762,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; @@ -821,9 +773,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"); } @@ -843,36 +795,45 @@ 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 getUnits() { + return pump.getUnits(); + } + + @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 = System.currentTimeMillis() - 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(System.currentTimeMillis()).toStringFull() + "\n"; } - if (isExtendedBoluslInProgress()) { - ret += "Extended: " + getExtendedBolus().toString() + "\n"; + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).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/PumpDanaR/DanaRPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java index 0714e2eeee..55fdc7ad04 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPump.java @@ -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,11 @@ public class DanaRPump { public double maxBolus; public double maxBasal; - public NSProfile createConvertedProfile() { + public String getUnits() { + return units == UNITS_MGDL ? Constants.MGDL : Constants.MMOL; + } + + public ProfileStore createConvertedProfile() { JSONObject json = new JSONObject(); JSONObject store = new JSONObject(); JSONObject profile = new JSONObject(); @@ -166,7 +193,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/PumpDanaR/Dialogs/ProfileViewDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java index 8907a230d2..a20934fdb7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java @@ -17,8 +17,14 @@ import java.util.Date; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +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; /** @@ -27,28 +33,25 @@ import info.nightscout.utils.DecimalFormatter; public class ProfileViewDialog extends DialogFragment { private static Logger log = LoggerFactory.getLogger(ProfileViewDialog.class); - private static TextView noProfile; - private static TextView units; - private static TextView dia; - private static TextView activeProfile; - private static TextView ic; - private static TextView isf; - private static TextView basal; - private static TextView target; + private TextView noProfile; + private TextView units; + private TextView dia; + private TextView activeProfile; + private TextView ic; + private TextView isf; + private TextView basal; + private TextView target; - private static Button refreshButton; + private Button refreshButton; 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 +75,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,19 +99,26 @@ public class ProfileViewDialog extends DialogFragment { } private void setContent() { - if (profile == null) { - noProfile.setVisibility(View.VISIBLE); - return; - } else { +// if (profile == null) { +// noProfile.setVisibility(View.VISIBLE); +// return; +// } else { +// noProfile.setVisibility(View.GONE); +// } + ProfileStore store = ((ProfileInterface)MainApp.getConfigBuilder().getActivePump()).getProfile(); + if (store != null) { noProfile.setVisibility(View.GONE); + Profile profile = store.getDefaultProfile(); + units.setText(profile.getUnits()); + dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); + activeProfile.setText(((ProfileInterface) MainApp.getConfigBuilder().getActivePump()).getProfileName()); + ic.setText(profile.getIcList()); + isf.setText(profile.getIsfList()); + basal.setText(profile.getBasalList()); + target.setText(profile.getTargetList()); + } else { + noProfile.setVisibility(View.VISIBLE); } - units.setText(profile.getUnits()); - dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); - activeProfile.setText(profile.getActiveProfile()); - 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/PumpDanaR/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java deleted file mode 100644 index f4ad770ac1..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRHistoryActivity.java +++ /dev/null @@ -1,448 +0,0 @@ -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.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.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; - -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.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.Services.ExecutionService; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -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 ExecutionService mExecutionService; - - private Handler mHandler; - private static HandlerThread mHandlerThread; - - static NSProfile 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, ExecutionService.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; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.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_ERROR, getString(R.string.danar_history_errors))); - typeList.add(new TypeList(RecordTypes.RECORD_TYPE_GLUCOSE, getString(R.string.danar_history_glucose))); - 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, - 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 = ConfigBuilderPlugin.getActiveProfile().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.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()); - 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.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.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(NSProfile.toUnitsString(record.getRecordValue(), record.getRecordValue() * 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) { - 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<>(); - } - 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 s) { - runOnUiThread( - new Runnable() { - @Override - public void run() { - statusView.setText(s.textStatus()); - } - } - ); - } - - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java index feb5a59b69..461b353c3e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/SerialIOThread.java @@ -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/PumpDanaRKorean/History/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java similarity index 82% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java index 8b2811e382..5fc022bcc6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRHistoryActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.History; +package info.nightscout.androidaps.plugins.PumpDanaR.activities; 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,14 @@ 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.PumpDanaR.History.DanaRNSHistorySync; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.DanaRInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.ToastUtils; @@ -53,12 +50,11 @@ public class DanaRHistoryActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRHistoryActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; - static NSProfile profile = null; + static Profile profile = null; Spinner historyTypeSpinner; TextView statusView; @@ -93,13 +89,6 @@ public class DanaRHistoryActivity extends Activity { } - @Override - public void onStart() { - super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); - bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } - @Override protected void onResume() { super.onResume(); @@ -112,31 +101,6 @@ public class DanaRHistoryActivity extends Activity { 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; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; - mExecutionService = mLocalBinder.getServiceInstance(); - } - }; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -157,6 +121,8 @@ public class DanaRHistoryActivity extends Activity { statusView.setVisibility(View.GONE); + boolean isKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP); + // Types ArrayList typeList = new ArrayList<>(); @@ -166,7 +132,11 @@ public class DanaRHistoryActivity extends Activity { 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))); - + if (!isKorean) { + typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ERROR, getString(R.string.danar_history_errors))); + 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, R.layout.spinner_centered, typeList); historyTypeSpinner.setAdapter(spinnerAdapter); @@ -174,7 +144,8 @@ public class DanaRHistoryActivity extends Activity { reloadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (mExecutionService.isConnected() || mExecutionService.isConnecting()) { + final PumpInterface pump = MainApp.getConfigBuilder().getActivePump(); + if (pump.isBusy()) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); return; } @@ -191,7 +162,7 @@ public class DanaRHistoryActivity extends Activity { } }); clearCardView(); - mExecutionService.loadHistory(selected.type); + ((DanaRInterface)pump).loadHistory(selected.type); loadDataFromDB(selected.type); runOnUiThread(new Runnable() { @Override @@ -248,7 +219,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(); @@ -272,12 +243,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); @@ -302,10 +273,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); @@ -317,7 +288,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: @@ -388,19 +359,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() { @@ -432,12 +392,12 @@ public class DanaRHistoryActivity extends Activity { } @Subscribe - public void onStatusEvent(final EventPumpStatusChanged c) { + public void onStatusEvent(final EventPumpStatusChanged s) { runOnUiThread( new Runnable() { @Override public void run() { - statusView.setText(c.textStatus()); + statusView.setText(s.textStatus()); } } ); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRNSHistorySync.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRNSHistorySync.java similarity index 60% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRNSHistorySync.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRNSHistorySync.java index 4c1e2e1f05..0668a74c1d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRNSHistorySync.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRNSHistorySync.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.History; +package info.nightscout.androidaps.plugins.PumpDanaR.activities; 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.data.Profile; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.ToastUtils; /** @@ -44,12 +46,6 @@ public class DanaRNSHistorySync { public void sync(int what) { try { - ConfigBuilderPlugin ConfigBuilderPlugin = MainApp.getConfigBuilder(); - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - if (profile == null) { - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.noprofile)); - return; - } Calendar cal = Calendar.getInstance(); long records = historyRecords.size(); long processing = 0; @@ -58,72 +54,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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("insulin", record.recordValue); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + NSUpload.uploadCareportalEntryToNS(nsrec); uploaded++; ev.message += MainApp.sResources.getString(R.string.danar_debolus); break; @@ -134,78 +130,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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("notes", "Refill " + record.recordValue + "U"); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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, MainApp.getConfigBuilder().getProfileUnits())); nsrec.put("glucoseType", "Finger"); - nsrec.put("created_at", DateUtil.toISOString(record.getRecordDate())); - nsrec.put("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("carbs", record.recordValue); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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("enteredBy", MainApp.sResources.getString(R.string.app_name)); - ConfigBuilderPlugin.uploadCareportalEntryToNS(nsrec); + nsrec.put("notes", "Alarm: " + record.recordAlarm); + nsrec.put("created_at", DateUtil.toISOString(record.recordDate)); + nsrec.put("enteredBy", "openaps://" + MainApp.sResources.getString(R.string.app_name)); + 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/activities/DanaRStatsActivity.java similarity index 86% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java index 883330dd5b..fbe828a25f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/History/DanaRStatsActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java @@ -1,18 +1,16 @@ -package info.nightscout.androidaps.plugins.PumpDanaR.History; +package info.nightscout.androidaps.plugins.PumpDanaR.activities; 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,35 +25,35 @@ 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; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.Date; +import java.util.LinkedList; 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.DanaRInterface; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.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.PumpDanaR.services.DanaRExecutionService; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.ToastUtils; @@ -63,7 +61,6 @@ public class DanaRStatsActivity extends Activity { private static Logger log = LoggerFactory.getLogger(DanaRStatsActivity.class); private boolean mBounded; - private static ExecutionService mExecutionService; private Handler mHandler; private static HandlerThread mHandlerThread; @@ -78,6 +75,7 @@ public class DanaRStatsActivity extends Activity { DecimalFormat decimalFormat; List historyList = new ArrayList<>(); + List dummies; public DanaRStatsActivity() { super(); @@ -86,13 +84,6 @@ public class DanaRStatsActivity extends Activity { this.mHandler = new Handler(mHandlerThread.getLooper()); } - @Override - public void onStart() { - super.onStart(); - Intent intent = new Intent(this, ExecutionService.class); - bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } - @Override protected void onResume() { super.onResume(); @@ -105,15 +96,6 @@ public class DanaRStatsActivity extends Activity { 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) { @@ -129,22 +111,6 @@ public class DanaRStatsActivity extends Activity { 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; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.LocalBinder) service; - mExecutionService = mLocalBinder.getServiceInstance(); - } - }; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -167,18 +133,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 @@ -278,7 +241,8 @@ public class DanaRStatsActivity extends Activity { reloadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (mExecutionService.isConnected() || mExecutionService.isConnecting()) { + final PumpInterface pump = MainApp.getConfigBuilder().getActivePump(); + if (pump.isBusy()) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy)); return; } @@ -294,7 +258,7 @@ public class DanaRStatsActivity extends Activity { statsMessage.setText(getString(R.string.danar_stats_warning_Message)); } }); - mExecutionService.loadHistory(RecordTypes.RECORD_TYPE_DAILY); + ((DanaRInterface)pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY); loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY); runOnUiThread(new Runnable() { @Override @@ -326,10 +290,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 +303,36 @@ 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); + + //only use newest 10 + historyList = historyList.subList(0, Math.min(10, historyList.size())); + + //fill single gaps + dummies = new LinkedList(); + DateFormat df = new SimpleDateFormat("dd.MM."); + for(int i = 0; i < historyList.size()-1; i++){ + DanaRHistoryRecord elem1 = historyList.get(i); + DanaRHistoryRecord elem2 = historyList.get(i+1); + + if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25*60*60*1000)))){ + DanaRHistoryRecord dummy = new DanaRHistoryRecord(); + dummy.recordDate = elem1.recordDate - 24*60*60*1000; + dummy.recordDailyBasal = elem1.recordDailyBasal/2; + dummy.recordDailyBolus = elem1.recordDailyBolus/2; + dummies.add(dummy); + elem1.recordDailyBasal /= 2; + elem1.recordDailyBolus /= 2; + } } + historyList.addAll(dummies); + Collections.sort(historyList, new Comparator() { + @Override + public int compare(DanaRHistoryRecord lhs, DanaRHistoryRecord rhs) { + return (int) (rhs.recordDate-lhs.recordDate); + } + }); + runOnUiThread(new Runnable() { @Override public void run() { @@ -379,11 +358,14 @@ 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); if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY); + if(dummies.contains(record)){ + tr.setBackgroundColor(Color.argb(125, 255, 0, 0)); + } tr.setId(100 + i); tr.setLayoutParams(new TableLayout.LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, @@ -392,19 +374,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 +443,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 +456,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/PumpDanaR/comm/MessageBase.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java index 4045f28f6e..943d4ee502 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageBase.java @@ -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/PumpDanaR/comm/MessageOriginalNames.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java index 1ab166801d..3712945094 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageOriginalNames.java @@ -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/PumpDanaR/comm/MsgBolusProgress.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java index 2130561aeb..b200ccc5c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusProgress.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; +import com.squareup.otto.Bus; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,13 +30,13 @@ public class MsgBolusProgress extends MessageBase { this(); this.amount = amount; this.t = t; - lastReceive = new Date().getTime(); + lastReceive = System.currentTimeMillis(); } @Override public void handleMessage(byte[] bytes) { progress = intFromBuff(bytes, 0, 2); - lastReceive = new Date().getTime(); + lastReceive = System.currentTimeMillis(); Double done = (amount * 100 - progress) / 100d; t.insulin = done; EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java index a5591746b0..0e6a3e814a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStart.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.utils.HardLimits; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java index 0d2c51bf7c..7040b84183 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStop.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; +import com.squareup.otto.Bus; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java index f63d49849b..c05029caff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java @@ -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/PumpDanaR/comm/MsgError.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java index ec52d533dc..b180d4107b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgError.java @@ -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/PumpDanaR/comm/MsgHistoryAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java index 4ba8bfe143..4e4bc759f5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgHistoryAll.java @@ -1,11 +1,8 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; -import com.j256.ormlite.dao.Dao; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.SQLException; import java.util.Date; import info.nightscout.androidaps.MainApp; @@ -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/PumpDanaR/comm/MsgInitConnStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java index 2a22fd86d9..e7f6032c00 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBasic.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgInitConnStatusBasic extends MessageBase { @@ -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/PumpDanaR/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java index 1b7a8dbe5c..b39929db5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusBolus.java @@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.Overview.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; @@ -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/PumpDanaR/comm/MsgInitConnStatusOption.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java index 2009bddd40..560ed8b332 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusOption.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.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/PumpDanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java index 00b8379179..dfd5788ec9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java @@ -8,9 +8,10 @@ import java.util.Date; 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.events.EventRefreshOverview; 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.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.utils.ToastUtils; @@ -27,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)){ @@ -39,7 +41,7 @@ public class MsgInitConnStatusTime extends MessageBase { } MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshGui(false)); + MainApp.bus().post(new EventRefreshOverview("MsgInitConnStatusTime")); return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java index 6a16fd1a57..4fcd6dee9c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetCarbsEntry.java @@ -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/PumpDanaR/comm/MsgSetExtendedBolusStart.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java index 9ef6b0136e..484078825e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetExtendedBolusStart.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.utils.HardLimits; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java index b56de8fd7a..32cd3745d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetSingleBasalProfile.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpDanaR.comm; +import com.j256.ormlite.stmt.query.Not; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java index aa15a02709..3910d52c97 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSetTime.java @@ -13,9 +13,11 @@ import info.nightscout.androidaps.Config; public class MsgSetTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgSetTime.class); + private static Date time; public MsgSetTime(Date time) { SetCommand(0x330a); + this.time = time; AddParamDateTime(time); } @@ -23,6 +25,6 @@ public class MsgSetTime extends MessageBase { int result = intFromBuff(bytes, 0, 1); if (Config.logDanaMessageDetail) - log.debug("Result: " + result); + log.debug("Result of setting time: " + time + " is " + result); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java index b737073a43..20498e28e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingActiveProfile.java @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.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/PumpDanaR/comm/MsgSettingBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java index 82d003b434..e1a7e45315 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasal.java @@ -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/PumpDanaR/comm/MsgSettingBasalProfileAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java index 6fab757486..24b5043769 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingBasalProfileAll.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; 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 index 6c7b302abf..0f20c0843a 100644 --- 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 @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,12 +17,13 @@ public class MsgSettingGlucose extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPlugin.getDanaRPump().units = intFromBuff(bytes, 0, 1); - DanaRPlugin.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1); + DanaRPump pump = DanaRPump.getInstance(); + pump.units = intFromBuff(bytes, 0, 1); + pump.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); + 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 index 0f2de2fe0b..9279f2b1ba 100644 --- 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 @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,14 +18,15 @@ public class MsgSettingMaxValues extends MessageBase { } 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; + 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: " + DanaRPlugin.getDanaRPump().maxBolus); - log.debug("Max basal: " + DanaRPlugin.getDanaRPump().maxBasal); - log.debug("Total daily max units: " + DanaRPlugin.getDanaRPump().maxDailyTotalUnits); + 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/PumpDanaR/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java index 1c8e3c2fcb..4ed5de2920 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingMeal.java @@ -4,7 +4,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -19,7 +23,7 @@ public class MsgSettingMeal extends MessageBase { } public void handleMessage(byte[] bytes) { - DanaRPump pump = DanaRPlugin.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; @@ -35,6 +39,13 @@ public class MsgSettingMeal extends MessageBase { log.debug("Block time: " + blockTime); log.debug("Is Config U/d: " + pump.isConfigUD); } + + if (pump.isConfigUD) { + Notification notification = new Notification(Notification.UD_MODE_ENABLED, MainApp.sResources.getString(R.string.danar_switchtouhmode), Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + } else { + MainApp.bus().post(new EventDismissNotification(Notification.UD_MODE_ENABLED)); + } } } 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 index 512c96990e..0b5150fc84 100644 --- 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 @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,27 +17,28 @@ public class MsgSettingProfileRatios extends MessageBase { } 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); + 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 { - 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); + 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): " + (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); + 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 index aaadb2bd59..9dd5a0070d 100644 --- 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 @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,38 +17,39 @@ public class MsgSettingProfileRatiosAll extends MessageBase { } 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); + 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 { - 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; + 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: " + (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); + 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); } - DanaRPlugin.getDanaRPump().createConvertedProfile(); + pump.createConvertedProfile(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java index 5344ae86b6..3da1451899 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingPumpTime.java @@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgSettingPumpTime extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class); @@ -27,8 +27,8 @@ public class MsgSettingPumpTime extends MessageBase { ); if (Config.logDanaMessageDetail) - log.debug("Pump time: " + time); + log.debug("Pump time: " + time + " Phone time: " + new Date()); - DanaRPlugin.getDanaRPump().pumpTime = time; + DanaRPump.getInstance().pumpTime = time; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java index 797a82f80a..9670d92a88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgSettingShippingInfo.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,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/PumpDanaR/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatus.java index 9e64f86363..fb75bfef0e 100644 --- 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 @@ -4,7 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; public class MsgStatus extends MessageBase { private static Logger log = LoggerFactory.getLogger(MsgStatus.class); @@ -14,25 +14,26 @@ public class MsgStatus extends MessageBase { } 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; + 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) { - DanaRPlugin.getDanaRPump().lastBolusTime = dateTimeFromBuff(bytes, 8); - DanaRPlugin.getDanaRPump().lastBolusAmount = lastBolusAmount; + pump.lastBolusTime = dateTimeFromBuff(bytes, 8); + pump.lastBolusAmount = lastBolusAmount; } - DanaRPlugin.getDanaRPump().iob = intFromBuff(bytes, 15, 2) / 100d; + pump.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); + 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/PumpDanaR/comm/MsgStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java index c50fac371a..ba8374f383 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgStatusBasic.java @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; @@ -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 index de0749c292..256ccc18da 100644 --- 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 @@ -5,14 +5,13 @@ 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.PumpDanaR.DanaRPlugin; +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 { @@ -29,19 +28,23 @@ public class MsgStatusBolusExtended extends MessageBase { 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; - 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; + 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(); @@ -58,54 +61,46 @@ public class MsgStatusBolusExtended extends MessageBase { @NonNull private Date getDateFromSecAgo(int tempBasalAgoSecs) { - return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + return new Date((long) (Math.ceil(System.currentTimeMillis() / 1000d) - tempBasalAgoSecs) * 1000); } public static void updateExtendedBolusInDB() { - DanaRPlugin DanaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRPump danaRPump = DanaRPlugin.getDanaRPump(); - Date now = new Date(); + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + DanaRPump pump = DanaRPump.getInstance(); + long now = System.currentTimeMillis(); - 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()); + if (treatmentsInterface.isInHistoryExtendedBoluslInProgress()) { + ExtendedBolus extendedBolus = treatmentsInterface.getExtendedBolusFromHistory(System.currentTimeMillis()); + 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 { - 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()); - } + // 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); } - } catch (SQLException e) { - e.printStackTrace(); } } } 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 index 7a703d468a..70b67c3b77 100644 --- 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 @@ -4,7 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; /** @@ -18,25 +17,26 @@ public class MsgStatusProfile extends MessageBase { } 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); + 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 { - 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; + 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): " + (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); + 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 index 1a2e21c004..725bed1220 100644 --- 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 @@ -5,14 +5,13 @@ 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.PumpDanaR.DanaRPlugin; +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 { @@ -23,23 +22,30 @@ public class MsgStatusTempBasal extends MessageBase { } public void handleMessage(byte[] bytes) { - boolean isTempBasalInProgress = intFromBuff(bytes, 0, 1) == 1; + boolean isTempBasalInProgress = (intFromBuff(bytes, 0, 1) & 0x01) == 0x01; + boolean isAPSTempBasalInProgress = (intFromBuff(bytes, 0, 1) & 0x02) == 0x02; int tempBasalPercent = intFromBuff(bytes, 1, 1); - int tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60; + 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); - DanaRPlugin.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress; - DanaRPlugin.getDanaRPump().tempBasalPercent = tempBasalPercent; - DanaRPlugin.getDanaRPump().tempBasalRemainingMin = tempBasalRemainingMin; - DanaRPlugin.getDanaRPump().tempBasalTotalSec = tempBasalTotalSec; - DanaRPlugin.getDanaRPump().tempBasalStart = tempBasalStart; + 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); @@ -49,54 +55,48 @@ public class MsgStatusTempBasal extends MessageBase { @NonNull private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) { - return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000); + return new Date((long) (Math.ceil(System.currentTimeMillis() / 1000d) - tempBasalAgoSecs) * 1000); } public static void updateTempBasalInDB() { - DanaRPlugin DanaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - DanaRPump danaRPump = DanaRPlugin.getDanaRPump(); - Date now = new Date(); + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + DanaRPump danaRPump = DanaRPump.getInstance(); + long now = System.currentTimeMillis(); - 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 { + if (treatmentsInterface.isInHistoryRealTempBasalInProgress()) { + TemporaryBasal tempBasal = treatmentsInterface.getRealTempBasalFromHistory(System.currentTimeMillis()); + if (danaRPump.isTempBasalInProgress) { + if (tempBasal.percentRate != danaRPump.tempBasalPercent) { // Close current temp basal - tempBasal.timeEnd = now; - MainApp.getDbHelper().getDaoTempBasals().update(tempBasal); - MainApp.bus().post(new EventTempBasalChange()); + 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 { - 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()); - } + // 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); } - } catch (SQLException e) { - e.printStackTrace(); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Services/ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java similarity index 90% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Services/ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java index 3916b25bf9..606eab3794 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/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.PumpDanaR.Services; +package info.nightscout.androidaps.plugins.PumpDanaR.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,6 +32,7 @@ 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.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread; @@ -79,12 +79,12 @@ 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.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; @@ -95,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; @@ -120,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; } } @@ -201,9 +200,9 @@ public class ExecutionService extends Service { 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; + long startTime = System.currentTimeMillis(); + while (!isConnected() && startTime + maxConnectionTime >= System.currentTimeMillis()) { + long secondsElapsed = (System.currentTimeMillis() - startTime) / 1000L; MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); if (Config.logDanaBTComm) log.debug("connect waiting " + secondsElapsed + "sec from: " + from); @@ -230,7 +229,7 @@ public class ExecutionService extends Service { if (!MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP)) return; getBTSocketForSelectedPump(); - startTime = new Date().getTime(); + startTime = System.currentTimeMillis(); } } } @@ -319,7 +318,7 @@ public class ExecutionService extends Service { } Date now = new Date(); - if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !((DanaRPlugin)MainApp.getSpecificPlugin(DanaRPlugin.class)).isInitialized()) { + if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) { mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); mSerialIOThread.sendMessage(new MsgSettingActiveProfile()); mSerialIOThread.sendMessage(new MsgSettingMeal()); @@ -327,23 +326,30 @@ public class ExecutionService extends Service { //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())); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + log.debug("Pump time difference: " + timeDiff + " seconds"); + if (Math.abs(timeDiff) > 10) { + mSerialIOThread.sendMessage(new MsgSetTime(new Date())); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + log.debug("Pump time difference: " + timeDiff + " seconds"); + } danaRPump.lastSettingsRead = now; } 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(); @@ -354,6 +360,11 @@ public class ExecutionService extends Service { 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()); @@ -400,12 +411,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(System.currentTimeMillis(), carbs)); } + MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables MainApp.bus().post(new EventDanaRBolusStart()); - long startTime = new Date().getTime(); + long startTime = System.currentTimeMillis(); if (!stop.stopped) { mSerialIOThread.sendMessage(start); @@ -415,7 +426,7 @@ public class ExecutionService extends Service { } 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 + if ((System.currentTimeMillis() - 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"); @@ -426,7 +437,7 @@ public class ExecutionService extends Service { // try to find real amount if bolusing was interrupted or comm failed if (t.insulin != amount) { disconnect("bolusingInterrupted"); - long now = new Date().getTime(); + long now = System.currentTimeMillis(); long estimatedBolusEnd = (long) (startTime + amount / 5d * 60 * 1000); // std delivery rate 5 U/min waitMsec(Math.max(5000, estimatedBolusEnd - now + 3000)); connect("bolusingInterrupted"); @@ -462,8 +473,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(System.currentTimeMillis(), amount); mSerialIOThread.sendMessage(msg); return true; } @@ -513,7 +523,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))); @@ -528,12 +538,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++) { //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; + double value = Math.round(100d * nsProfile.getBasal((Integer) (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/PumpDanaRKorean/DanaRKoreanFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanFragment.java index e03fc97b33..50ec8883c6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanFragment.java @@ -24,17 +24,20 @@ 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.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRStatsActivity; import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; -import info.nightscout.androidaps.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 { +public class DanaRKoreanFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(DanaRKoreanFragment.class); private static DanaRKoreanPlugin danaRKoreanPlugin = new DanaRKoreanPlugin(); @@ -152,18 +155,6 @@ public class DanaRKoreanFragment extends Fragment { 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(); @@ -194,8 +185,14 @@ public class DanaRKoreanFragment extends Fragment { updateGUI(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange s) { + updateGUI(); + } + // GUI functions - private void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null && basaBasalRateView != null) @@ -203,15 +200,15 @@ public class DanaRKoreanFragment extends Fragment { @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(); + Long agoMsec = System.currentTimeMillis() - 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(); +// Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime(); // double agoHours = agoMsec / 60d / 60d / 1000d; // if (agoHours < 6) // max 6h back // lastBolusView.setText(formatTime.format(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + " U"); @@ -221,13 +218,13 @@ public class DanaRKoreanFragment extends Fragment { 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(System.currentTimeMillis()).toStringFull()); } else { tempBasalView.setText(""); } - if (danaRKoreanPlugin.isExtendedBoluslInProgress()) { - extendedBolusView.setText(danaRKoreanPlugin.getExtendedBolus().toString()); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString()); } else { extendedBolusView.setText(""); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index 726e1b95ab..354db54c48 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -4,9 +4,7 @@ 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,32 +22,37 @@ 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; import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.interfaces.DanaRInterface; 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.plugins.PumpDanaRKorean.Services.ExecutionService; -import info.nightscout.androidaps.plugins.ProfileNS.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. */ -public class DanaRKoreanPlugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface { +public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface { private static Logger log = LoggerFactory.getLogger(DanaRKoreanPlugin.class); @Override @@ -61,48 +64,39 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints 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.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; @@ -111,7 +105,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints pumpDescription.isRefillingCapable = true; } - ServiceConnection mConnection = new ServiceConnection() { + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceDisconnected(ComponentName name) { log.debug("Service is disconnected"); @@ -120,7 +114,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(); } }; @@ -135,12 +129,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(); } } @@ -160,7 +151,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; } @@ -219,14 +210,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 @@ -237,23 +233,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; @@ -278,17 +258,17 @@ 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; 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); + Double profileValue = profile.getBasal((Integer) (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; @@ -299,7 +279,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints @Override public Date lastDataTime() { - return getDanaRPump().lastConnection; + return pump.lastConnection; } @Override @@ -311,84 +291,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(InsulinInterface insulinType, 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(insulinType); + detailedBolusInfo.insulin = configBuilderPlugin.applyBolusConstraints(detailedBolusInfo.insulin); + if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { + Treatment t = new Treatment(); 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 = System.currentTimeMillis(); + 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; @@ -406,9 +336,9 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints // This is called from APS @Override - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { // 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 < System.currentTimeMillis()) { doConnect("setTempBasalAbsolute old data"); } @@ -424,13 +354,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(); @@ -453,7 +383,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(); @@ -463,26 +393,21 @@ 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) { - result.success = true; - result.percent = percentRate; - result.absolute = getTempBasalAbsoluteRate(); - result.enacted = false; - result.duration = ((Double) getTempBasalRemainingMinutes()).intValue(); - result.isPercent = true; - result.isTempCancel = false; - if (Config.logPumpActions) - log.debug("setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)"); - return result; - } else { - if (Config.logPumpActions) - log.debug("setTempBasalAbsolute: Stopping temp basal (doLowTemp || doHighTemp)"); - result = cancelRealTempBasal(); - // Check for proper result - if (!result.success) { - log.error("setTempBasalAbsolute: Failed to stop previous temp basal (doLowTemp || doHighTemp)"); + if (MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).percentRate == percentRate) { + if (force) { + cancelTempBasal(true); + } else { + 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; } } @@ -494,7 +419,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(); @@ -511,21 +436,21 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints Double extendedRateToSet = absoluteRate - getBaseBasalRate(); extendedRateToSet = configBuilderPlugin.applyBasalConstraints(extendedRateToSet); // needs to be rounded to 0.1 - extendedRateToSet = Round.roundTo(extendedRateToSet, 0.1d); + extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2); // *2 because of 30 min // 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) @@ -567,14 +492,16 @@ 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.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: Correct value already set"); @@ -582,13 +509,14 @@ 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.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); result.isPercent = true; if (Config.logPumpActions) log.debug("setTempBasalPercent: OK"); @@ -606,31 +534,31 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints ConfigBuilderPlugin configBuilderPlugin = MainApp.getConfigBuilder(); insulin = configBuilderPlugin.applyBolusConstraints(insulin); // needs to be rounded - insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep); + int durationInHalfHours = Math.max(durationInMinutes / 30, 1); + insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep * (1 + durationInHalfHours % 1)); 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"); @@ -644,11 +572,13 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints } @Override - public PumpEnactResult cancelTempBasal() { - if (isRealTempBasalInProgress()) + public PumpEnactResult cancelTempBasal(boolean force) { + 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; @@ -659,12 +589,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); @@ -683,12 +613,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) @@ -720,48 +650,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 < System.currentTimeMillis()) { 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(System.currentTimeMillis()); if (tb != null) { - extended.put("TempBasalAbsoluteRate", getTempBasalAbsoluteRate()); - extended.put("TempBasalStart", tb.timeStart.toLocaleString()); + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); - extended.put("IsExtended", tb.isExtended); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + 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 @@ -769,6 +706,15 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, Constraints return pumpDescription; } + /** + * DanaR interface + */ + + @Override + public boolean loadHistory(byte type) { + return sExecutionService.loadHistory(type); + } + /** * Constraint interface */ @@ -797,9 +743,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"); } @@ -812,7 +758,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; @@ -822,9 +769,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"); } @@ -844,36 +791,45 @@ 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 getUnits() { + return pump.getUnits(); + } + + @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 = System.currentTimeMillis() - 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(System.currentTimeMillis()).toStringFull() + "\n"; } - if (!veryShort){ - ret += "TDD: " + DecimalFormatter.to0Decimal(getDanaRPump().dailyTotalUnits) + " / " + getDanaRPump().maxDailyTotalUnits + " U\n"; + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).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/DanaRKoreanPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPump.java deleted file mode 100644 index 7ea3a0cffc..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPump.java +++ /dev/null @@ -1,167 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean; - -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, Constants.defaultDIA); - - 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/PumpDanaRKorean/History/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java deleted file mode 100644 index dc0e513913..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/History/DanaRStatsActivity.java +++ /dev/null @@ -1,561 +0,0 @@ -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; -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.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; -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.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; -import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.Services.ExecutionService; -import info.nightscout.utils.DecimalFormatter; -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 ExecutionService 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, ExecutionService.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; - ExecutionService.LocalBinder mLocalBinder = (ExecutionService.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); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - TBB = preferences.getString("TBB", "10.00"); - totalBaseBasal.setText(TBB); - - ProfileInterface pi = ConfigBuilderPlugin.getActiveProfile(); - 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", ""); - } - - // 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 { - SharedPreferences.Editor edit = preferences.edit(); - edit.putString("TBB", totalBaseBasal.getText().toString()); - edit.commit(); - TBB = preferences.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) { - 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<>(); - } - 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.getRecordDailyBolus() + record.getRecordDailyBasal(); - - // 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.getRecordDate()))); - 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.setTextColor(Color.WHITE); - tr.addView(labelBASAL); - - TextView labelBOLUS = new TextView(DanaRStatsActivity.this); - labelBOLUS.setId(400 + i); - labelBOLUS.setText(DecimalFormatter.to2Decimal(record.getRecordDailyBolus()) + " 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).getRecordDate())).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.getRecordDailyBolus() + record.getRecordDailyBasal(); - 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/PumpDanaRKorean/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java index b6b7a291e0..597a49a676 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/SerialIOThread.java @@ -14,8 +14,9 @@ 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; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MessageHashTable_k; 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_k.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/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/PumpDanaRKorean/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java similarity index 80% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java index 1cd6c25abf..7536bd278c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java @@ -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.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPump; 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/PumpDanaRKorean/comm/MsgInitConnStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java similarity index 84% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java index 53f62972c2..26462987d9 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBasic_k.java @@ -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.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgInitConnStatusBolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java similarity index 85% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java index 5fe064dcdd..2e6d6234f0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusBolus_k.java @@ -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.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPump; 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/PumpDanaRKorean/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java similarity index 72% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java index e302d55e7f..f54b8edb30 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java @@ -8,17 +8,18 @@ import java.util.Date; 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.events.EventRefreshOverview; 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.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)){ @@ -41,7 +43,7 @@ public class MsgInitConnStatusTime extends MessageBase { } MainApp.getConfigBuilder().storeSettings(); - MainApp.bus().post(new EventRefreshGui(false)); + MainApp.bus().post(new EventRefreshOverview("MsgInitConnStatusTime_k")); return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java similarity index 78% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java index 1a5eeeeba3..304ec9fc37 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasalProfileAll_k.java @@ -4,9 +4,8 @@ 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; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPump; /** @@ -15,16 +14,16 @@ import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgSettingBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java similarity index 75% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java index fcf8a1e1f6..72a8be4e42 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingBasal_k.java @@ -4,22 +4,22 @@ 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; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPump; /** * 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/PumpDanaRKorean/comm/MsgSettingGlucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingGlucose.java deleted file mode 100644 index 10b8f5ef74..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingGlucose.java +++ /dev/null @@ -1,30 +0,0 @@ -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.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgSettingMaxValues.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingMaxValues.java deleted file mode 100644 index c5eca68dca..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingMaxValues.java +++ /dev/null @@ -1,33 +0,0 @@ -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.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgSettingMeal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingMeal.java deleted file mode 100644 index 0fae0a27db..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingMeal.java +++ /dev/null @@ -1,53 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.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.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPump; -import info.nightscout.androidaps.plugins.Overview.Notification; -import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; - -/** - * 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) { - DanaRKoreanPump pump = DanaRKoreanPlugin.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); - } - - if (pump.isConfigUD) { - Notification notification = new Notification(Notification.UD_MODE_ENABLED, MainApp.sResources.getString(R.string.danar_switchtouhmode), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); - } else { - MainApp.bus().post(new EventDismissNotification(Notification.UD_MODE_ENABLED)); - } - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingProfileRatios.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingProfileRatios.java deleted file mode 100644 index f34dff5328..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingProfileRatios.java +++ /dev/null @@ -1,45 +0,0 @@ -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.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingPumpTime.java deleted file mode 100644 index 180da93bbb..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingPumpTime.java +++ /dev/null @@ -1,35 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Date; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgSettingShippingInfo.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingShippingInfo.java deleted file mode 100644 index 80900dfba5..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgSettingShippingInfo.java +++ /dev/null @@ -1,33 +0,0 @@ -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.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus.java deleted file mode 100644 index d17b41edd2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatus.java +++ /dev/null @@ -1,39 +0,0 @@ -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.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgStatusBasic.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java similarity index 64% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java index 5332ec5ffa..0fcaf17d83 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBasic_k.java @@ -4,29 +4,30 @@ 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; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -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/MsgStatusBolusExtended.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBolusExtended.java deleted file mode 100644 index f5879b76a8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusBolusExtended.java +++ /dev/null @@ -1,114 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.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.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgStatusProfile.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusProfile.java deleted file mode 100644 index 58f7077ae8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusProfile.java +++ /dev/null @@ -1,43 +0,0 @@ -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.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/PumpDanaRKorean/comm/MsgStatusTempBasal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusTempBasal.java deleted file mode 100644 index 6ba599f33b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgStatusTempBasal.java +++ /dev/null @@ -1,103 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.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.PumpDanaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.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/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..1fdcf26917 --- /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/PumpDanaRKorean/Services/ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java similarity index 82% rename from app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/Services/ExecutionService.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java index fff5a84eb3..b7c9f8ca2c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/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.PumpDanaRKorean.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,6 +32,8 @@ 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.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; @@ -56,31 +57,30 @@ import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetSingleBasalProfil import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStart; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTempBasalStop; import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgSetTime; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.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.DanaRKoreanPump; import info.nightscout.androidaps.plugins.PumpDanaRKorean.SerialIOThread; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgCheckValue; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingBasal; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingGlucose; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingMaxValues; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingMeal; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingProfileRatios; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingPumpTime; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgSettingShippingInfo; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBasic; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusBolusExtended; -import info.nightscout.androidaps.plugins.PumpDanaRKorean.comm.MsgStatusTempBasal; -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.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; } @@ -197,9 +196,9 @@ public class ExecutionService extends Service { 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; + long startTime = System.currentTimeMillis(); + while (!isConnected() && startTime + maxConnectionTime >= System.currentTimeMillis()) { + long secondsElapsed = (System.currentTimeMillis() - startTime) / 1000L; MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); if (Config.logDanaBTComm) log.debug("connect waiting " + secondsElapsed + "sec from: " + from); @@ -219,14 +218,14 @@ 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); if (!MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP)) return; getBTSocketForSelectedPump(); - startTime = new Date().getTime(); + startTime = System.currentTimeMillis(); } } } @@ -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,34 @@ 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() || !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; + long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + log.debug("Pump time difference: " + timeDiff + " seconds"); + if (Math.abs(timeDiff) > 10) { + mSerialIOThread.sendMessage(new MsgSetTime(new Date())); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + log.debug("Pump time difference: " + timeDiff + " seconds"); + } + 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(); @@ -348,6 +353,11 @@ public class ExecutionService extends Service { 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()); @@ -385,7 +395,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 +404,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(System.currentTimeMillis(), carbs)); } MsgBolusProgress progress = new MsgBolusProgress(amount, t); // initialize static variables @@ -409,7 +418,7 @@ public class ExecutionService extends Service { } 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 + if ((System.currentTimeMillis() - 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"); @@ -440,8 +449,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(System.currentTimeMillis(), amount); mSerialIOThread.sendMessage(msg); return true; } @@ -491,23 +499,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 = Math.round(100d * nsProfile.getBasal(hour * 60 * 60))/100d + 0.00001; + double value = Math.round(100d * nsProfile.getBasal((Integer) (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..85d9f4b5f2 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Fragment.java @@ -0,0 +1,250 @@ +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.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRStatsActivity; +import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.SetWarnColor; + +public class DanaRv2Fragment extends SubscriberFragment { + 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; + TextView basalStepView; + TextView bolusStepView; + 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); + basalStepView = (TextView) view.findViewById(R.id.danar_basalstep); + bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep); + + + 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; + } + + @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 + @Override + protected 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 = System.currentTimeMillis() - 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 = System.currentTimeMillis() - pump.lastBolusTime.getTime(); + double agoHours = agoMsec / 60d / 60d / 1000d; + if (agoHours < 6) // max 6h back + lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + MainApp.sResources.getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U"); + 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(System.currentTimeMillis()).toStringFull()); + } else { + tempBasalView.setText(""); + } + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).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"); + } + basalStepView.setText("" + pump.basalStep); + bolusStepView.setText("" + pump.bolusStep); + } + }); + + } + +} 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..6960e96b17 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -0,0 +1,772 @@ +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.DanaRInterface; +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.ConfigBuilder.DetailedBolusInfoStorage; +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, DanaRInterface, 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() { + 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; + } + + private 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((Integer) (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) { + DetailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history + // v2 stores end time for bolus, we need to adjust time + // delivery speed is 12 U/min + detailedBolusInfo.date += detailedBolusInfo.insulin / 12d * 60 * 1000; + // clean carbs to prevent counting them as twice because they will picked up as another record + // I don't think it's necessary to copy DetailedBolusInfo right now for carbs records + double carbs = detailedBolusInfo.carbs; + detailedBolusInfo.carbs = 0; + int carbTime = detailedBolusInfo.carbTime; + detailedBolusInfo.carbTime = 0; + + Treatment t = new Treatment(); + boolean connectionOK = false; + if (detailedBolusInfo.insulin > 0 || carbs > 0) + connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + 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); + // remove carbs because it's get from history seprately + 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, boolean force) { + // Recheck pump status if older than 30 min + if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { + 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(false); + } + 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(System.currentTimeMillis()).percentRate == percentRate) { + if (!force) { + 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.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); + 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.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory(); + 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 + int durationInHalfHours = Math.max(durationInMinutes / 30, 1); + insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep * (1 + durationInHalfHours % 1)); + 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; + } + 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(boolean force) { + 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 < System.currentTimeMillis()) { + 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(System.currentTimeMillis()); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + 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; + } + + /** + * DanaR interface + */ + + @Override + public boolean loadHistory(byte type) { + return sExecutionService.loadHistory(type); + } + + /** + * 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 getUnits() { + return pump.getUnits(); + } + + @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 = System.currentTimeMillis() - 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(System.currentTimeMillis()).toStringFull() + "\n"; + } + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).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/PumpDanaRv2/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java new file mode 100644 index 0000000000..0b67b6acc6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/SerialIOThread.java @@ -0,0 +1,229 @@ +package info.nightscout.androidaps.plugins.PumpDanaRv2; + +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.PumpDanaRv2.comm.MessageHashTable_v2; +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_v2.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.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/PumpDanaRKorean/comm/MessageHashTable.java rename to app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java index 36cf8c8edb..0940efd73f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MessageHashTable.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.PumpDanaRKorean.comm; +package info.nightscout.androidaps.plugins.PumpDanaRv2.comm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -6,32 +6,14 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; 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.MsgError; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAll; -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.MsgHistoryGlucose; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryNew; -import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryNewDone; -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.*; + /** * 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..d7b37a4b0f --- /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.EventRefreshOverview; +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 EventRefreshOverview("MsgCheckValue_v2")); + 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..f04218ac61 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgHistoryEvents_v2.java @@ -0,0 +1,151 @@ +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.ConfigBuilder.DetailedBolusInfoStorage; +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 = DetailedBolusInfoStorage.findDetailedBolusInfo(datetime.getTime()); + if (detailedBolusInfo == null) { + log.debug("DetailedBolusInfo not found for " + datetime.toLocaleString()); + detailedBolusInfo = new DetailedBolusInfo(); + } + detailedBolusInfo.date = datetime.getTime(); + detailedBolusInfo.source = Source.PUMP; + detailedBolusInfo.pumpId = datetime.getTime(); + + 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: + detailedBolusInfo.insulin = param1 / 100d; + boolean newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + log.debug((newRecord ? "**NEW** " : "") + "EVENT BOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + DetailedBolusInfoStorage.remove(detailedBolusInfo.date); + break; + case DanaRPump.DUALBOLUS: + detailedBolusInfo.insulin = param1 / 100d; + newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + log.debug((newRecord ? "**NEW** " : "") + "EVENT DUALBOLUS (" + recordCode + ") " + datetime.toLocaleString() + " Bolus: " + (param1 / 100d) + "U Duration: " + param2 + "min"); + DetailedBolusInfoStorage.remove(detailedBolusInfo.date); + 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 + " CurrentRate: " + (param2 / 100d) + "U/h"); + break; + case DanaRPump.CARBS: + DetailedBolusInfo emptyCarbsInfo = new DetailedBolusInfo(); + emptyCarbsInfo.carbs = param1; + emptyCarbsInfo.date = datetime.getTime(); + emptyCarbsInfo.source = Source.PUMP; + emptyCarbsInfo.pumpId = datetime.getTime(); + newRecord = MainApp.getConfigBuilder().addToHistoryTreatment(emptyCarbsInfo); + log.debug((newRecord ? "**NEW** " : "") + "EVENT CARBS (" + recordCode + ") " + datetime.toLocaleString() + " Carbs: " + param1 + "g"); + 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..f695f6a792 --- /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(System.currentTimeMillis() / 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..256fa4cd8a --- /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(System.currentTimeMillis() / 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..0ac333787a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -0,0 +1,563 @@ +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 = System.currentTimeMillis(); + while (!isConnected() && startTime + maxConnectionTime >= System.currentTimeMillis()) { + long secondsElapsed = (System.currentTimeMillis() - startTime) / 1000L; + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + if (Config.logDanaBTComm) + log.debug("connect waiting " + secondsElapsed + "sec from: " + from); + 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 = System.currentTimeMillis(); + } + } + } + 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() || !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 MsgSettingActiveProfile()); + mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); + mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll()); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + log.debug("Pump time difference: " + timeDiff + " seconds"); + if (Math.abs(timeDiff) > 10) { + mSerialIOThread.sendMessage(new MsgSetTime(new Date())); + mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L; + log.debug("Pump time difference: " + timeDiff + " seconds"); + } + 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 ((System.currentTimeMillis() - 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; + waitMsec(300); + 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((Integer) (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 deleted file mode 100644 index f6221d627e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIFragment.java +++ /dev/null @@ -1,12 +0,0 @@ -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/PumpMDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java index e9010438c6..f9f4b6fa2d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.PumpMDI; -import android.content.Context; - import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; @@ -13,13 +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.Profile; import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.TempBasal; -import info.nightscout.androidaps.interfaces.InsulinInterface; 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.utils.DateUtil; /** @@ -33,37 +30,27 @@ public class MDIPlugin implements PluginBase, PumpInterface { PumpDescription pumpDescription = new PumpDescription(); + static MDIPlugin plugin = null; + + public static MDIPlugin getPlugin() { + if (plugin == null) + plugin = new MDIPlugin(); + return plugin; + } + public MDIPlugin() { pumpDescription.isBolusCapable = true; 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; } @Override public String getFragmentClass() { - return MDIFragment.class.getName(); + return null; } @Override @@ -117,6 +104,11 @@ public class MDIPlugin implements PluginBase, PumpInterface { return PluginBase.PUMP; } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return false; + } + @Override public boolean isInitialized() { return true; @@ -133,23 +125,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; } @@ -169,37 +151,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(InsulinInterface insulinType, 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; } @@ -208,7 +166,7 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes) { + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { PumpEnactResult result = new PumpEnactResult(); result.success = false; result.comment = MainApp.instance().getString(R.string.pumperror); @@ -238,7 +196,7 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public PumpEnactResult cancelTempBasal() { + public PumpEnactResult cancelTempBasal(boolean force) { PumpEnactResult result = new PumpEnactResult(); result.success = false; result.comment = MainApp.instance().getString(R.string.pumperror); @@ -266,7 +224,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/PumpVirtual/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java index edad845092..b479183b80 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java @@ -5,7 +5,6 @@ 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; @@ -18,17 +17,12 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; -public class VirtualPumpFragment extends Fragment { +public class VirtualPumpFragment extends SubscriberFragment { 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; @@ -63,47 +57,35 @@ public class VirtualPumpFragment extends Fragment { batteryView = (TextView) view.findViewById(R.id.virtualpump_battery); reservoirView = (TextView) view.findViewById(R.id.virtualpump_reservoir); - 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 EventVirtualPumpUpdateGui ev) { updateGUI(); } - public void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null && basaBasalRateView != null) activity.runOnUiThread(new Runnable() { @Override public void run() { - - basaBasalRateView.setText(virtualPumpPlugin.getBaseBasalRate() + "U"); - if (virtualPumpPlugin.isTempBasalInProgress()) { - tempBasalView.setText(virtualPumpPlugin.getTempBasal().toString()); + VirtualPumpPlugin virtualPump = VirtualPumpPlugin.getInstance(); + basaBasalRateView.setText(virtualPump.getBaseBasalRate() + "U"); + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + tempBasalView.setText(MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()).toStringFull()); } else { tempBasalView.setText(""); } - if (virtualPumpPlugin.isExtendedBoluslInProgress()) { - extendedBolusView.setText(virtualPumpPlugin.getExtendedBolus().toString()); + if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) { + extendedBolusView.setText(MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString()); } else { extendedBolusView.setText(""); } - batteryView.setText(VirtualPumpPlugin.batteryPercent + "%"); - reservoirView.setText(VirtualPumpPlugin.reservoirInUnits + "U"); + batteryView.setText(virtualPump.batteryPercent + "%"); + reservoirView.setText(virtualPump.reservoirInUnits + "U"); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 2a1221e88d..c04ec9b12f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.PumpVirtual; -import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -9,24 +8,27 @@ 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.interfaces.InsulinInterface; +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.PumpVirtual.events.EventVirtualPumpUpdateGui; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; +import info.nightscout.utils.SP; /** * Created by mike on 05.08.2016. @@ -44,32 +46,53 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { boolean fragmentEnabled = true; boolean fragmentVisible = true; + private static boolean fromNSAreCommingFakedExtendedBoluses = false; + PumpDescription pumpDescription = new PumpDescription(); + static void loadFakingStatus() { + fromNSAreCommingFakedExtendedBoluses = SP.getBoolean("fromNSAreCommingFakedExtendedBoluses", false); + } + + public static void setFakingStatus(boolean newStatus) { + fromNSAreCommingFakedExtendedBoluses = newStatus; + SP.putBoolean("fromNSAreCommingFakedExtendedBoluses", fromNSAreCommingFakedExtendedBoluses); + } + + public static boolean getFakingStatus() { + return fromNSAreCommingFakedExtendedBoluses; + } + + static VirtualPumpPlugin instance = null; + public static VirtualPumpPlugin getInstance() { + loadFakingStatus(); + 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; } @@ -87,7 +110,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; } @@ -135,6 +158,11 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { return PluginBase.PUMP; } + @Override + public boolean isFakingTempsByExtendedBoluses() { + return Config.NSCLIENT && fromNSAreCommingFakedExtendedBoluses; + } + @Override public boolean isInitialized() { return true; @@ -151,24 +179,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; } @@ -179,74 +197,38 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public void refreshDataFromPump(String reason) { - MainApp.getConfigBuilder().uploadDeviceStatus(); + if (!BuildConfig.NSCLIENTOLNY) + NSUpload.uploadDeviceStatus(); lastDataTime = new Date(); } @Override public double getBaseBasalRate() { - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - if (profile == null) - return defaultBasalValue; - return profile.getBasal(profile.secondsFromMidnight()); + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile != null) + return profile.getBasal(); + else + return 0d; } @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(InsulinInterface insulinType, 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; } @@ -255,18 +237,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; } @@ -276,28 +258,22 @@ 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(); + public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + TemporaryBasal tempBasal = new TemporaryBasal(); + tempBasal.date = System.currentTimeMillis(); 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()); @@ -307,17 +283,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()) { - result = cancelTempBasal(); + if (MainApp.getConfigBuilder().isTempBasalInProgress()) { + result = cancelTempBasal(false); if (!result.success) return result; } - TempBasal tempBasal = new TempBasal(); - tempBasal.timeStart = new Date(); + TemporaryBasal tempBasal = new TemporaryBasal(); + tempBasal.date = System.currentTimeMillis(); 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; @@ -325,13 +303,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()); @@ -341,29 +313,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 = System.currentTimeMillis(); + 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()); @@ -372,27 +337,21 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } @Override - public PumpEnactResult cancelTempBasal() { + public PumpEnactResult cancelTempBasal(boolean force) { + 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(System.currentTimeMillis()); + 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; @@ -400,17 +359,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(System.currentTimeMillis()); + exStop.source = Source.USER; + treatmentsInterface.addToHistoryExtendedBolus(exStop); } result.success = true; result.enacted = true; @@ -438,13 +392,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(System.currentTimeMillis()); + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(System.currentTimeMillis())); + extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date)); + extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); + } + ExtendedBolus eb = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()); + 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())); @@ -454,6 +415,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/SensitivityAAPS/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java new file mode 100644 index 0000000000..9f0dc9a21f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java @@ -0,0 +1,200 @@ +package info.nightscout.androidaps.plugins.SensitivityAAPS; + +import android.support.v4.util.LongSparseArray; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.SensitivityInterface; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.utils.Round; +import info.nightscout.utils.SP; +import info.nightscout.utils.SafeParse; + +/** + * Created by mike on 24.06.2017. + */ + +public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{ + private static Logger log = LoggerFactory.getLogger(SensitivityAAPSPlugin.class); + + private static boolean fragmentEnabled = true; + private static boolean fragmentVisible = false; + + static SensitivityAAPSPlugin plugin = null; + + public static SensitivityAAPSPlugin getPlugin() { + if (plugin == null) + plugin = new SensitivityAAPSPlugin(); + return plugin; + } + + @Override + public int getType() { + return SENSITIVITY; + } + + @Override + public String getFragmentClass() { + return null; + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.sensitivityaaps); + } + + @Override + public String getNameShort() { + return MainApp.sResources.getString(R.string.sensitivity_shortname); + } + + @Override + public boolean isEnabled(int type) { + return type == SENSITIVITY && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == SENSITIVITY && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + 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 == SENSITIVITY) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == SENSITIVITY) this.fragmentVisible = fragmentVisible; + } + + + @Override + public AutosensResult detectSensitivity(long fromTime, long toTime) { + LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getAutosensDataTable(); + + String age = SP.getString(R.string.key_age, ""); + int defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_adult))) defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_teenage))) defaultHours = 4; + if (age.equals(MainApp.sResources.getString(R.string.key_child))) defaultHours = 4; + int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours); + + if (autosensDataTable == null || autosensDataTable.size() < 4) { + log.debug("No autosens data available"); + return new AutosensResult(); + } + + AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); + if (current == null) { + log.debug("No 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.time > toTime) { + index++; + continue; + } + + if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L) + deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d); + if (deviationsArray.size() > hoursForDetection * 60 / 5) + deviationsArray.remove(0); + + + pastSensitivity += autosensData.pastSensitivity; + int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time); + if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) { + pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")"; + } + index++; + } + + Double[] deviations = new Double[deviationsArray.size()]; + deviations = deviationsArray.toArray(deviations); + + Profile profile = MainApp.getConfigBuilder().getProfile(); + + double sens = profile.getIsf(); + + String ratioLimit = ""; + String sensResult = ""; + + log.debug("Records: " + index + " " + pastSensitivity); + Arrays.sort(deviations); + + double percentile = IobCobCalculatorPlugin.percentile(deviations, 0.50); + double basalOff = percentile * (60 / 5) / Profile.toMgdl(sens, profile.getUnits()); + double ratio = 1 + (basalOff / profile.getMaxDailyBasal()); + + if (percentile < 0) { // sensitive + sensResult = "Excess insulin sensitivity detected"; + } else if (percentile > 0) { // resistant + sensResult = "Excess insulin resistance detected"; + } else { + sensResult = "Sensitivity normal"; + } + + log.debug(sensResult); + + 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); + } + + log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " percentile: " + percentile + " ratio: " + ratio); + log.debug("Sensitivity to: deviations " + Arrays.toString(deviations)); + + AutosensResult output = new AutosensResult(); + output.ratio = Round.roundTo(ratio, 0.01); + output.carbsAbsorbed = Round.roundTo(current.cob, 0.01); + output.pastSensitivity = pastSensitivity; + output.ratioLimit = ratioLimit; + output.sensResult = sensResult; + return output; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java new file mode 100644 index 0000000000..4face65ced --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java @@ -0,0 +1,210 @@ +package info.nightscout.androidaps.plugins.SensitivityOref0; + +import android.support.v4.util.LongSparseArray; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.SensitivityInterface; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.utils.Round; +import info.nightscout.utils.SP; +import info.nightscout.utils.SafeParse; + +/** + * Created by mike on 24.06.2017. + */ + +public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface { + private static Logger log = LoggerFactory.getLogger(IobCobCalculatorPlugin.class); + + private static boolean fragmentEnabled = true; + private static boolean fragmentVisible = false; + + static SensitivityOref0Plugin plugin = null; + + public static SensitivityOref0Plugin getPlugin() { + if (plugin == null) + plugin = new SensitivityOref0Plugin(); + return plugin; + } + + @Override + public int getType() { + return SENSITIVITY; + } + + @Override + public String getFragmentClass() { + return null; + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.sensitivityoref0); + } + + @Override + public String getNameShort() { + return MainApp.sResources.getString(R.string.sensitivity_shortname); + } + + @Override + public boolean isEnabled(int type) { + return type == SENSITIVITY && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == SENSITIVITY && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + 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 == SENSITIVITY) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == SENSITIVITY) this.fragmentVisible = fragmentVisible; + } + + + @Override + public AutosensResult detectSensitivity(long fromTime, long toTime) { + LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getAutosensDataTable(); + + String age = SP.getString(R.string.key_age, ""); + int defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_adult))) defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_teenage))) defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_child))) defaultHours = 24; + int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours); + + long now = System.currentTimeMillis(); + + if (autosensDataTable == null || autosensDataTable.size() < 4) { + log.debug("No autosens data available"); + return new AutosensResult(); + } + + AutosensData current = IobCobCalculatorPlugin.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.time > toTime) { + index++; + continue; + } + + if (autosensData.time > toTime - hoursForDetection * 60 * 60 * 1000L) + deviationsArray.add(autosensData.nonEqualDeviation ? autosensData.deviation : 0d); + if (deviationsArray.size() > hoursForDetection * 60 / 5) + deviationsArray.remove(0); + + pastSensitivity += autosensData.pastSensitivity; + int secondsFromMidnight = Profile.secondsFromMidnight(autosensData.time); + if (secondsFromMidnight % 3600 < 2.5 * 60 || secondsFromMidnight % 3600 > 57.5 * 60) { + pastSensitivity += "(" + Math.round(secondsFromMidnight / 3600d) + ")"; + } + index++; + } + + 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 (IobCobCalculatorPlugin.percentile(deviations, (i + 0.02)) >= 0 && IobCobCalculatorPlugin.percentile(deviations, i) < 0) { + log.debug(Math.round(100 * i) + "% of non-meal deviations negative (target 45%-50%)"); + } + } + double pSensitive = IobCobCalculatorPlugin.percentile(deviations, 0.50); + double pResistant = IobCobCalculatorPlugin.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; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java new file mode 100644 index 0000000000..b957e21bda --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java @@ -0,0 +1,217 @@ +package info.nightscout.androidaps.plugins.SensitivityWeightedAverage; + +import android.support.v4.util.LongSparseArray; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.SensitivityInterface; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensResult; +import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.utils.Round; +import info.nightscout.utils.SP; +import info.nightscout.utils.SafeParse; + +/** + * Created by mike on 24.06.2017. + */ + +public class SensitivityWeightedAveragePlugin implements PluginBase, SensitivityInterface { + private static Logger log = LoggerFactory.getLogger(SensitivityWeightedAveragePlugin.class); + + private static boolean fragmentEnabled = true; + private static boolean fragmentVisible = false; + + static SensitivityWeightedAveragePlugin plugin = null; + + public static SensitivityWeightedAveragePlugin getPlugin() { + if (plugin == null) + plugin = new SensitivityWeightedAveragePlugin(); + return plugin; + } + + @Override + public int getType() { + return SENSITIVITY; + } + + @Override + public String getFragmentClass() { + return null; + } + + @Override + public String getName() { + return MainApp.sResources.getString(R.string.sensitivityweightedaverage); + } + + @Override + public String getNameShort() { + return MainApp.sResources.getString(R.string.sensitivity_shortname); + } + + @Override + public boolean isEnabled(int type) { + return type == SENSITIVITY && fragmentEnabled; + } + + @Override + public boolean isVisibleInTabs(int type) { + return type == SENSITIVITY && fragmentVisible; + } + + @Override + public boolean canBeHidden(int type) { + 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 == SENSITIVITY) this.fragmentEnabled = fragmentEnabled; + } + + @Override + public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == SENSITIVITY) this.fragmentVisible = fragmentVisible; + } + + + @Override + public AutosensResult detectSensitivity(long fromTime, long toTime) { + LongSparseArray autosensDataTable = IobCobCalculatorPlugin.getAutosensDataTable(); + + String age = SP.getString(R.string.key_age, ""); + int defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_adult))) defaultHours = 24; + if (age.equals(MainApp.sResources.getString(R.string.key_teenage))) defaultHours = 4; + if (age.equals(MainApp.sResources.getString(R.string.key_child))) defaultHours = 4; + int hoursForDetection = SP.getInt(R.string.key_openapsama_autosens_period, defaultHours); + + if (autosensDataTable == null || autosensDataTable.size() < 4) { + log.debug("No autosens data available"); + return new AutosensResult(); + } + + AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); + if (current == null) { + log.debug("No autosens data available"); + return new AutosensResult(); + } + + + String pastSensitivity = ""; + int index = 0; + LongSparseArray data = new LongSparseArray<>(); + + while (index < autosensDataTable.size()) { + AutosensData autosensData = autosensDataTable.valueAt(index); + + if (autosensData.time < fromTime) { + index++; + continue; + } + + if (autosensData.time > toTime) { + index++; + continue; + } + + if (autosensData.time < toTime - hoursForDetection * 60 * 60 * 1000L) { + index++; + continue; + } + + //data.append(autosensData.time); + long reverseWeight = (toTime - autosensData.time) / (5 * 60 * 1000L); + data.append(reverseWeight, autosensData.nonEqualDeviation ? autosensData.deviation : 0d); + //weights += reverseWeight; + //weightedsum += reverseWeight * (autosensData.nonEqualDeviation ? autosensData.deviation : 0d); + + + 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++; + } + + if (data.size() == 0) { + return new AutosensResult(); + } + + double weightedsum = 0; + double weights = 0; + + long hightestWeight = data.keyAt(data.size() - 1); + for (int i = 0; i < data.size(); i++) { + long reversedWeigth = data.keyAt(i); + double value = data.valueAt(i); + double weight = (hightestWeight - reversedWeigth) / 2; + weights += weight; + weightedsum += weight * value; + } + + Profile profile = MainApp.getConfigBuilder().getProfile(); + + double sens = profile.getIsf(); + + String ratioLimit = ""; + String sensResult = ""; + + log.debug("Records: " + index + " " + pastSensitivity); + + double average = weightedsum / weights; + double basalOff = average * (60 / 5) / Profile.toMgdl(sens, profile.getUnits()); + double ratio = 1 + (basalOff / profile.getMaxDailyBasal()); + + if (average < 0) { // sensitive + sensResult = "Excess insulin sensitivity detected"; + } else if (average > 0) { // resistant + sensResult = "Excess insulin resistance detected"; + } else { + sensResult = "Sensitivity normal"; + } + + log.debug(sensResult); + + 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); + } + + log.debug("Sensitivity to: " + new Date(toTime).toLocaleString() + " weightedaverage: " + average + " ratio: " + ratio); + + AutosensResult output = new AutosensResult(); + output.ratio = Round.roundTo(ratio, 0.01); + output.carbsAbsorbed = Round.roundTo(current.cob, 0.01); + output.pastSensitivity = pastSensitivity; + output.ratioLimit = ratioLimit; + output.sensResult = sensResult; + return output; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java index 83973e83ff..09a635bf86 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorFragment.java @@ -20,13 +20,14 @@ import java.util.Comparator; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; import info.nightscout.utils.DateUtil; /** * A simple {@link Fragment} subclass. */ -public class SmsCommunicatorFragment extends Fragment { +public class SmsCommunicatorFragment extends SubscriberFragment { private static Logger log = LoggerFactory.getLogger(SmsCommunicatorFragment.class); private static SmsCommunicatorPlugin smsCommunicatorPlugin; @@ -56,25 +57,14 @@ public class SmsCommunicatorFragment extends Fragment { 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 EventSmsCommunicatorUpdateGui ev) { updateGUI(); } - private void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) activity.runOnUiThread(new Runnable() { 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 d7020a536d..bb6fb80132 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 @@ -21,30 +21,32 @@ 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.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.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.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventNewSMS; import info.nightscout.androidaps.plugins.SmsCommunicator.events.EventSmsCommunicatorUpdateGui; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; import info.nightscout.utils.SafeParse; import info.nightscout.utils.XdripCalibrations; -import static info.nightscout.androidaps.R.string.profile; - /** * Created by mike on 05.08.2016. */ @@ -233,33 +235,26 @@ 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(); - if (ConfigBuilderPlugin.getActiveProfile() == null || ConfigBuilderPlugin.getActiveProfile().getProfile() == null) { - reply = MainApp.sResources.getString(R.string.noprofile); - sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); - return; - } - - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - String units = profile.getUnits(); + String units = MainApp.getConfigBuilder().getProfileUnits(); if (actualBG != null) { reply = MainApp.sResources.getString(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", "; } else if (lastBG != null) { - Long agoMsec = new Date().getTime() - lastBG.timeIndex; + Long agoMsec = System.currentTimeMillis() - 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 + ", "; - ConfigBuilderPlugin.getActiveTreatments().updateTotalIOB(); - IobTotal bolusIob = ConfigBuilderPlugin.getActiveTreatments().getLastCalculation().round(); - ConfigBuilderPlugin.getActiveTempBasals().updateTotalIOB(); - IobTotal basalIob = ConfigBuilderPlugin.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 " @@ -274,11 +269,11 @@ public class SmsCommunicatorPlugin implements PluginBase { switch (splited[1].toUpperCase()) { case "DISABLE": case "STOP": - LoopPlugin loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + 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)); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); + MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_STOP")); reply = MainApp.sResources.getString(R.string.smscommunicator_loophasbeendisabled)+ " " + MainApp.sResources.getString(result.success?R.string.smscommunicator_tempbasalcanceled:R.string.smscommunicator_tempbasalcancelfailed); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); @@ -288,17 +283,18 @@ public class SmsCommunicatorPlugin implements PluginBase { break; case "ENABLE": case "START": - loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + 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())); + MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_START")); } receivedSms.processed = true; Answers.getInstance().logCustom(new CustomEvent("SMS_Loop_Start")); break; case "STATUS": - loopPlugin = (LoopPlugin) MainApp.getSpecificPlugin(LoopPlugin.class); + loopPlugin = MainApp.getSpecificPlugin(LoopPlugin.class); if (loopPlugin != null) { if (loopPlugin.isEnabled(PluginBase.LOOP)) { if (loopPlugin.isSuspended()) @@ -316,8 +312,8 @@ public class SmsCommunicatorPlugin implements PluginBase { case "RESUME": final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); activeloop.suspendTo(0); - MainApp.bus().post(new EventRefreshGui(false)); - ConfigBuilderPlugin.uploadOpenAPSOffline(0); + MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_RESUME")); + 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")); @@ -375,12 +371,12 @@ public class SmsCommunicatorPlugin implements PluginBase { } break; case "DANAR": - DanaRPlugin danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); + DanaRPlugin danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); if (danaRPlugin != null && danaRPlugin.isEnabled(PluginBase.PUMP)) { reply = danaRPlugin.shortStatus(true); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } - DanaRKoreanPlugin danaRKoreanPlugin = (DanaRKoreanPlugin) MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); + DanaRKoreanPlugin danaRKoreanPlugin = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); if (danaRKoreanPlugin != null && danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) { reply = danaRKoreanPlugin.shortStatus(true); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); @@ -421,9 +417,12 @@ public class SmsCommunicatorPlugin implements PluginBase { } break; case "BOLUS": - if (new Date().getTime() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) { + if (System.currentTimeMillis() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) { reply = MainApp.sResources.getString(R.string.smscommunicator_remotebolusnotallowed); sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); + } else if (MainApp.getConfigBuilder().isSuspended()) { + 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); @@ -460,12 +459,15 @@ public class SmsCommunicatorPlugin implements PluginBase { break; default: // expect passCode here if (bolusWaitingForConfirmation != null && !bolusWaitingForConfirmation.processed && - bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - bolusWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - bolusWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { bolusWaitingForConfirmation.processed = true; PumpInterface pumpInterface = MainApp.getConfigBuilder(); if (pumpInterface != null) { - danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.deliverTreatment(ConfigBuilderPlugin.getActiveInsulin(), bolusWaitingForConfirmation.bolusRequested, 0, null); + danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = bolusWaitingForConfirmation.bolusRequested; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = pumpInterface.deliverTreatment(detailedBolusInfo); if (result.success) { reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered); if (danaRPlugin != null) @@ -480,12 +482,12 @@ public class SmsCommunicatorPlugin implements PluginBase { } } } else if (tempBasalWaitingForConfirmation != null && !tempBasalWaitingForConfirmation.processed && - tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - tempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - tempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { tempBasalWaitingForConfirmation.processed = true; PumpInterface pumpInterface = MainApp.getConfigBuilder(); if (pumpInterface != null) { - danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30); + danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); + PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, false); if (result.success) { reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); if (danaRPlugin != null) @@ -499,12 +501,12 @@ public class SmsCommunicatorPlugin implements PluginBase { } } } else if (cancelTempBasalWaitingForConfirmation != null && !cancelTempBasalWaitingForConfirmation.processed && - cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - cancelTempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - cancelTempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { cancelTempBasalWaitingForConfirmation.processed = true; PumpInterface pumpInterface = MainApp.getConfigBuilder(); if (pumpInterface != null) { - danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); - PumpEnactResult result = pumpInterface.cancelTempBasal(); + danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class); + PumpEnactResult result = pumpInterface.cancelTempBasal(true); if (result.success) { reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled); if (danaRPlugin != null) @@ -518,7 +520,7 @@ public class SmsCommunicatorPlugin implements PluginBase { } } } else if (calibrationWaitingForConfirmation != null && !calibrationWaitingForConfirmation.processed && - calibrationWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - calibrationWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + calibrationWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - calibrationWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { calibrationWaitingForConfirmation.processed = true; boolean result = XdripCalibrations.sendIntent(calibrationWaitingForConfirmation.calibrationRequested); if (result) { @@ -529,13 +531,13 @@ public class SmsCommunicatorPlugin implements PluginBase { sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date())); } } else if (suspendWaitingForConfirmation != null && !suspendWaitingForConfirmation.processed && - suspendWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - suspendWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + suspendWaitingForConfirmation.confirmCode.equals(splited[0]) && System.currentTimeMillis() - suspendWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { suspendWaitingForConfirmation.processed = true; final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); - activeloop.suspendTo(new Date().getTime() + suspendWaitingForConfirmation.duration * 60L * 1000); - PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(); - ConfigBuilderPlugin.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); - MainApp.bus().post(new EventRefreshGui(false)); + activeloop.suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000); + PumpEnactResult result = MainApp.getConfigBuilder().cancelTempBasal(true); + NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); + MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " + MainApp.sResources.getString(result.success?R.string.smscommunicator_tempbasalcanceled:R.string.smscommunicator_tempbasalcancelfailed); sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date())); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/Events/EventNewSMS.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java similarity index 100% rename from app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/Events/EventNewSMS.java rename to app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/events/EventNewSMS.java 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 deleted file mode 100644 index 63ab27deee..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpFragment.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.SourceGlimp; - - -import android.support.v4.app.Fragment; - -public class SourceGlimpFragment extends Fragment { - - private static SourceGlimpPlugin sourceGlimpPlugin = new SourceGlimpPlugin(); - - public static SourceGlimpPlugin getPlugin() { - return 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 3c1248c4de..0f914feddc 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 @@ -4,7 +4,6 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment; /** * Created by mike on 05.08.2016. @@ -12,9 +11,17 @@ import info.nightscout.androidaps.plugins.SourceMM640g.SourceMM640gFragment; public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { boolean fragmentEnabled = false; + static SourceGlimpPlugin plugin = null; + + public static SourceGlimpPlugin getPlugin() { + if (plugin == null) + plugin = new SourceGlimpPlugin(); + return plugin; + } + @Override public String getFragmentClass() { - return SourceGlimpFragment.class.getName(); + return null; } @Override 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 deleted file mode 100644 index 28bfabf813..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gFragment.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.SourceMM640g; - - -import android.support.v4.app.Fragment; - -public class SourceMM640gFragment extends Fragment { - - private static SourceMM640gPlugin sourceMM640gPlugin = new SourceMM640gPlugin(); - - public static SourceMM640gPlugin getPlugin() { - return 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 df8111b5cd..6276b97f25 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 @@ -4,7 +4,6 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; /** * Created by mike on 05.08.2016. @@ -12,9 +11,17 @@ import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { boolean fragmentEnabled = false; + static SourceMM640gPlugin plugin = null; + + public static SourceMM640gPlugin getPlugin() { + if (plugin == null) + plugin = new SourceMM640gPlugin(); + return plugin; + } + @Override public String getFragmentClass() { - return SourceMM640gFragment.class.getName(); + return null; } @Override 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 deleted file mode 100644 index b2eddc09fc..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientFragment.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.SourceNSClient; - - -import android.support.v4.app.Fragment; - -public class SourceNSClientFragment extends Fragment { - - private static SourceNSClientPlugin sourceNSClientPlugin = new SourceNSClientPlugin(); - - public static SourceNSClientPlugin getPlugin() { - return 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 db11ab4ea5..a10d0d1d1e 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; @@ -11,9 +12,17 @@ import info.nightscout.androidaps.interfaces.PluginBase; public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { boolean fragmentEnabled = true; + static SourceNSClientPlugin plugin = null; + + public static SourceNSClientPlugin getPlugin() { + if (plugin == null) + plugin = new SourceNSClientPlugin(); + return plugin; + } + @Override public String getFragmentClass() { - return SourceNSClientFragment.class.getName(); + return null; } @Override @@ -35,7 +44,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public boolean isEnabled(int type) { - return type == BGSOURCE && fragmentEnabled; + return Config.NSCLIENT || type == BGSOURCE && fragmentEnabled; } @Override @@ -55,7 +64,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public boolean showInList(int type) { - return true; + return !Config.NSCLIENT; } @Override 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 deleted file mode 100644 index c9be1298d2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripFragment.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.androidaps.plugins.SourceXdrip; - - -import android.support.v4.app.Fragment; - -public class SourceXdripFragment extends Fragment { - - private static SourceXdripPlugin sourceXdripPlugin = new SourceXdripPlugin(); - - public static SourceXdripPlugin getPlugin() { - return 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 b32040a2e8..6d214dc028 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 @@ -4,16 +4,23 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment; /** * Created by mike on 05.08.2016. */ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { + static SourceXdripPlugin plugin = null; + + public static SourceXdripPlugin getPlugin() { + if (plugin == null) + plugin = new SourceXdripPlugin(); + return plugin; + } + @Override public String getFragmentClass() { - return SourceNSClientFragment.class.getName(); + return null; } private static boolean fragmentEnabled = false; 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 cbc018278a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsPlugin.java +++ /dev/null @@ -1,279 +0,0 @@ -package info.nightscout.androidaps.plugins.TempBasals; - -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.data.IobTotal; -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.utils.SP; - -/** - * 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() { - useExtendedBoluses = SP.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 boolean hasFragment() { - return true; - } - - @Override - public boolean showInList(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; - } - - public 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() < now) { - t.timeEnd = new Date(t.getPlannedTimeEnd()); - 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())); - 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); - 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(time); - //log.debug("BasalIOB " + new Date(time) + " >>> " + calc.basaliob); - 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(time); - 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) { - if (s.isChanged("danar_useextended")) { - useExtendedBoluses = SP.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 63592f7878..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempTargetRange/TempTargetRangePlugin.java +++ /dev/null @@ -1,124 +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 = false; - 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 boolean hasFragment() { - return true; - } - - @Override - public boolean showInList(int type) { - return true; - } - - @Override - public void setFragmentEnabled(int type, boolean fragmentEnabled) { - if (type == GENERAL) { - this.fragmentEnabled = fragmentEnabled; - } - } - - @Override - public void setFragmentVisible(int type, boolean fragmentVisible) { - if (type == GENERAL) this.fragmentVisible = fragmentVisible; - } - - 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 e4442dde0f..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,24 @@ 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.InsulinInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.utils.DateUtil; -import info.nightscout.utils.DecimalFormatter; -import info.nightscout.utils.SP; -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 { private static Logger log = LoggerFactory.getLogger(TreatmentsFragment.class); @@ -54,201 +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); - return new TreatmentsViewHolder(v); - } - - @Override - public void onBindViewHolder(TreatmentsViewHolder holder, int position) { - if (MainApp.getConfigBuilder() == null || ConfigBuilderPlugin.getActiveProfile() == null) // app not initialized yet - return; - NSProfile profile = ConfigBuilderPlugin.getActiveProfile().getProfile(); - InsulinInterface insulinInterface = ConfigBuilderPlugin.getActiveInsulin(); - if (profile == null || insulinInterface == 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 = insulinInterface.iobCalc(treatments.get(position), new Date().getTime(), 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(); - 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("RemoveTreatment")); - } - }); - 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: - boolean nsUploadOnly = SP.getBoolean(R.string.key_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 d0ba64f124..0f5a6c582e 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,29 +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.Intervals; +import info.nightscout.androidaps.data.NonOverlappingIntervals; +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.TempTarget; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.InsulinInterface; +import info.nightscout.androidaps.events.EventReloadProfileSwitchData; +import info.nightscout.androidaps.events.EventReloadTempBasalData; +import info.nightscout.androidaps.events.EventReloadTreatmentData; +import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.SP; /** @@ -32,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 Intervals tempBasals = new NonOverlappingIntervals(); + private static Intervals extendedBoluses = new NonOverlappingIntervals(); + private static Intervals tempTargets = new OverlappingIntervals(); + private static ProfileIntervals profiles = new ProfileIntervals<>(); private static boolean fragmentEnabled = true; private static boolean fragmentVisible = true; @@ -83,7 +100,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { @Override public boolean showInList(int type) { - return true; + return !Config.NSCLIENT; } @Override @@ -103,76 +120,116 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { public TreatmentsPlugin() { MainApp.bus().register(this); - initializeData(); + initializeTempBasalData(); + initializeTreatmentData(); + initializeExtendedBolusData(); + initializeTempTargetData(); + initializeProfileSwitchData(); } - public void initializeData() { - double dia = Constants.defaultDIA; - 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)); + public static void initializeTreatmentData() { + // Treatments + double dia = MainApp.getConfigBuilder() == null ? Constants.defaultDIA : MainApp.getConfigBuilder().getProfile().getDia(); + long fromMills = (long) (System.currentTimeMillis() - 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) (System.currentTimeMillis() - 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) (System.currentTimeMillis() - 60 * 60 * 1000L * (24 + dia)); + + extendedBoluses.reset().add(MainApp.getDbHelper().getExtendedBolusDataFromTime(fromMills, false)); + + } + + public void initializeTempTargetData() { + long fromMills = System.currentTimeMillis() - 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(); - InsulinInterface insulinInterface = MainApp.getConfigBuilder().getActiveInsulin(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return total; - Double dia = profile.getDia(); + double dia = profile.getDia(); for (Integer pos = 0; pos < treatments.size(); pos++) { Treatment t = treatments.get(pos); - if (t.created_at.getTime() > time) continue; - Iob tIOB = insulinInterface.iobCalc(t, time, dia); + if (!t.isValid) continue; + if (t.date > time) continue; + Iob tIOB = t.iobCalc(time, dia); total.iob += tIOB.iobContrib; total.activity += tIOB.activityContrib; - Iob bIOB = insulinInterface.iobCalc(t, time, dia / SP.getInt("openapsama_bolussnooze_dia_divisor", 2)); - total.bolussnooze += bIOB.iobContrib; + if (!t.isSMB) { + // instead of dividing the DIA that only worked on the bilinear curves, + // multiply the time the treatment is seen active. + long timeSinceTreatment = time - t.date; + long snoozeTime = t.date + (long)(timeSinceTreatment * SP.getDouble("openapsama_bolussnooze_dia_divisor", 2.0)); + Iob bIOB = t.iobCalc(snoozeTime, dia); + total.bolussnooze += bIOB.iobContrib; + } else { + total.basaliob += t.insulin; + total.microBolusIOB += tIOB.iobContrib; + } } + + if (!MainApp.getConfigBuilder().isFakingTempsByExtendedBoluses()) + synchronized (extendedBoluses) { + 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(System.currentTimeMillis()); - lastCalculationTimestamp = new Date().getTime(); - lastCalculation = total; + lastTreatmentCalculation = total; } @Override public MealData getMealData() { MealData result = new MealData(); - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); + Profile profile = MainApp.getConfigBuilder().getProfile(); if (profile == null) return result; - long now = new Date().getTime(); + long now = System.currentTimeMillis(); long dia_ago = now - (new Double(1.5d * profile.getDia() * 60 * 60 * 1000l)).longValue(); for (Treatment treatment : treatments) { - long t = treatment.created_at.getTime(); + if (!treatment.isValid) + continue; + long t = treatment.date; if (t > dia_ago && t <= now) { if (treatment.carbs >= 1) { result.carbs += treatment.carbs; @@ -191,25 +248,254 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { } @Override - public List getTreatments() { + public List getTreatmentsFromHistory() { return treatments; } @Override - public List getTreatments5MinBack(long time) { + public List getTreatments5MinBackFromHistory(long time) { List in5minback = new ArrayList<>(); for (Integer pos = 0; pos < treatments.size(); pos++) { Treatment t = treatments.get(pos); - if (t.created_at.getTime() <= time && t.created_at.getTime() > time - 5 * 60 * 1000) + if (!t.isValid) + continue; + if (t.date <= time && t.date > time - 5 * 60 * 1000 && t.carbs > 0) in5minback.add(t); } return in5minback; } - @Subscribe - public void onStatusEvent(final EventTreatmentChange ev) { - initializeData(); - updateTotalIOB(); + @Override + public boolean isInHistoryRealTempBasalInProgress() { + return getRealTempBasalFromHistory(System.currentTimeMillis()) != null; } + @Override + public TemporaryBasal getRealTempBasalFromHistory(long time) { + return (TemporaryBasal) tempBasals.getValueByInterval(time); + } + + @Override + public boolean isTempBasalInProgress() { + return getTempBasalFromHistory(System.currentTimeMillis()) != null; + } + + @Override + public boolean isInHistoryExtendedBoluslInProgress() { + return getExtendedBolusFromHistory(System.currentTimeMillis()) != 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); + synchronized (tempBasals) { + 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); + synchronized (extendedBoluses) { + 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(System.currentTimeMillis()); + + 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 Intervals getExtendedBolusesFromHistory() { + return extendedBoluses; + } + + @Override + public double getTempBasalAbsoluteRateHistory() { + PumpInterface pump = MainApp.getConfigBuilder(); + + TemporaryBasal tb = getTempBasalFromHistory(System.currentTimeMillis()); + if (tb != null) { + if (tb.isFakeExtended){ + double baseRate = pump.getBaseBasalRate(); + double tempRate = baseRate + tb.netExtendedRate; + return tempRate; + } else 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(System.currentTimeMillis()).getPlannedRemainingMinutes(); + return 0; + } + + @Override + public Intervals 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(); + treatment.date = detailedBolusInfo.date; + treatment.source = detailedBolusInfo.source; + treatment.pumpId = detailedBolusInfo.pumpId; + treatment.insulin = detailedBolusInfo.insulin; + treatment.isValid = detailedBolusInfo.isValid; + treatment.isSMB = detailedBolusInfo.isSMB; + 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(); + 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 = System.currentTimeMillis(); + synchronized (tempBasals) { + if (tempBasals.size() > 0) + oldestTime = Math.min(oldestTime, tempBasals.get(0).date); + } + synchronized (extendedBoluses) { + if (extendedBoluses.size() > 0) + oldestTime = Math.min(oldestTime, extendedBoluses.get(0).date); + } + synchronized (treatments) { + 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 Intervals getTempTargetsFromHistory() { + return tempTargets; + } + + // Profile Switch + @Subscribe + public void onStatusEvent(final EventReloadProfileSwitchData 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/ProfileViewerDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileViewerDialog.java new file mode 100644 index 0000000000..b4461eabb7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/ProfileViewerDialog.java @@ -0,0 +1,108 @@ +package info.nightscout.androidaps.plugins.Treatments.fragments; + +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.db.ProfileSwitch; +import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; + +/** + * Created by adrian on 17/08/17. + */ + +public class ProfileViewerDialog extends DialogFragment { + + private long time; + + private static Logger log = LoggerFactory.getLogger(ProfileViewDialog.class); + + private TextView noProfile; + private TextView units; + private TextView dia; + private TextView activeProfile; + private TextView ic; + private TextView isf; + private TextView basal; + private TextView target; + private View dateDelimiter; + private LinearLayout dateLayout; + private TextView dateTextView; + private Button refreshButton; + + static ProfileViewerDialog newInstance(long time) { + ProfileViewerDialog dialog = new ProfileViewerDialog(); + + Bundle args = new Bundle(); + args.putLong("time", time); + dialog.setArguments(args); + + return dialog; + } + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + time = getArguments().getLong("time"); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View layout = inflater.inflate(R.layout.nsprofileviewer_fragment, container, false); + + noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile); + units = (TextView) layout.findViewById(R.id.profileview_units); + dia = (TextView) layout.findViewById(R.id.profileview_dia); + activeProfile = (TextView) layout.findViewById(R.id.profileview_activeprofile); + ic = (TextView) layout.findViewById(R.id.profileview_ic); + isf = (TextView) layout.findViewById(R.id.profileview_isf); + basal = (TextView) layout.findViewById(R.id.profileview_basal); + target = (TextView) layout.findViewById(R.id.profileview_target); + refreshButton = (Button) layout.findViewById(R.id.profileview_reload); + refreshButton.setVisibility(View.GONE); + dateDelimiter = layout.findViewById(R.id.profileview_datedelimiter); + dateDelimiter.setVisibility(View.VISIBLE); + dateLayout = (LinearLayout) layout.findViewById(R.id.profileview_datelayout); + dateLayout.setVisibility(View.VISIBLE); + dateTextView = (TextView) layout.findViewById(R.id.profileview_date); + + setContent(); + return layout; + } + + private void setContent() { + Profile profile = null; + ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(time); + if(profileSwitch!=null && profileSwitch.profileJson != null){ + profile = profileSwitch.getProfileObject(); + } + if (profile != null) { + noProfile.setVisibility(View.GONE); + units.setText(profile.getUnits()); + dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h"); + activeProfile.setText(profileSwitch.profileName); + dateTextView.setText(DateUtil.dateAndTimeString(profileSwitch.date)); + ic.setText(profile.getIcList()); + isf.setText(profile.getIsfList()); + basal.setText(profile.getBasalList()); + target.setText(profile.getTargetList()); + } else { + noProfile.setVisibility(View.VISIBLE); + } + } +} 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..b47cd3a6bf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java @@ -0,0 +1,243 @@ +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.Common.SubscriberFragment; +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 SubscriberFragment 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(System.currentTimeMillis(), 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); + holder.invalid.setVisibility(t.isValid ? View.GONE : View.VISIBLE); + 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; + TextView invalid; + + 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); + invalid = (TextView) itemView.findViewById(R.id.invalid_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 (treatment.source == Source.PUMP) { + treatment.isValid = false; + MainApp.getDbHelper().update(treatment); + } else { + 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; + } + } + + @Subscribe + public void onStatusEvent(final EventTreatmentChange ev) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + @Override + protected 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..eb3bd49d89 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java @@ -0,0 +1,207 @@ +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 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.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.androidaps.data.Intervals; + + +public class TreatmentsExtendedBolusesFragment extends SubscriberFragment { + private static Logger log = LoggerFactory.getLogger(TreatmentsExtendedBolusesFragment.class); + + RecyclerView recyclerView; + LinearLayoutManager llm; + + Context context; + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + Intervals extendedBolusList; + + RecyclerViewAdapter(Intervals 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(System.currentTimeMillis()); + 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(System.currentTimeMillis()).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; + } + + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + updateGUI(); + } + + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + @Override + protected 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..fc9d836b8b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java @@ -0,0 +1,218 @@ +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.app.FragmentManager; +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.androidaps.plugins.Common.SubscriberFragment; +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 SubscriberFragment 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); + holder.name.setTag(profileSwitch); + holder.date.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); + name.setOnClickListener(this); + date.setOnClickListener(this); + + } + + @Override + public void onClick(View v) { + final ProfileSwitch profileSwitch = (ProfileSwitch) v.getTag(); + switch (v.getId()) { + case R.id.profileswitch_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(profileSwitch.date)); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = profileSwitch._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeCareportalEntryFromNS(_id); + } + MainApp.getDbHelper().delete(profileSwitch); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + case R.id.profileswitch_date: + case R.id.profileswitch_name: + long time = ((ProfileSwitch)v.getTag()).date; + ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(time); + FragmentManager manager = getFragmentManager(); + pvd.show(manager, "ProfileViewDialog"); + 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; + } + } + + @Subscribe + public void onStatusEvent(final EventProfileSwitchChange ev) { + updateGUI(); + } + + @Override + protected 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 60% 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 9222a9a819..9e3836e118 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.plugins.ConfigBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; +import info.nightscout.androidaps.events.EventTempTargetChange; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.androidaps.data.Intervals; import info.nightscout.utils.SP; -import info.nightscout.utils.ToastUtils; /** * Created by mike on 13/01/17. */ -public class TempTargetRangeFragment extends Fragment implements View.OnClickListener { - - private static TempTargetRangePlugin tempTargetRangePlugin = new TempTargetRangePlugin(); - - public static TempTargetRangePlugin getPlugin() { - return tempTargetRangePlugin; - } +public class TreatmentsTempTargetFragment extends SubscriberFragment implements View.OnClickListener { RecyclerView recyclerView; LinearLayoutManager llm; @@ -59,32 +47,35 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis public class RecyclerViewAdapter extends RecyclerView.Adapter { - List tempTargetList; + Intervals tempTargetList; + TempTarget currentlyActiveTarget; - RecyclerViewAdapter(List TempTargetList) { + RecyclerViewAdapter(Intervals TempTargetList) { this.tempTargetList = TempTargetList; + currentlyActiveTarget = tempTargetList.getValueByInterval(System.currentTimeMillis()); } @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(); - 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"); - holder.low.setText(tempTarget.lowValueToUnitsToString(profile.getUnits())); - holder.high.setText(tempTarget.highValueToUnitsToString(profile.getUnits())); + String units = MainApp.getConfigBuilder().getProfileUnits(); + 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(units)); + holder.high.setText(tempTarget.highValueToUnitsToString(units)); 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(""); @@ -92,10 +83,18 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis holder.reasonLabel.setText(""); holder.reasonColon.setText(""); } - if (tempTarget.isInProgress()) - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress)); - else - holder.dateLinearLayout.setBackgroundColor(ContextCompat.getColor(MainApp.instance(), R.color.cardColorBackground)); + if (tempTarget.isInProgress()) { + if(tempTarget == currentlyActiveTarget){ + // active as newest + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress)); + } else { + // other's that might become active again after the latest (overlapping) is over + holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + } + } + else { + holder.date.setTextColor(holder.reasonColon.getCurrentTextColor()); + } holder.remove.setTag(tempTarget); } @@ -119,7 +118,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,34 +131,28 @@ 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 public void onClick(View v) { final TempTarget tempTarget = (TempTarget) v.getTag(); - final Context finalContext = context; switch (v.getId()) { 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 +166,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 +181,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,53 +193,36 @@ public class TempTargetRangeFragment extends Fragment implements View.OnClickLis public void onClick(View view) { switch (view.getId()) { case R.id.temptargetrange_refreshfromnightscout: - boolean nsUploadOnly = SP.getBoolean(R.string.key_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 - public void onPause() { - super.onPause(); - MainApp.bus().unregister(this); - } - - @Override - public void onResume() { - super.onResume(); - MainApp.bus().register(this); } @Subscribe - public void onStatusEvent(final EventTempTargetRangeChange ev) { + public void onStatusEvent(final EventTempTargetChange ev) { updateGUI(); } - void updateGUI() { + @Override + protected void updateGUI() { Activity activity = getActivity(); if (activity != null) 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/TempBasals/TempBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java similarity index 56% rename from app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java rename to app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java index 1bd43719de..9127bf1e7a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/TempBasals/TempBasalsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.TempBasals; +package info.nightscout.androidaps.plugins.Treatments.fragments; import android.app.Activity; import android.content.Context; @@ -14,7 +14,6 @@ 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.crashlytics.android.answers.Answers; @@ -24,26 +23,22 @@ 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.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; +import info.nightscout.utils.NSUpload; +import info.nightscout.androidaps.data.Intervals; -public class TempBasalsFragment extends Fragment { - private static Logger log = LoggerFactory.getLogger(TempBasalsFragment.class); - - private static TempBasalsPlugin tempBasalsPlugin = new TempBasalsPlugin(); - - public static TempBasalsPlugin getPlugin() { - return tempBasalsPlugin; - } +public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { + private static Logger log = LoggerFactory.getLogger(TreatmentsTemporaryBasalsFragment.class); RecyclerView recyclerView; LinearLayoutManager llm; @@ -54,48 +49,64 @@ public class TempBasalsFragment extends Fragment { public class RecyclerViewAdapter extends RecyclerView.Adapter { - List tempBasalList; + Intervals tempBasalList; - RecyclerViewAdapter(List tempBasalList) { + RecyclerViewAdapter(Intervals 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); + 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) { - 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 { + 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(DecimalFormatter.to0Decimal(tempBasal.percent) + "%"); + 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(System.currentTimeMillis()); + 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(System.currentTimeMillis()).basaliob != 0) + holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); + else + holder.iob.setTextColor(holder.netRatio.getCurrentTextColor()); } - 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); - 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().getTime()).basaliob != 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(tempBasal); } @@ -120,8 +131,9 @@ public class TempBasalsFragment extends Fragment { TextView netInsulin; TextView iob; TextView extendedFlag; - LinearLayout dateLinearLayout; TextView remove; + TextView ph; + TextView ns; TempBasalsViewHolder(View itemView) { super(itemView); @@ -135,7 +147,8 @@ public class TempBasalsFragment extends Fragment { 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); + 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); @@ -143,22 +156,19 @@ public class TempBasalsFragment extends Fragment { @Override public void onClick(View v) { - final TempBasal tempBasal = (TempBasal) v.getTag(); + 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.timeStart)); + 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) { - // TODO: handle this in NS too - //final String _id = tempBasal._id; - //if (_id != null && !_id.equals("")) { - // MainApp.getConfigBuilder().removeCareportalEntryFromNS(_id); - //} + final String _id = tempBasal._id; + if (_id != null && !_id.equals("")) { + NSUpload.removeCareportalEntryFromNS(_id); + } MainApp.getDbHelper().delete(tempBasal); - tempBasalsPlugin.initializeData(); - updateGUI(); Answers.getInstance().logCustom(new CustomEvent("RemoveTempBasal")); } }); @@ -173,14 +183,14 @@ public class TempBasalsFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.tempbasals_fragment, container, false); + 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(tempBasalsPlugin.getMergedList()); + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getConfigBuilder().getTemporaryBasalsFromHistory()); recyclerView.setAdapter(adapter); tempBasalTotalView = (TextView) view.findViewById(R.id.tempbasals_totaltempiob); @@ -191,32 +201,26 @@ public class TempBasalsFragment extends Fragment { 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() { + @Subscribe + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + @Override + protected void updateGUI() { Activity activity = getActivity(); - if (activity != null && recyclerView != null) + if (activity != 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"; + 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 682073d42f..e60e30d158 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,28 +4,42 @@ 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.DateFormat; import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; +import java.util.LinkedList; +import java.util.List; import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.db.DanaRHistoryRecord; +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.DanaRInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog; +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.TempTargetRange.TempTargetRangePlugin; -import info.nightscout.androidaps.plugins.TempTargetRange.events.EventTempTargetRangeChange; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; +import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; +import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; +import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; +import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin; import info.nightscout.utils.BolusWizard; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -46,13 +60,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 +128,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 +157,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,16 +166,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])){ - rTitle += " TARGETS"; - rMessage = getTargetsStatus(); + rMessage = "TARGETS:\n" + getTargetsStatus(); + rMessage += "\n\n" + getLoopStatus(); + rMessage += "\n\nOAPS RESULT:\n" + getOAPSResultStatus(); } } else if ("wizard".equals(act[0])) { @@ -173,41 +181,44 @@ 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]); + int percentage = Integer.parseInt(act[5]); - 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, percentage, 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,15 +227,103 @@ 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"; + if(percentage != 100){ + rMessage += "\nPercentage: " +format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U"; + } lastBolusWizard = bolusWizard; - } else return; + } else if("opencpp".equals(act[0])){ + Object activeProfile = MainApp.getConfigBuilder().getActiveProfileInterface(); + CircadianPercentageProfilePlugin cpp = MainApp.getSpecificPlugin(CircadianPercentageProfilePlugin.class); + + if(cpp == null || activeProfile==null || cpp != activeProfile){ + sendError("CPP not activated!"); + return; + } else { + // read CPP values + rTitle = "opencpp"; + rMessage = "opencpp"; + rAction = "opencpp" + " " + cpp.getPercentage() + " " + cpp.getTimeshift(); + } + + } else if("cppset".equals(act[0])){ + Object activeProfile = MainApp.getConfigBuilder().getActiveProfileInterface(); + CircadianPercentageProfilePlugin cpp = MainApp.getSpecificPlugin(CircadianPercentageProfilePlugin.class); + + if(cpp == null || activeProfile==null || cpp != activeProfile){ + sendError("CPP not activated!"); + return; + } else { + // read CPP values + rMessage = "CPP:" + "\n\n"+ + "Timeshift: " + act[1] + "\n" + + "Percentage: " + act[2] + "%"; + rAction = actionstring; + } + + } else if("tddstats".equals(act[0])){ + Object activePump = MainApp.getConfigBuilder().getActivePump(); + PumpInterface dana = MainApp.getSpecificPlugin(DanaRPlugin.class); + PumpInterface danaV2 = MainApp.getSpecificPlugin(DanaRv2Plugin.class); + PumpInterface danaKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class); + + + if((dana == null || dana != activePump) && + (danaV2 == null || danaV2 != activePump) && + (danaKorean == null || danaKorean != activePump) + ){ + sendError("Pump does not support TDDs!"); + return; + } else { + // check if DB up to date + List dummies = new LinkedList(); + List historyList = getTDDList(dummies); + + if(isOldData(historyList)){ + rTitle = "TDD"; + rAction = "statusmessage"; + rMessage = "OLD DATA - "; + + //if pump is not busy: try to fetch data + final PumpInterface pump = MainApp.getConfigBuilder().getActivePump(); + if (pump.isBusy()) { + rMessage += MainApp.instance().getString(R.string.pumpbusy); + } else { + rMessage += "trying to fetch data from pump."; + Handler handler = new Handler(handlerThread.getLooper()); + handler.post(new Runnable() { + @Override + public void run() { + ((DanaRInterface)pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY); + List dummies = new LinkedList(); + List historyList = getTDDList(dummies); + if(isOldData(historyList)){ + sendStatusmessage("TDD", "TDD: Still old data! Cannot load from pump."); + } else { + sendStatusmessage("TDD", generateTDDMessage(historyList, dummies)); + } + } + }); + } + } else { + // if up to date: prepare, send (check if CPP is activated -> add CPP stats) + rTitle = "TDD"; + rAction = "statusmessage"; + rMessage = generateTDDMessage(historyList, dummies); + } + } + + } + else return; + // send result WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation(rTitle, rMessage, rAction); @@ -232,6 +331,98 @@ public class ActionStringHandler { lastConfirmActionString = rAction; } + private static String generateTDDMessage(List historyList, List dummies) { + + DateFormat df = new SimpleDateFormat("dd.MM."); + String message = ""; + + CircadianPercentageProfilePlugin cpp = MainApp.getSpecificPlugin(CircadianPercentageProfilePlugin.class); + boolean isCPP = (cpp!= null && cpp.isEnabled(PluginBase.PROFILE)); + double refTDD = 100; + if(isCPP) refTDD = cpp.baseBasalSum()*2; + + int i = 0; + double sum = 0d; + double weighted03 = 0d; + double weighted05 = 0d; + double weighted07 = 0d; + + Collections.reverse(historyList); + 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++; + } + message += "weighted:\n"; + message += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (isCPP?(DecimalFormatter.to0Decimal(100*weighted03/refTDD) + "%"):"") + "\n"; + message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (isCPP?(DecimalFormatter.to0Decimal(100*weighted05/refTDD) + "%"):"") + "\n"; + message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (isCPP?(DecimalFormatter.to0Decimal(100*weighted07/refTDD) + "%"):"") + "\n"; + message += "\n"; + + PumpInterface pump = MainApp.getConfigBuilder().getActivePump(); + if (pump != null && pump instanceof DanaRPlugin) { + double tdd = DanaRPump.getInstance().dailyTotalUnits; + message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (isCPP?(DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%"):"") + "\n"; + message += "\n"; + } + + //add TDDs: + Collections.reverse(historyList); + for (DanaRHistoryRecord record : historyList) { + double tdd = record.recordDailyBolus + record.recordDailyBasal; + message += df.format(new Date(record.recordDate)) + " " + DecimalFormatter.to2Decimal(tdd) +"U " + (isCPP?(DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%"):"") + (dummies.contains(record)?"x":"") +"\n"; + } + return message; + } + + public static boolean isOldData(List historyList) { + DateFormat df = new SimpleDateFormat("dd.MM."); + return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).recordDate)).equals(df.format(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24))))); + } + + @NonNull + public static List getTDDList(List returnDummies) { + List historyList = MainApp.getDbHelper().getDanaRHistoryRecordsByType(RecordTypes.RECORD_TYPE_DAILY); + + //only use newest 10 + historyList = historyList.subList(0, Math.min(10, historyList.size())); + + //fill single gaps + List dummies = (returnDummies!=null)?returnDummies:(new LinkedList()); + DateFormat df = new SimpleDateFormat("dd.MM."); + for(int i = 0; i < historyList.size()-1; i++){ + DanaRHistoryRecord elem1 = historyList.get(i); + DanaRHistoryRecord elem2 = historyList.get(i+1); + + if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25*60*60*1000)))){ + DanaRHistoryRecord dummy = new DanaRHistoryRecord(); + dummy.recordDate = elem1.recordDate - 24*60*60*1000; + dummy.recordDailyBasal = elem1.recordDailyBasal/2; + dummy.recordDailyBolus = elem1.recordDailyBolus/2; + dummies.add(dummy); + elem1.recordDailyBasal /= 2; + elem1.recordDailyBolus /= 2; + } + } + historyList.addAll(dummies); + Collections.sort(historyList, new Comparator() { + @Override + public int compare(DanaRHistoryRecord lhs, DanaRHistoryRecord rhs) { + return (int) (rhs.recordDate-lhs.recordDate); + } + }); + return historyList; + } + @NonNull private static String getPumpStatus() { return MainApp.getConfigBuilder().shortStatus(false); @@ -242,25 +433,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,44 +461,66 @@ 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(System.currentTimeMillis()); + if (tempTarget != null) { + ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.low, tempTarget.low, Constants.MGDL, profile.getUnits()); + ret += "\nuntil: " + DateUtil.timeString(tempTarget.originalEnd()); + ret += "\n\n"; } - //Default Range/Target - Double maxBgDefault = Constants.MAX_BG_DEFAULT_MGDL; - Double minBgDefault = Constants.MIN_BG_DEFAULT_MGDL; - Double targetBgDefault = Constants.TARGET_BG_DEFAULT_MGDL; - if (!profile.getUnits().equals(Constants.MGDL)) { - maxBgDefault = Constants.MAX_BG_DEFAULT_MMOL; - minBgDefault = Constants.MIN_BG_DEFAULT_MMOL; - targetBgDefault = Constants.TARGET_BG_DEFAULT_MMOL; - } ret += "DEFAULT RANGE: "; - ret += SP.getDouble("openapsma_min_bg", minBgDefault) + " - " + SP.getDouble("openapsma_max_bg", maxBgDefault); - ret += " target: " + SP.getDouble("openapsma_target_bg", targetBgDefault); + ret += profile.getTargetLow() + " - " + profile.getTargetHigh(); + ret += " target: " + (profile.getTargetLow() + profile.getTargetHigh()) / 2; + return ret; + } + + private static String getOAPSResultStatus() { + String ret = ""; + if (!Config.APS) { + return "Only apply in APS mode!"; + } + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (profile == null) { + return "No profile set :("; + } + + APSInterface usedAPS = MainApp.getConfigBuilder().getActiveAPS(); + if (usedAPS == null) { + return "No active APS :(!"; + } + + APSResult result = usedAPS.getLastAPSResult(); + if (result == null) { + return "Last result not available!"; + } + + if (!result.changeRequested) { + ret += MainApp.sResources.getString(R.string.nochangerequested) + "\n"; + } else if (result.rate == 0 && result.duration == 0) { + ret += MainApp.sResources.getString(R.string.canceltemp)+ "\n"; + } else { + ret += MainApp.sResources.getString(R.string.rate) + ": " + DecimalFormatter.to2Decimal(result.rate) + " U/h " + + "(" + DecimalFormatter.to2Decimal(result.rate / MainApp.getConfigBuilder().getBaseBasalRate() * 100) + "%)\n" + + MainApp.sResources.getString(R.string.duration) + ": " + DecimalFormatter.to0Decimal(result.duration) + " min\n"; + } + ret += "\n" + MainApp.sResources.getString(R.string.reason) + ": " + result.reason; + return ret; } - 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 +532,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 +546,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); @@ -348,34 +560,51 @@ public class ActionStringHandler { double insulin = SafeParse.stringToDouble(act[1]); int carbs = SafeParse.stringToInt(act[2]); doBolus(insulin, carbs); + } else if ("cppset".equals(act[0])) { + int timeshift = SafeParse.stringToInt(act[1]); + int percentage = SafeParse.stringToInt(act[2]); + setCPP(percentage, timeshift); + } else if ("dismissoverviewnotification".equals(act[0])){ + MainApp.bus().post(new EventDismissNotification(SafeParse.stringToInt(act[1]))); } lastBolusWizard = null; } + private static void setCPP(int percentage, int timeshift) { + Object activeProfile = MainApp.getConfigBuilder().getActiveProfileInterface(); + CircadianPercentageProfilePlugin cpp = MainApp.getSpecificPlugin(CircadianPercentageProfilePlugin.class); + + if(cpp == null || activeProfile==null || cpp != activeProfile){ + sendError("CPP not activated!"); + return; + } + String msg = cpp.externallySetParameters(timeshift, percentage); + if(msg != null && !"".equals(msg)){ + String rTitle = "STATUS"; + String rAction = "statusmessage"; + WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation(rTitle, msg, rAction); + lastSentTimestamp = System.currentTimeMillis(); + lastConfirmActionString = rAction; + } + } + private static void generateTempTarget(int duration, double low, double high) { TempTarget tempTarget = new TempTarget(); - tempTarget.timeStart = new Date(); - tempTarget.duration = duration; + tempTarget.date = System.currentTimeMillis(); + 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 +613,13 @@ public class ActionStringHandler { handler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), amount, 0, null, false); + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = amount; + detailedBolusInfo.isValid = false; + detailedBolusInfo.source = Source.USER; + PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(detailedBolusInfo); if (!result.success) { - sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + + sendError(MainApp.sResources.getString(R.string.treatmentdeliveryerror) + "\n" + result.comment); } @@ -400,9 +633,13 @@ public class ActionStringHandler { handler.post(new Runnable() { @Override public void run() { - PumpEnactResult result = MainApp.getConfigBuilder().deliverTreatment(MainApp.getConfigBuilder().getActiveInsulin(), 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,10 +647,25 @@ 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; lastBolusWizard = null; } + + private synchronized static void sendStatusmessage(String title, String message) { + WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation(title, message, "statusmessage"); + lastSentTimestamp = System.currentTimeMillis(); + lastConfirmActionString = null; + lastBolusWizard = null; + } + + public synchronized static void expectNotificationAction(String message, int id) { + String actionstring = "dismissoverviewnotification " + id; + WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation("DISMISS", message, actionstring); + lastSentTimestamp = System.currentTimeMillis(); + lastConfirmActionString = actionstring; + lastBolusWizard = null; + } } 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 9508908c84..c115819f0d 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 @@ -9,19 +9,19 @@ 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; -import info.nightscout.androidaps.events.EventRefreshGui; +import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogressIfRunning; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.Wear.wearintegration.WatchUpdaterService; -import info.nightscout.utils.ToastUtils; +import info.nightscout.utils.SP; /** * Created by adrian on 17/11/16. @@ -149,6 +149,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); @@ -160,7 +165,7 @@ public class WearPlugin implements PluginBase { } @Subscribe - public void onStatusEvent(final EventRefreshGui ev) { + public void onStatusEvent(final EventRefreshOverview ev) { LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); if (activeloop == null) return; @@ -224,5 +229,10 @@ public class WearPlugin implements PluginBase { watchUS = null; } + public void overviewNotification(int id, String message) { + if(SP.getBoolean("wear_overview_notification", false)){ + ActionStringHandler.expectNotificationAction(message, id); + } + } } 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 2a2ef68156..93a85686b3 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 @@ -19,6 +19,9 @@ import com.google.android.gms.wearable.PutDataRequest; import com.google.android.gms.wearable.Wearable; import com.google.android.gms.wearable.WearableListenerService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -27,16 +30,19 @@ 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.ProfileCircadianPercentage.CircadianPercentageProfilePlugin; 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; @@ -66,11 +72,13 @@ 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; + private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfilePlugin.class); + + @Override public void onCreate() { mPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); @@ -93,7 +101,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) @@ -129,15 +139,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 { @@ -167,13 +176,13 @@ public class WatchUpdaterService extends WearableListenerService implements if (event != null && event.getPath().equals(WEARABLE_INITIATE_ACTIONSTRING_PATH)) { String actionstring = new String(event.getData()); - ToastUtils.showToastInUiThread(this, "Wear: " + actionstring); + log.debug("Wear: " + actionstring); ActionStringHandler.handleInitiate(actionstring); } if (event != null && event.getPath().equals(WEARABLE_CONFIRM_ACTIONSTRING_PATH)) { String actionstring = new String(event.getData()); - ToastUtils.showToastInUiThread(this, "Wear Confirm: " + actionstring); + log.debug("Wear Confirm: " + actionstring); ActionStringHandler.handleConfirmation(actionstring); } } @@ -186,15 +195,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; } @@ -205,24 +216,23 @@ public class WatchUpdaterService extends WearableListenerService implements } private DataMap dataMapSingleBG(BgReading lastBG, GlucoseStatus glucoseStatus) { - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if(profile == null) return null; + String units = MainApp.getConfigBuilder().getProfileUnits(); 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 (!units.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,20 +245,20 @@ public class WatchUpdaterService extends WearableListenerService implements DataMap dataMap = new DataMap(); int battery = getBatteryLevel(getApplicationContext()); - dataMap.putString("sgvString", lastBG.valueToUnitsToString(profile.getUnits())); - dataMap.putDouble("timestamp", lastBG.getTimeIndex()); - if(glucoseStatus == null) { - dataMap.putString("slopeArrow", "" ); + dataMap.putString("sgvString", lastBG.valueToUnitsToString(units)); + dataMap.putDouble("timestamp", lastBG.date); + if (glucoseStatus == null) { + dataMap.putString("slopeArrow", ""); dataMap.putString("delta", ""); dataMap.putString("avgDelta", ""); } else { dataMap.putString("slopeArrow", slopeArrow(glucoseStatus.delta)); - dataMap.putString("delta", deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, profile.getUnits())); - dataMap.putString("avgDelta", deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, profile.getUnits())); + dataMap.putString("delta", deltastring(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)); + dataMap.putString("avgDelta", deltastring(glucoseStatus.avgdelta, glucoseStatus.avgdelta * Constants.MGDL_TO_MMOLL, units)); } 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); @@ -257,33 +267,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"; @@ -292,25 +301,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); } } @@ -322,47 +333,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); + status += " " + ((bgi >= 0) ? "+" : "") + DecimalFormatter.to2Decimal(bgi); return status; } @@ -583,7 +596,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); } @@ -591,9 +604,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 deleted file mode 100644 index ba2cbc0783..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslineFragment.java +++ /dev/null @@ -1,29 +0,0 @@ -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 index a0555682e0..45b5867886 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/XDripStatusline/StatuslinePlugin.java @@ -9,19 +9,21 @@ import android.support.annotation.NonNull; import com.squareup.otto.Subscribe; +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.TempBasal; +import info.nightscout.androidaps.data.Profile; +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.EventRefreshOverview; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSProfile; import info.nightscout.utils.DecimalFormatter; /** @@ -42,6 +44,17 @@ public class StatuslinePlugin implements PluginBase { private final Context ctx; SharedPreferences mPrefs; + private static StatuslinePlugin statuslinePlugin; + + public static StatuslinePlugin getPlugin(Context ctx) { + + if (statuslinePlugin == null) { + statuslinePlugin = new StatuslinePlugin(ctx); + } + + return statuslinePlugin; + } + StatuslinePlugin(Context ctx) { this.ctx = ctx; this.mPrefs = PreferenceManager.getDefaultSharedPreferences(ctx); @@ -54,7 +67,7 @@ public class StatuslinePlugin implements PluginBase { @Override public String getFragmentClass() { - return StatuslineFragment.class.getName(); + return null; } @Override @@ -95,7 +108,7 @@ public class StatuslinePlugin implements PluginBase { @Override public boolean showInList(int type) { - return true; + return !Config.NSCLIENT; } @Override @@ -106,13 +119,14 @@ public class StatuslinePlugin implements PluginBase { if (fragmentEnabled) { try { MainApp.bus().register(this); - } catch (Exception e) {} + } catch (Exception e) { + } sendStatus(); - } - else{ + } else { try { MainApp.bus().unregister(this); - } catch (Exception e) {} + } catch (Exception e) { + } sendStatus(); } } @@ -127,9 +141,9 @@ public class StatuslinePlugin implements PluginBase { private void sendStatus() { - String status = ""; // sent once on disable + String status = ""; // sent once on disable - if(fragmentEnabled) { + if (fragmentEnabled) { status = buildStatusString(); } @@ -146,8 +160,6 @@ public class StatuslinePlugin implements PluginBase { @NonNull private String buildStatusString() { String status = ""; - boolean shortString = true; // make setting? - LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); if (activeloop != null && !activeloop.isEnabled(PluginBase.LOOP)) { @@ -158,23 +170,20 @@ public class StatuslinePlugin implements PluginBase { } //Temp basal - PumpInterface pump = MainApp.getConfigBuilder(); + TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder(); + + if (treatmentsInterface.isTempBasalInProgress()) { + TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis()); + status += activeTemp.toStringShort(); - if (pump.isTempBasalInProgress()) { - TempBasal activeTemp = pump.getTempBasal(); - if (shortString) { - status += activeTemp.toStringShort(); - } else { - status += activeTemp.toStringMedium(); - } } //IOB - MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB(); - IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round(); - MainApp.getConfigBuilder().getActiveTempBasals().updateTotalIOB(); - IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round(); - status += (shortString ? "" : (ctx.getString(R.string.treatments_iob_label_string) + " ")) + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob); + treatmentsInterface.updateTotalIOBTreatments(); + IobTotal bolusIob = treatmentsInterface.getLastCalculationTreatments().round(); + treatmentsInterface.updateTotalIOBTempBasals(); + IobTotal basalIob = treatmentsInterface.getLastCalculationTempBasals().round(); + status += DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob); if (mPrefs.getBoolean("xdripstatus_detailediob", true)) { @@ -182,14 +191,14 @@ public class StatuslinePlugin implements PluginBase { + DecimalFormatter.to2Decimal(bolusIob.iob) + "|" + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")"; } - NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - if (!mPrefs.getBoolean("xdripstatus_showbgi", false) ||profile == null || profile.getIsf(NSProfile.secondsFromMidnight()) == null || profile.getIc(NSProfile.secondsFromMidnight()) == null) { + Profile profile = MainApp.getConfigBuilder().getProfile(); + if (!mPrefs.getBoolean("xdripstatus_showbgi", false)) { return status; } - double bgi = -(bolusIob.activity + basalIob.activity)*5*profile.getIsf(NSProfile.secondsFromMidnight()); + double bgi = -(bolusIob.activity + basalIob.activity) * 5 * profile.getIsf(); - status += " " + ((bgi>=0)?"+":"") + DecimalFormatter.to2Decimal(bgi); + status += " " + ((bgi >= 0) ? "+" : "") + DecimalFormatter.to2Decimal(bgi); return status; } @@ -211,13 +220,18 @@ public class StatuslinePlugin implements PluginBase { sendStatus(); } + @Subscribe + public void onStatusEvent(final EventExtendedBolusChange ev) { + sendStatus(); + } + @Subscribe public void onStatusEvent(final EventNewBG ev) { sendStatus(); } @Subscribe - public void onStatusEvent(final EventRefreshGui ev) { + public void onStatusEvent(final EventRefreshOverview ev) { //Filter events where loop is (de)activated 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..e3c77d0122 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()) + if (lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) 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/receivers/NSAlarmReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java new file mode 100644 index 0000000000..bff2e6695a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/receivers/NSAlarmReceiver.java @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import org.json.JSONException; +import org.json.JSONObject; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.Services.Intents; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSAlarm; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; + +public class NSAlarmReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null) + return; + Bundle bundle = intent.getExtras(); + String data = bundle.getString("data"); + JSONObject json = null; + try { + json = new JSONObject(data); + } catch (JSONException e) { + e.printStackTrace(); + return; + } + NSAlarm nsAlarm = new NSAlarm(json); + switch (intent.getAction()) { + case Intents.ACTION_ANNOUNCEMENT: + case Intents.ACTION_ALARM: + case Intents.ACTION_URGENT_ALARM: + Notification notification = new Notification(nsAlarm); + if (notification.isEnabled()) + MainApp.bus().post(new EventNewNotification(notification)); + break; + case Intents.ACTION_CLEAR_ALARM: + MainApp.bus().post(new EventDismissNotification(Notification.NSALARM)); + MainApp.bus().post(new EventDismissNotification(Notification.NSURGENTALARM)); + break; + } + } +} 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/TabPageAdapter.java b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java index 0ec2921a14..8dff2aec93 100644 --- a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java @@ -20,12 +20,10 @@ public class TabPageAdapter extends FragmentStatePagerAdapter { ArrayList visibleFragmentList = new ArrayList<>(); - FragmentManager fm; Context context; public TabPageAdapter(FragmentManager fm, Context context) { super(fm); - this.fm = fm; this.context = context; } @@ -61,7 +59,7 @@ public class TabPageAdapter extends FragmentStatePagerAdapter { } public void registerNewFragment(PluginBase plugin) { - if (plugin.isVisibleInTabs(plugin.getType())) { + if (plugin.hasFragment() && 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 f9d3748f3a..f4eb4907ef 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; @@ -51,9 +47,14 @@ public class BolusWizard { // Result public Double calculatedTotalInsulin = 0d; + public Double totalBeforePercentageAdjustment = 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) { + return doCalc(specificProfile, carbs, cob, bg, correction, 100d, includeBolusIOB, includeBasalIOB, superBolus, trend); + } + + public Double doCalc(Profile specificProfile, Integer carbs, Double cob, Double bg, Double correction, double percentageCorrection, Boolean includeBolusIOB, Boolean includeBasalIOB, Boolean superBolus, Boolean trend) { this.specificProfile = specificProfile; this.carbs = carbs; this.bg = bg; @@ -61,12 +62,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 { @@ -77,25 +77,21 @@ public class BolusWizard { // Insulin from 15 min trend glucoseStatus = GlucoseStatus.getGlucoseStatusData(); if (glucoseStatus != null && trend) { - insulinFromTrend = (NSProfile.fromMgdlToUnits(glucoseStatus.short_avgdelta, profile.getUnits()) * 3) / sens; + 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; // 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,21 +101,28 @@ public class BolusWizard { // Insulin from superbolus for 2h. Get basal rate now and after 1h if (superBolus) { - insulinFromSuperBolus = profile.getBasal(NSProfile.secondsFromMidnight()); - long timeAfter1h = new Date().getTime(); + insulinFromSuperBolus = specificProfile.getBasal(); + long timeAfter1h = System.currentTimeMillis(); timeAfter1h += 60L * 60 * 1000; - insulinFromSuperBolus += profile.getBasal(NSProfile.secondsFromMidnight(new Date(timeAfter1h))); + insulinFromSuperBolus += specificProfile.getBasal(timeAfter1h); } // Total - calculatedTotalInsulin = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulingFromBolusIOB + insulingFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB; + calculatedTotalInsulin = totalBeforePercentageAdjustment = insulinFromBG + insulinFromTrend + insulinFromCarbs + insulingFromBolusIOB + insulingFromBasalsIOB + insulinFromCorrection + insulinFromSuperBolus + insulinFromCOB; + + //percentage + if(totalBeforePercentageAdjustment > 0){ + calculatedTotalInsulin = totalBeforePercentageAdjustment*percentageCorrection/100d; + } + if (calculatedTotalInsulin < 0) { carbsEquivalent = -calculatedTotalInsulin * ic; calculatedTotalInsulin = 0d; } - calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, 0.05d); + double bolusStep = MainApp.getConfigBuilder().getPumpDescription().bolusStep; + calculatedTotalInsulin = Round.roundTo(calculatedTotalInsulin, bolusStep); return calculatedTotalInsulin; } diff --git a/app/src/main/java/info/nightscout/utils/BundleLogger.java b/app/src/main/java/info/nightscout/utils/BundleLogger.java new file mode 100644 index 0000000000..ba6ffff869 --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/BundleLogger.java @@ -0,0 +1,21 @@ +package info.nightscout.utils; + +import android.os.Bundle; + +/** + * Created by mike on 14.08.2017. + */ + +public class BundleLogger { + public static String log(Bundle bundle) { + if (bundle == null) { + return null; + } + String string = "Bundle{"; + for (String key : bundle.keySet()) { + string += " " + key + " => " + bundle.get(key) + ";"; + } + string += " }Bundle"; + return string; + } +} diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/utils/DateUtil.java index c4efa45f93..bf2c1ba1fd 100644 --- a/app/src/main/java/info/nightscout/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/utils/DateUtil.java @@ -3,6 +3,7 @@ package info.nightscout.utils; import android.text.format.DateUtils; import java.text.DateFormat; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -12,6 +13,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; /** * The Class DateUtil. A simple wrapper around SimpleDateFormat to ease the handling of iso date string <-> date obj @@ -23,6 +25,7 @@ public class DateUtil { * The date format in iso. */ public static String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + public static String FORMAT_DATE_ISO_MSEC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; /** * Takes in an ISO date string of the following format: @@ -35,8 +38,15 @@ public class DateUtil { public static Date fromISODateString(String isoDateString) throws Exception { SimpleDateFormat f = new SimpleDateFormat(FORMAT_DATE_ISO); + Date date; f.setTimeZone(TimeZone.getTimeZone("UTC")); - Date date = f.parse(isoDateString); + try { + date = f.parse(isoDateString); + } catch (ParseException e) { + f = new SimpleDateFormat(FORMAT_DATE_ISO_MSEC); + f.setTimeZone(TimeZone.getTimeZone("UTC")); + date = f.parse(isoDateString); + } return date; } @@ -75,12 +85,16 @@ public class DateUtil { } public static int toSeconds(String hh_colon_mm) { - Pattern p = Pattern.compile("(\\d+):(\\d+)"); + Pattern p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.|)"); Matcher m = p.matcher(hh_colon_mm); int retval = 0; if (m.find()) { retval = SafeParse.stringToInt(m.group(1)) * 60 * 60 + SafeParse.stringToInt(m.group(2)) * 60; + if (m.group(3).equals(" .a.m") && m.group(1).equals("12")) + retval -= 12 * 60 * 60; + if (m.group(3).equals(" p.m.") && !m.group(1).equals("12")) + retval += 12 * 60 * 60; } return retval; } @@ -111,4 +125,10 @@ public class DateUtil { public static String dateAndTimeString(long mills) { return dateString(mills) + " " + timeString(mills); } + + public static String minAgo(long time) { + int mins = (int) ((System.currentTimeMillis() - time) / 1000 / 60); + return String.format(MainApp.sResources.getString(R.string.minago), mins); + } + } \ No newline at end of file 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..09ecbc9370 --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -0,0 +1,407 @@ +package info.nightscout.utils; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; +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", "openaps://" + MainApp.instance().getString(R.string.app_name)); + 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", "openaps://" + 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 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", "openaps://" + MainApp.instance().getString(R.string.app_name)); + 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", "openaps://" + 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", "openaps://" + 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() > System.currentTimeMillis() - 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://" + Build.MANUFACTURER + " " + Build.MODEL; + 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); + data.put("isSMB", detailedBolusInfo.isSMB); + 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 + 1000L); + 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", "openaps://" + 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/NumberPicker.java b/app/src/main/java/info/nightscout/utils/NumberPicker.java new file mode 100644 index 0000000000..ce960cbe7a --- /dev/null +++ b/app/src/main/java/info/nightscout/utils/NumberPicker.java @@ -0,0 +1,248 @@ +package info.nightscout.utils; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.NumberFormat; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; + +/** + * Created by mike on 28.06.2016. + */ +public class NumberPicker extends LinearLayout implements View.OnKeyListener, + View.OnTouchListener, View.OnClickListener { + private static Logger log = LoggerFactory.getLogger(NumberPicker.class); + + TextView editText; + Button minusButton; + Button plusButton; + + Double value; + Double minValue = 0d; + Double maxValue = 1d; + Double step = 1d; + NumberFormat formater; + boolean allowZero = false; + + private Handler mHandler; + private ScheduledExecutorService mUpdater; + + private class UpdateCounterTask implements Runnable { + private boolean mInc; + private int repeated = 0; + private int multiplier = 1; + + private final int doubleLimit = 5; + + public UpdateCounterTask(boolean inc) { + mInc = inc; + } + + public void run() { + Message msg = new Message(); + if (repeated % doubleLimit == 0) multiplier *= 2; + repeated++; + msg.arg1 = multiplier; + msg.arg2 = repeated; + if (mInc) { + msg.what = MSG_INC; + } else { + msg.what = MSG_DEC; + } + mHandler.sendMessage(msg); + } + } + + private static final int MSG_INC = 0; + private static final int MSG_DEC = 1; + + public NumberPicker(Context context) { + super(context, null); + } + + public NumberPicker(Context context, AttributeSet attrs) { + super(context, attrs); + + this.initialize(context, attrs); + } + + public NumberPicker(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs) { + // set layout view + LayoutInflater.from(context).inflate(R.layout.number_picker_layout, this, true); + + // init ui components + this.minusButton = (Button) findViewById(R.id.decrement); + this.plusButton = (Button) findViewById(R.id.increment); + this.editText = (EditText) findViewById(R.id.display); + + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_INC: + inc(msg.arg1); + return; + case MSG_DEC: + dec(msg.arg1); + return; + } + super.handleMessage(msg); + } + }; + + minusButton.setOnTouchListener(this); + minusButton.setOnKeyListener(this); + minusButton.setOnClickListener(this); + plusButton.setOnTouchListener(this); + plusButton.setOnKeyListener(this); + plusButton.setOnClickListener(this); + } + + public void removeTextChangedListener(TextWatcher textWatcher) { + editText.removeTextChangedListener(textWatcher); + } + + public void addTextChangedListener(TextWatcher textWatcher) { + editText.addTextChangedListener(textWatcher); + } + + public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, TextWatcher textWatcher) { + setParams(initValue, minValue, maxValue, step, formater, allowZero); + editText.addTextChangedListener(textWatcher); + } + + public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero) { + this.value = initValue; + this.minValue = minValue; + this.maxValue = maxValue; + this.step = step; + this.formater = formater; + this.allowZero = allowZero; + + updateEditText(); + } + + public void setValue(Double value) { + this.value = value; + updateEditText(); + } + + public Double getValue() { + return value; + } + + public String getText() { + return editText.getText().toString(); + } + + public void setStep(Double step) { + this.step = step; + } + + private void inc(int multiplier) { + value += step * multiplier; + if (value > maxValue) { + value = maxValue; + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.youareonallowedlimit)); + stopUpdating(); + } + updateEditText(); + } + + private void dec( int multiplier) { + value -= step * multiplier; + if (value < minValue) { + value = minValue; + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.youareonallowedlimit)); + stopUpdating(); + } + updateEditText(); + } + + private void updateEditText() { + if (value == 0d && !allowZero) + editText.setText(""); + else + editText.setText(formater.format(value)); + } + + private void startUpdating(boolean inc) { + if (mUpdater != null) { + log.debug("Another executor is still active"); + return; + } + mUpdater = Executors.newSingleThreadScheduledExecutor(); + mUpdater.scheduleAtFixedRate(new UpdateCounterTask(inc), 200, 200, + TimeUnit.MILLISECONDS); + } + + private void stopUpdating() { + if (mUpdater != null) { + mUpdater.shutdownNow(); + mUpdater = null; + } + } + + @Override + public void onClick(View v) { + if (mUpdater == null) { + if (v == plusButton) { + inc(1); + } else { + dec(1); + } + } + } + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + boolean isKeyOfInterest = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER; + boolean isReleased = event.getAction() == KeyEvent.ACTION_UP; + boolean isPressed = event.getAction() == KeyEvent.ACTION_DOWN + && event.getAction() != KeyEvent.ACTION_MULTIPLE; + + if (isKeyOfInterest && isReleased) { + stopUpdating(); + } else if (isKeyOfInterest && isPressed) { + startUpdating(v == plusButton); + } + return false; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + boolean isReleased = event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL; + boolean isPressed = event.getAction() == MotionEvent.ACTION_DOWN; + + if (isReleased) { + stopUpdating(); + } else if (isPressed) { + startUpdating(v == plusButton); + } + return false; + } + +} diff --git a/app/src/main/java/info/nightscout/utils/OKDialog.java b/app/src/main/java/info/nightscout/utils/OKDialog.java index 19fbe7c62a..72e0ddd8d2 100644 --- a/app/src/main/java/info/nightscout/utils/OKDialog.java +++ b/app/src/main/java/info/nightscout/utils/OKDialog.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.DialogInterface; import android.support.v7.app.AlertDialog; import android.support.v7.view.ContextThemeWrapper; +import android.text.Spanned; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,4 +42,28 @@ public class OKDialog { log.debug("show_dialog exception: " + e); } } + + public static void show(final Activity activity, String title, Spanned message, final Runnable runnable) { + try { + AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(activity, R.style.AppTheme)); + builder.setTitle(title); + builder.setMessage(message); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + if (runnable != null) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + activity.runOnUiThread(runnable); + } + } + }); + + builder.create().show(); + } catch (Exception e) { + log.debug("show_dialog exception: " + e); + } + } } diff --git a/app/src/main/java/info/nightscout/utils/OverlappingIntervals.java b/app/src/main/java/info/nightscout/utils/OverlappingIntervals.java deleted file mode 100644 index 6711d941c4..0000000000 --- a/app/src/main/java/info/nightscout/utils/OverlappingIntervals.java +++ /dev/null @@ -1,145 +0,0 @@ -package info.nightscout.utils; - -import android.os.Handler; -import android.os.HandlerThread; -import android.support.annotation.Nullable; -import android.support.v4.util.LongSparseArray; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by mike on 09.05.2017. - */ - -public class OverlappingIntervals { - - private Handler sHandler = null; - private HandlerThread sHandlerThread = null; - private Object dataLock = new Object(); - - - public abstract class Interval { - Long start = null; - Long duration = null; - Long cuttedEnd = null; - - public Interval(long start, long duration) { - this.start = start; - this.duration = duration; - } - - long durationInMsec() { - return duration; - } - - long start() { - return start; - } - - // planned end time at time of creation - long originalEnd() { - return start + duration; - } - - // end time after cut - long end() { - if (cuttedEnd != null) - return cuttedEnd; - return originalEnd(); - } - - void cutEndTo(long end) { - cuttedEnd = end; - } - - boolean match(long time) { - if (start() <= time && end() >= time) - return true; - return false; - } - - boolean before(long time) { - if (end() < time) - return true; - return false; - } - - boolean after(long time) { - if (start() > time) - return true; - return false; - } - } - - private static LongSparseArray rawData = new LongSparseArray<>(); // oldest at index 0 - - public OverlappingIntervals() { - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(OverlappingIntervals.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } - } - - public OverlappingIntervals resetData() { - rawData = new LongSparseArray<>(); - return this; - } - - public void add(Interval newInterval) { - rawData.put(newInterval.start(), newInterval); - merge(); - } - - public void add(List list) { - for (Interval interval : list) { - rawData.put(interval.start(), interval); - } - merge(); - } - - private void merge() { - for (int index = 0; index < rawData.size() - 1; index++) { - Interval i = rawData.get(index); - long startOfNewer = rawData.get(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.get(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; - } - - private static 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 - } - -} 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/Profiler.java b/app/src/main/java/info/nightscout/utils/Profiler.java index 99093b238f..0410ad6ff8 100644 --- a/app/src/main/java/info/nightscout/utils/Profiler.java +++ b/app/src/main/java/info/nightscout/utils/Profiler.java @@ -12,7 +12,7 @@ public class Profiler { public Profiler(){} static public void log(Logger log, String function, Date start) { - long msec = new Date().getTime() - start.getTime(); + long msec = System.currentTimeMillis() - start.getTime(); log.debug(">>> " + function + " <<< executed in " + msec + " miliseconds"); } } diff --git a/app/src/main/java/info/nightscout/utils/Round.java b/app/src/main/java/info/nightscout/utils/Round.java index f1fe3e0df6..26a4d5abce 100644 --- a/app/src/main/java/info/nightscout/utils/Round.java +++ b/app/src/main/java/info/nightscout/utils/Round.java @@ -4,7 +4,7 @@ package info.nightscout.utils; * Created by mike on 20.06.2016. */ public class Round { - public static Double roundTo(Double x, Double step) { + public static Double roundTo(double x, Double step) { if (x != 0d) { return Math.round(x / 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..36ab3b05e7 100644 --- a/app/src/main/java/info/nightscout/utils/SP.java +++ b/app/src/main/java/info/nightscout/utils/SP.java @@ -49,11 +49,19 @@ public class SP { } static public int getInt(int resourceID, Integer defaultValue) { - return SafeParse.stringToInt(sharedPreferences.getString(MainApp.sResources.getString(resourceID), defaultValue.toString())); + try { + return sharedPreferences.getInt(MainApp.sResources.getString(resourceID), defaultValue); + } catch (Exception e) { + return SafeParse.stringToInt(sharedPreferences.getString(MainApp.sResources.getString(resourceID), defaultValue.toString())); + } } static public int getInt(String key, Integer defaultValue) { - return SafeParse.stringToInt(sharedPreferences.getString(key, defaultValue.toString())); + try { + return sharedPreferences.getInt(key, defaultValue); + } catch (Exception e) { + return SafeParse.stringToInt(sharedPreferences.getString(key, defaultValue.toString())); + } } static public long getLong(int resourceID, Long defaultValue) { @@ -80,27 +88,51 @@ public class SP { editor.apply(); } - static public void removeBoolean(int resourceID) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.remove(MainApp.sResources.getString(resourceID)); - editor.apply(); - } - static public void putLong(String key, long value) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putLong(key, value); editor.apply(); } + static public void putLong(int resourceID, long value) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putLong(MainApp.sResources.getString(resourceID), value); + editor.apply(); + } + + static public void putInt(String key, int value) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putInt(key, value); + editor.apply(); + } + + static public void putInt(int resourceID, int value) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putInt(MainApp.sResources.getString(resourceID), value); + editor.apply(); + } + static public void putString(int resourceID, String value) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(MainApp.sResources.getString(resourceID), value); editor.apply(); } - static public void removeString(int resourceID) { + static public void putString(String key, String value) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(key, value); + editor.apply(); + } + + static public void remove(int resourceID) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.remove(MainApp.sResources.getString(resourceID)); editor.apply(); } + + static public void remove(String key) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.remove(key); + editor.apply(); + } } diff --git a/app/src/main/java/info/nightscout/utils/SafeParse.java b/app/src/main/java/info/nightscout/utils/SafeParse.java index 8697daeebd..ff749f732b 100644 --- a/app/src/main/java/info/nightscout/utils/SafeParse.java +++ b/app/src/main/java/info/nightscout/utils/SafeParse.java @@ -11,6 +11,8 @@ public class SafeParse { public static Double stringToDouble(String input) { Double result = 0d; input = input.replace(",", "."); + if (input.equals("")) + return 0d; try { result = Double.parseDouble(input); } catch (Exception e) { @@ -22,6 +24,8 @@ public class SafeParse { public static Integer stringToInt(String input) { Integer result = 0; input = input.replace(",", "."); + if (input.equals("")) + return 0; try { result = Integer.parseInt(input); } catch (Exception e) { @@ -33,6 +37,8 @@ public class SafeParse { public static Long stringToLong(String input) { Long result = 0L; input = input.replace(",", "."); + if (input.equals("")) + return 0L; try { result = Long.parseLong(input); } catch (Exception e) { diff --git a/app/src/main/java/info/nightscout/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/utils/TimeListEdit.java index ce1f604060..2ad591b1ef 100644 --- a/app/src/main/java/info/nightscout/utils/TimeListEdit.java +++ b/app/src/main/java/info/nightscout/utils/TimeListEdit.java @@ -25,6 +25,7 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; @@ -285,12 +286,19 @@ public class TimeListEdit { public void editItem(int index, int timeAsSeconds, double value1, double value2) { try { + String time; + int hour = timeAsSeconds / 60 / 60; + DecimalFormat df = new DecimalFormat("00"); + time = df.format(hour) + ":00"; + JSONObject newObject1 = new JSONObject(); + newObject1.put("time", time); newObject1.put("timeAsSeconds", timeAsSeconds); newObject1.put("value", value1); data1.put(index, newObject1); if (data2 != null) { JSONObject newObject2 = new JSONObject(); + newObject1.put("time", time); newObject2.put("timeAsSeconds", timeAsSeconds); newObject2.put("value", value2); data2.put(index, newObject2); diff --git a/app/src/main/java/info/nightscout/utils/ToastUtils.java b/app/src/main/java/info/nightscout/utils/ToastUtils.java index dba4fb4202..4e1e4ac4ed 100644 --- a/app/src/main/java/info/nightscout/utils/ToastUtils.java +++ b/app/src/main/java/info/nightscout/utils/ToastUtils.java @@ -6,6 +6,10 @@ import android.os.Handler; import android.os.Looper; import android.widget.Toast; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.Overview.Notification; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; + public class ToastUtils { public static void showToastInUiThread(final Context ctx, @@ -25,6 +29,13 @@ public class ToastUtils { showToastInUiThread(ctx, string); playSound(ctx, soundID); + new Thread(new Runnable() { + @Override + public void run() { + Notification notification = new Notification(Notification.TOAST_ALARM, string, Notification.URGENT); + MainApp.bus().post(new EventNewNotification(notification)); + } + }).start(); } private static void playSound(final Context ctx, final int soundID) { diff --git a/app/src/main/java/info/nightscout/utils/XdripCalibrations.java b/app/src/main/java/info/nightscout/utils/XdripCalibrations.java index 53c3bf45ec..662b7a0c8f 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,13 +44,11 @@ public class XdripCalibrations { } public static boolean sendIntent(Double bg) { - final NSProfile profile = MainApp.getConfigBuilder().getActiveProfile().getProfile(); - Context context = MainApp.instance().getApplicationContext(); Bundle bundle = new Bundle(); bundle.putDouble("glucose_number", bg); - bundle.putString("units", profile.getUnits().equals(Constants.MGDL) ? "mgdl" : "mmol"); - bundle.putLong("timestamp", new Date().getTime()); + bundle.putString("units", MainApp.getConfigBuilder().getProfileUnits().equals(Constants.MGDL) ? "mgdl" : "mmol"); + bundle.putLong("timestamp", System.currentTimeMillis()); Intent intent = new Intent(Intents.ACTION_REMOTE_CALIBRATION); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); diff --git a/app/src/main/res/drawable-hdpi/background_darkgray.xml b/app/src/main/res/drawable-hdpi/background_darkgray.xml new file mode 100644 index 0000000000..4d5138556b --- /dev/null +++ b/app/src/main/res/drawable-hdpi/background_darkgray.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/border_gray.xml b/app/src/main/res/drawable-hdpi/border_gray.xml new file mode 100644 index 0000000000..c2792233ee --- /dev/null +++ b/app/src/main/res/drawable-hdpi/border_gray.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-hdpi/icon_actions_cancelextbolus.png b/app/src/main/res/drawable-hdpi/icon_actions_cancelextbolus.png new file mode 100644 index 0000000000..95761084a9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_actions_cancelextbolus.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_actions_profileswitch.png b/app/src/main/res/drawable-hdpi/icon_actions_profileswitch.png new file mode 100644 index 0000000000..4b36a0cc23 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_actions_profileswitch.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_actions_refill.png b/app/src/main/res/drawable-hdpi/icon_actions_refill.png new file mode 100644 index 0000000000..ace25d1558 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_actions_refill.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_actions_startextbolus.png b/app/src/main/res/drawable-hdpi/icon_actions_startextbolus.png new file mode 100644 index 0000000000..a67d52838c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_actions_startextbolus.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_actions_starttempbasal.png b/app/src/main/res/drawable-hdpi/icon_actions_starttempbasal.png new file mode 100644 index 0000000000..8772df62a4 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_actions_starttempbasal.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_actions_temptarget.png b/app/src/main/res/drawable-hdpi/icon_actions_temptarget.png new file mode 100644 index 0000000000..f839a6894b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_actions_temptarget.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_bolus.png b/app/src/main/res/drawable-hdpi/icon_bolus.png new file mode 100644 index 0000000000..b212194219 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_bolus.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_calculator.png b/app/src/main/res/drawable-hdpi/icon_calculator.png new file mode 100644 index 0000000000..2eb2a3b96c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_calculator.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_calibration.png b/app/src/main/res/drawable-hdpi/icon_calibration.png new file mode 100644 index 0000000000..605635f41d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_calibration.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cancelbasal.png b/app/src/main/res/drawable-hdpi/icon_cancelbasal.png new file mode 100644 index 0000000000..91803a3f3c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_aaps_offline.png b/app/src/main/res/drawable-hdpi/icon_cp_aaps_offline.png new file mode 100644 index 0000000000..0fe1cd628b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_aaps_offline.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_age_battery.png b/app/src/main/res/drawable-hdpi/icon_cp_age_battery.png new file mode 100644 index 0000000000..abc626901a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_age_battery.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_age_canula.png b/app/src/main/res/drawable-hdpi/icon_cp_age_canula.png new file mode 100644 index 0000000000..ecccc39426 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_age_canula.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_age_insulin.png b/app/src/main/res/drawable-hdpi/icon_cp_age_insulin.png new file mode 100644 index 0000000000..ab4d345881 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_age_insulin.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_age_sensor.png b/app/src/main/res/drawable-hdpi/icon_cp_age_sensor.png new file mode 100644 index 0000000000..30d5d02de0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_age_sensor.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_announcement.png b/app/src/main/res/drawable-hdpi/icon_cp_announcement.png new file mode 100644 index 0000000000..23c9a9847d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_announcement.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_basal_end.png b/app/src/main/res/drawable-hdpi/icon_cp_basal_end.png new file mode 100644 index 0000000000..b9cdf5cc1f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_basal_end.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_basal_start.png b/app/src/main/res/drawable-hdpi/icon_cp_basal_start.png new file mode 100644 index 0000000000..d79ca15f86 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_basal_start.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_bgcheck.png b/app/src/main/res/drawable-hdpi/icon_cp_bgcheck.png new file mode 100644 index 0000000000..56569a264a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_bgcheck.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_bolus_carbs.png b/app/src/main/res/drawable-hdpi/icon_cp_bolus_carbs.png new file mode 100644 index 0000000000..ed6be099aa Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_bolus_carbs.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_bolus_combo.png b/app/src/main/res/drawable-hdpi/icon_cp_bolus_combo.png new file mode 100644 index 0000000000..98c076905c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_bolus_combo.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_bolus_correction.png b/app/src/main/res/drawable-hdpi/icon_cp_bolus_correction.png new file mode 100644 index 0000000000..8ad7864406 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_bolus_correction.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_bolus_meal.png b/app/src/main/res/drawable-hdpi/icon_cp_bolus_meal.png new file mode 100644 index 0000000000..97dd4e2ed8 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_bolus_meal.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_bolus_snack.png b/app/src/main/res/drawable-hdpi/icon_cp_bolus_snack.png new file mode 100644 index 0000000000..710bf6e0da Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_bolus_snack.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_cgm_insert.png b/app/src/main/res/drawable-hdpi/icon_cp_cgm_insert.png new file mode 100644 index 0000000000..699be54792 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_cgm_insert.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_cgm_profile.png b/app/src/main/res/drawable-hdpi/icon_cp_cgm_profile.png new file mode 100644 index 0000000000..8887e60f27 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_cgm_profile.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_cgm_start.png b/app/src/main/res/drawable-hdpi/icon_cp_cgm_start.png new file mode 100644 index 0000000000..e917402c48 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_cgm_start.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_cgm_target.png b/app/src/main/res/drawable-hdpi/icon_cp_cgm_target.png new file mode 100644 index 0000000000..2cf826dad1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_cgm_target.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_exercise.png b/app/src/main/res/drawable-hdpi/icon_cp_exercise.png new file mode 100644 index 0000000000..e9aee1ac8a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_exercise.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_note.png b/app/src/main/res/drawable-hdpi/icon_cp_note.png new file mode 100644 index 0000000000..b6b752e150 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_note.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_pump_battery.png b/app/src/main/res/drawable-hdpi/icon_cp_pump_battery.png new file mode 100644 index 0000000000..b4a4f2923a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_pump_battery.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_pump_canula.png b/app/src/main/res/drawable-hdpi/icon_cp_pump_canula.png new file mode 100644 index 0000000000..e75d9ed81d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_pump_canula.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_pump_cartridge.png b/app/src/main/res/drawable-hdpi/icon_cp_pump_cartridge.png new file mode 100644 index 0000000000..f780c23e37 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_pump_cartridge.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_cp_question.png b/app/src/main/res/drawable-hdpi/icon_cp_question.png new file mode 100644 index 0000000000..65102f2abf Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_cp_question.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_home_loop.png b/app/src/main/res/drawable-hdpi/icon_home_loop.png new file mode 100644 index 0000000000..b0f9f6ea29 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_home_loop.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_home_profile.png b/app/src/main/res/drawable-hdpi/icon_home_profile.png new file mode 100644 index 0000000000..b288171332 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_home_profile.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_home_target.png b/app/src/main/res/drawable-hdpi/icon_home_target.png new file mode 100644 index 0000000000..0b2f2b166a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_home_target.png differ diff --git a/app/src/main/res/drawable-hdpi/icon_quickwizard.png b/app/src/main/res/drawable-hdpi/icon_quickwizard.png new file mode 100644 index 0000000000..67a020c05e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_quickwizard.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_actions_cancelextbolus.png b/app/src/main/res/drawable-mdpi/icon_actions_cancelextbolus.png new file mode 100644 index 0000000000..4ad378e374 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_actions_cancelextbolus.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_actions_profileswitch.png b/app/src/main/res/drawable-mdpi/icon_actions_profileswitch.png new file mode 100644 index 0000000000..eeae6ccfdb Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_actions_profileswitch.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_actions_refill.png b/app/src/main/res/drawable-mdpi/icon_actions_refill.png new file mode 100644 index 0000000000..737cca8b00 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_actions_refill.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_actions_startextbolus.png b/app/src/main/res/drawable-mdpi/icon_actions_startextbolus.png new file mode 100644 index 0000000000..338df773c2 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_actions_startextbolus.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_actions_starttempbasal.png b/app/src/main/res/drawable-mdpi/icon_actions_starttempbasal.png new file mode 100644 index 0000000000..18fbd8c111 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_actions_starttempbasal.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_actions_temptarget.png b/app/src/main/res/drawable-mdpi/icon_actions_temptarget.png new file mode 100644 index 0000000000..39170bab37 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_actions_temptarget.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_bolus.png b/app/src/main/res/drawable-mdpi/icon_bolus.png new file mode 100644 index 0000000000..c083219b45 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_bolus.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_calculator.png b/app/src/main/res/drawable-mdpi/icon_calculator.png new file mode 100644 index 0000000000..056722a440 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_calculator.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_calibration.png b/app/src/main/res/drawable-mdpi/icon_calibration.png new file mode 100644 index 0000000000..0929d3690d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_calibration.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cancelbasal.png b/app/src/main/res/drawable-mdpi/icon_cancelbasal.png new file mode 100644 index 0000000000..c48a20792d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_aaps_offline.png b/app/src/main/res/drawable-mdpi/icon_cp_aaps_offline.png new file mode 100644 index 0000000000..dc50653883 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_aaps_offline.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_age_battery.png b/app/src/main/res/drawable-mdpi/icon_cp_age_battery.png new file mode 100644 index 0000000000..6c7fc56139 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_age_battery.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_age_canula.png b/app/src/main/res/drawable-mdpi/icon_cp_age_canula.png new file mode 100644 index 0000000000..303ad946cd Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_age_canula.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_age_insulin.png b/app/src/main/res/drawable-mdpi/icon_cp_age_insulin.png new file mode 100644 index 0000000000..5cd8598faa Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_age_insulin.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_age_sensor.png b/app/src/main/res/drawable-mdpi/icon_cp_age_sensor.png new file mode 100644 index 0000000000..d312b6c572 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_age_sensor.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_announcement.png b/app/src/main/res/drawable-mdpi/icon_cp_announcement.png new file mode 100644 index 0000000000..6e1338ac24 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_announcement.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_basal_end.png b/app/src/main/res/drawable-mdpi/icon_cp_basal_end.png new file mode 100644 index 0000000000..be8474f002 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_basal_end.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_basal_start.png b/app/src/main/res/drawable-mdpi/icon_cp_basal_start.png new file mode 100644 index 0000000000..34cd31f14b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_basal_start.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_bgcheck.png b/app/src/main/res/drawable-mdpi/icon_cp_bgcheck.png new file mode 100644 index 0000000000..0cb14c2f57 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_bgcheck.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_bolus_carbs.png b/app/src/main/res/drawable-mdpi/icon_cp_bolus_carbs.png new file mode 100644 index 0000000000..561703fb06 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_bolus_carbs.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_bolus_combo.png b/app/src/main/res/drawable-mdpi/icon_cp_bolus_combo.png new file mode 100644 index 0000000000..ce4d8fb9d3 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_bolus_combo.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_bolus_correction.png b/app/src/main/res/drawable-mdpi/icon_cp_bolus_correction.png new file mode 100644 index 0000000000..582472dc92 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_bolus_correction.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_bolus_meal.png b/app/src/main/res/drawable-mdpi/icon_cp_bolus_meal.png new file mode 100644 index 0000000000..54b51e126e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_bolus_meal.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_bolus_snack.png b/app/src/main/res/drawable-mdpi/icon_cp_bolus_snack.png new file mode 100644 index 0000000000..b2ba41c27d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_bolus_snack.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_cgm_insert.png b/app/src/main/res/drawable-mdpi/icon_cp_cgm_insert.png new file mode 100644 index 0000000000..67c0fb1ba2 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_cgm_insert.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_cgm_profile.png b/app/src/main/res/drawable-mdpi/icon_cp_cgm_profile.png new file mode 100644 index 0000000000..e0f0a15cc8 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_cgm_profile.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_cgm_start.png b/app/src/main/res/drawable-mdpi/icon_cp_cgm_start.png new file mode 100644 index 0000000000..14a44bc852 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_cgm_start.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_cgm_target.png b/app/src/main/res/drawable-mdpi/icon_cp_cgm_target.png new file mode 100644 index 0000000000..86ce00442c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_cgm_target.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_exercise.png b/app/src/main/res/drawable-mdpi/icon_cp_exercise.png new file mode 100644 index 0000000000..1c92c0ebb5 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_exercise.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_note.png b/app/src/main/res/drawable-mdpi/icon_cp_note.png new file mode 100644 index 0000000000..7c8663a4fe Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_note.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_pump_battery.png b/app/src/main/res/drawable-mdpi/icon_cp_pump_battery.png new file mode 100644 index 0000000000..f4dab169a8 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_pump_battery.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_pump_canula.png b/app/src/main/res/drawable-mdpi/icon_cp_pump_canula.png new file mode 100644 index 0000000000..ee512c5fef Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_pump_canula.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_pump_cartridge.png b/app/src/main/res/drawable-mdpi/icon_cp_pump_cartridge.png new file mode 100644 index 0000000000..70a90c596f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_pump_cartridge.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_cp_question.png b/app/src/main/res/drawable-mdpi/icon_cp_question.png new file mode 100644 index 0000000000..5d430d9164 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_cp_question.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_home_loop.png b/app/src/main/res/drawable-mdpi/icon_home_loop.png new file mode 100644 index 0000000000..5240cc85db Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_home_loop.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_home_profile.png b/app/src/main/res/drawable-mdpi/icon_home_profile.png new file mode 100644 index 0000000000..f689df10c6 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_home_profile.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_home_target.png b/app/src/main/res/drawable-mdpi/icon_home_target.png new file mode 100644 index 0000000000..9fc7086e9d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_home_target.png differ diff --git a/app/src/main/res/drawable-mdpi/icon_quickwizard.png b/app/src/main/res/drawable-mdpi/icon_quickwizard.png new file mode 100644 index 0000000000..d65347f235 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/icon_quickwizard.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_actions_cancelextbolus.png b/app/src/main/res/drawable-xhdpi/icon_actions_cancelextbolus.png new file mode 100644 index 0000000000..8c4ee82d1e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_actions_cancelextbolus.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_actions_profileswitch.png b/app/src/main/res/drawable-xhdpi/icon_actions_profileswitch.png new file mode 100644 index 0000000000..57864f6ed5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_actions_profileswitch.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_actions_refill.png b/app/src/main/res/drawable-xhdpi/icon_actions_refill.png new file mode 100644 index 0000000000..ace20f3bfe Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_actions_refill.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_actions_startextbolus.png b/app/src/main/res/drawable-xhdpi/icon_actions_startextbolus.png new file mode 100644 index 0000000000..0e59f6ec36 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_actions_startextbolus.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_actions_starttempbasal.png b/app/src/main/res/drawable-xhdpi/icon_actions_starttempbasal.png new file mode 100644 index 0000000000..1deb6f3ca8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_actions_starttempbasal.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_actions_temptarget.png b/app/src/main/res/drawable-xhdpi/icon_actions_temptarget.png new file mode 100644 index 0000000000..c484837e53 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_actions_temptarget.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_bolus.png b/app/src/main/res/drawable-xhdpi/icon_bolus.png new file mode 100644 index 0000000000..a472289d6b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_bolus.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_calculator.png b/app/src/main/res/drawable-xhdpi/icon_calculator.png new file mode 100644 index 0000000000..9352f7b2a7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_calculator.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_calibration.png b/app/src/main/res/drawable-xhdpi/icon_calibration.png new file mode 100644 index 0000000000..98a24e4c78 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_calibration.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cancelbasal.png b/app/src/main/res/drawable-xhdpi/icon_cancelbasal.png new file mode 100644 index 0000000000..a6eb55c6cb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_aaps_offline.png b/app/src/main/res/drawable-xhdpi/icon_cp_aaps_offline.png new file mode 100644 index 0000000000..4239e40ba7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_aaps_offline.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_age_battery.png b/app/src/main/res/drawable-xhdpi/icon_cp_age_battery.png new file mode 100644 index 0000000000..3d75b9dc7a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_age_battery.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_age_canula.png b/app/src/main/res/drawable-xhdpi/icon_cp_age_canula.png new file mode 100644 index 0000000000..8629a7998d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_age_canula.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_age_insulin.png b/app/src/main/res/drawable-xhdpi/icon_cp_age_insulin.png new file mode 100644 index 0000000000..2e88ec9ad4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_age_insulin.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_age_sensor.png b/app/src/main/res/drawable-xhdpi/icon_cp_age_sensor.png new file mode 100644 index 0000000000..a3577da118 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_age_sensor.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_announcement.png b/app/src/main/res/drawable-xhdpi/icon_cp_announcement.png new file mode 100644 index 0000000000..472b51d775 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_announcement.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_basal_end.png b/app/src/main/res/drawable-xhdpi/icon_cp_basal_end.png new file mode 100644 index 0000000000..c92af22df3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_basal_end.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_basal_start.png b/app/src/main/res/drawable-xhdpi/icon_cp_basal_start.png new file mode 100644 index 0000000000..5e694ba89c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_basal_start.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_bgcheck.png b/app/src/main/res/drawable-xhdpi/icon_cp_bgcheck.png new file mode 100644 index 0000000000..030099f910 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_bgcheck.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_bolus_carbs.png b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_carbs.png new file mode 100644 index 0000000000..64815bc8f0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_carbs.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_bolus_combo.png b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_combo.png new file mode 100644 index 0000000000..908f33ccd8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_combo.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_bolus_correction.png b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_correction.png new file mode 100644 index 0000000000..0fe89d5f8b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_correction.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_bolus_meal.png b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_meal.png new file mode 100644 index 0000000000..52ef734adf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_meal.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_bolus_snack.png b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_snack.png new file mode 100644 index 0000000000..8d2e9690fc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_bolus_snack.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_cgm_insert.png b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_insert.png new file mode 100644 index 0000000000..af93321e3a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_insert.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_cgm_profile.png b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_profile.png new file mode 100644 index 0000000000..e4c50f2667 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_profile.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_cgm_start.png b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_start.png new file mode 100644 index 0000000000..ce23d1cf54 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_start.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_cgm_target.png b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_target.png new file mode 100644 index 0000000000..fbd5880490 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_cgm_target.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_exercise.png b/app/src/main/res/drawable-xhdpi/icon_cp_exercise.png new file mode 100644 index 0000000000..90cc102c07 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_exercise.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_note.png b/app/src/main/res/drawable-xhdpi/icon_cp_note.png new file mode 100644 index 0000000000..cf821a9d1f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_note.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_pump_battery.png b/app/src/main/res/drawable-xhdpi/icon_cp_pump_battery.png new file mode 100644 index 0000000000..15af2af396 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_pump_battery.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_pump_canula.png b/app/src/main/res/drawable-xhdpi/icon_cp_pump_canula.png new file mode 100644 index 0000000000..84ae19c4a3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_pump_canula.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_pump_cartridge.png b/app/src/main/res/drawable-xhdpi/icon_cp_pump_cartridge.png new file mode 100644 index 0000000000..d40a8540e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_pump_cartridge.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_cp_question.png b/app/src/main/res/drawable-xhdpi/icon_cp_question.png new file mode 100644 index 0000000000..43df04ef81 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_cp_question.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_loop.png b/app/src/main/res/drawable-xhdpi/icon_home_loop.png new file mode 100644 index 0000000000..09ebbed57f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_loop.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_profile.png b/app/src/main/res/drawable-xhdpi/icon_home_profile.png new file mode 100644 index 0000000000..95c0ca4502 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_profile.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_home_target.png b/app/src/main/res/drawable-xhdpi/icon_home_target.png new file mode 100644 index 0000000000..545ff5db79 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_home_target.png differ diff --git a/app/src/main/res/drawable-xhdpi/icon_quickwizard.png b/app/src/main/res/drawable-xhdpi/icon_quickwizard.png new file mode 100644 index 0000000000..b937f1448f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/icon_quickwizard.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_actions_cancelextbolus.png b/app/src/main/res/drawable-xxhdpi/icon_actions_cancelextbolus.png new file mode 100644 index 0000000000..d223d16d8f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_actions_cancelextbolus.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_actions_profileswitch.png b/app/src/main/res/drawable-xxhdpi/icon_actions_profileswitch.png new file mode 100644 index 0000000000..29e28afe02 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_actions_profileswitch.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_actions_refill.png b/app/src/main/res/drawable-xxhdpi/icon_actions_refill.png new file mode 100644 index 0000000000..45cc5d3e1a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_actions_refill.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_actions_startextbolus.png b/app/src/main/res/drawable-xxhdpi/icon_actions_startextbolus.png new file mode 100644 index 0000000000..e33b5e0a64 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_actions_startextbolus.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_actions_starttempbasal.png b/app/src/main/res/drawable-xxhdpi/icon_actions_starttempbasal.png new file mode 100644 index 0000000000..9e4aca67e2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_actions_starttempbasal.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_actions_temptarget.png b/app/src/main/res/drawable-xxhdpi/icon_actions_temptarget.png new file mode 100644 index 0000000000..4fa88421ae Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_actions_temptarget.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_bolus.png b/app/src/main/res/drawable-xxhdpi/icon_bolus.png new file mode 100644 index 0000000000..efa063d54d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_bolus.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_calculator.png b/app/src/main/res/drawable-xxhdpi/icon_calculator.png new file mode 100644 index 0000000000..18ab99e92b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_calculator.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_calibration.png b/app/src/main/res/drawable-xxhdpi/icon_calibration.png new file mode 100644 index 0000000000..3fd492a623 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_calibration.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cancelbasal.png b/app/src/main/res/drawable-xxhdpi/icon_cancelbasal.png new file mode 100644 index 0000000000..2bb5d6df09 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_aaps_offline.png b/app/src/main/res/drawable-xxhdpi/icon_cp_aaps_offline.png new file mode 100644 index 0000000000..1b4603bafc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_aaps_offline.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_age_battery.png b/app/src/main/res/drawable-xxhdpi/icon_cp_age_battery.png new file mode 100644 index 0000000000..d32a7791e1 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_age_battery.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_age_canula.png b/app/src/main/res/drawable-xxhdpi/icon_cp_age_canula.png new file mode 100644 index 0000000000..715682129b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_age_canula.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_age_insulin.png b/app/src/main/res/drawable-xxhdpi/icon_cp_age_insulin.png new file mode 100644 index 0000000000..79a21cea45 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_age_insulin.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_age_sensor.png b/app/src/main/res/drawable-xxhdpi/icon_cp_age_sensor.png new file mode 100644 index 0000000000..bb269c3af9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_age_sensor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_announcement.png b/app/src/main/res/drawable-xxhdpi/icon_cp_announcement.png new file mode 100644 index 0000000000..e287fa15d4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_announcement.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_basal_end.png b/app/src/main/res/drawable-xxhdpi/icon_cp_basal_end.png new file mode 100644 index 0000000000..08acae3012 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_basal_end.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_basal_start.png b/app/src/main/res/drawable-xxhdpi/icon_cp_basal_start.png new file mode 100644 index 0000000000..1b6d970b95 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_basal_start.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_bgcheck.png b/app/src/main/res/drawable-xxhdpi/icon_cp_bgcheck.png new file mode 100644 index 0000000000..4e68c25d70 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_bgcheck.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_carbs.png b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_carbs.png new file mode 100644 index 0000000000..a110276120 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_carbs.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_combo.png b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_combo.png new file mode 100644 index 0000000000..c91b515001 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_combo.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_correction.png b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_correction.png new file mode 100644 index 0000000000..d0c7a40613 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_correction.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_meal.png b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_meal.png new file mode 100644 index 0000000000..e13a420bad Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_meal.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_snack.png b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_snack.png new file mode 100644 index 0000000000..6a9fb42088 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_bolus_snack.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_insert.png b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_insert.png new file mode 100644 index 0000000000..f1a791b702 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_insert.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_profile.png b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_profile.png new file mode 100644 index 0000000000..d40cba3c46 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_profile.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_start.png b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_start.png new file mode 100644 index 0000000000..47d5de66a1 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_start.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_target.png b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_target.png new file mode 100644 index 0000000000..13fc303aa2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_cgm_target.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_exercise.png b/app/src/main/res/drawable-xxhdpi/icon_cp_exercise.png new file mode 100644 index 0000000000..4fb54d3703 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_exercise.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_note.png b/app/src/main/res/drawable-xxhdpi/icon_cp_note.png new file mode 100644 index 0000000000..c1881112b7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_note.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_pump_battery.png b/app/src/main/res/drawable-xxhdpi/icon_cp_pump_battery.png new file mode 100644 index 0000000000..1a6d44bba0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_pump_battery.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_pump_canula.png b/app/src/main/res/drawable-xxhdpi/icon_cp_pump_canula.png new file mode 100644 index 0000000000..6021f928ed Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_pump_canula.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_pump_cartridge.png b/app/src/main/res/drawable-xxhdpi/icon_cp_pump_cartridge.png new file mode 100644 index 0000000000..c7a8897a52 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_pump_cartridge.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cp_question.png b/app/src/main/res/drawable-xxhdpi/icon_cp_question.png new file mode 100644 index 0000000000..09455d09fd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cp_question.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_home_loop.png b/app/src/main/res/drawable-xxhdpi/icon_home_loop.png new file mode 100644 index 0000000000..c33f090311 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_home_loop.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_home_profile.png b/app/src/main/res/drawable-xxhdpi/icon_home_profile.png new file mode 100644 index 0000000000..00c4de023a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_home_profile.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_home_target.png b/app/src/main/res/drawable-xxhdpi/icon_home_target.png new file mode 100644 index 0000000000..70fd9ebc27 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_home_target.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_quickwizard.png b/app/src/main/res/drawable-xxhdpi/icon_quickwizard.png new file mode 100644 index 0000000000..9f2c9c9350 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_quickwizard.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_actions_cancelextbolus.png b/app/src/main/res/drawable-xxxhdpi/icon_actions_cancelextbolus.png new file mode 100644 index 0000000000..f5b57a9bc9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_actions_cancelextbolus.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_actions_profileswitch.png b/app/src/main/res/drawable-xxxhdpi/icon_actions_profileswitch.png new file mode 100644 index 0000000000..d5631ef3ae Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_actions_profileswitch.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_actions_refill.png b/app/src/main/res/drawable-xxxhdpi/icon_actions_refill.png new file mode 100644 index 0000000000..be3a5db708 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_actions_refill.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_actions_startextbolus.png b/app/src/main/res/drawable-xxxhdpi/icon_actions_startextbolus.png new file mode 100644 index 0000000000..89b44ea201 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_actions_startextbolus.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_actions_starttempbasal.png b/app/src/main/res/drawable-xxxhdpi/icon_actions_starttempbasal.png new file mode 100644 index 0000000000..7be2e32dfe Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_actions_starttempbasal.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_actions_temptarget.png b/app/src/main/res/drawable-xxxhdpi/icon_actions_temptarget.png new file mode 100644 index 0000000000..955a19f3bc Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_actions_temptarget.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_bolus.png b/app/src/main/res/drawable-xxxhdpi/icon_bolus.png new file mode 100644 index 0000000000..b4c4fb8559 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_bolus.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_calculator.png b/app/src/main/res/drawable-xxxhdpi/icon_calculator.png new file mode 100644 index 0000000000..90c8fab919 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_calculator.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_calibration.png b/app/src/main/res/drawable-xxxhdpi/icon_calibration.png new file mode 100644 index 0000000000..82eb93205e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_calibration.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cancelbasal.png b/app/src/main/res/drawable-xxxhdpi/icon_cancelbasal.png new file mode 100644 index 0000000000..cd66d14c4f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_aaps_offline.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_aaps_offline.png new file mode 100644 index 0000000000..3da8775fb4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_aaps_offline.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_age_battery.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_battery.png new file mode 100644 index 0000000000..dd21ad490c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_battery.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_age_canula.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_canula.png new file mode 100644 index 0000000000..6a3585b72f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_canula.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_age_insulin.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_insulin.png new file mode 100644 index 0000000000..3b50b616fc Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_insulin.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_age_sensor.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_sensor.png new file mode 100644 index 0000000000..2dd35e6e9e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_age_sensor.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_announcement.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_announcement.png new file mode 100644 index 0000000000..256631f49b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_announcement.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_basal_end.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_basal_end.png new file mode 100644 index 0000000000..a57ceb3b8a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_basal_end.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_basal_start.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_basal_start.png new file mode 100644 index 0000000000..d36b0b711c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_basal_start.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_bgcheck.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_bgcheck.png new file mode 100644 index 0000000000..fa72b549a9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_bgcheck.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_carbs.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_carbs.png new file mode 100644 index 0000000000..4dab75558b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_carbs.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_combo.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_combo.png new file mode 100644 index 0000000000..1418ea4994 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_combo.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_correction.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_correction.png new file mode 100644 index 0000000000..ccc3d0e39c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_correction.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_meal.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_meal.png new file mode 100644 index 0000000000..aa7bdf7fe3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_meal.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_snack.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_snack.png new file mode 100644 index 0000000000..1f9ab1697d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_bolus_snack.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_insert.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_insert.png new file mode 100644 index 0000000000..2d7e6b4542 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_insert.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_profile.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_profile.png new file mode 100644 index 0000000000..e8b4668b86 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_profile.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_start.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_start.png new file mode 100644 index 0000000000..e8d0e6773e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_start.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_target.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_target.png new file mode 100644 index 0000000000..2bdaf7d73d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_cgm_target.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_exercise.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_exercise.png new file mode 100644 index 0000000000..c16560e8de Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_exercise.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_note.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_note.png new file mode 100644 index 0000000000..dd1e04b419 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_note.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_battery.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_battery.png new file mode 100644 index 0000000000..f1d306de12 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_battery.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_canula.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_canula.png new file mode 100644 index 0000000000..465111a6ba Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_canula.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_cartridge.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_cartridge.png new file mode 100644 index 0000000000..afffd90482 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_pump_cartridge.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_cp_question.png b/app/src/main/res/drawable-xxxhdpi/icon_cp_question.png new file mode 100644 index 0000000000..b2e19c1575 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_cp_question.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_home_loop.png b/app/src/main/res/drawable-xxxhdpi/icon_home_loop.png new file mode 100644 index 0000000000..a59d73e2b4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_home_loop.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_home_profile.png b/app/src/main/res/drawable-xxxhdpi/icon_home_profile.png new file mode 100644 index 0000000000..80234a0f75 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_home_profile.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_home_target.png b/app/src/main/res/drawable-xxxhdpi/icon_home_target.png new file mode 100644 index 0000000000..c1a4d99087 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_home_target.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/icon_quickwizard.png b/app/src/main/res/drawable-xxxhdpi/icon_quickwizard.png new file mode 100644 index 0000000000..314b8a98de Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/icon_quickwizard.png differ diff --git a/app/src/main/res/drawable/icon_actions_cancelextbolus.png b/app/src/main/res/drawable/icon_actions_cancelextbolus.png new file mode 100644 index 0000000000..4ad378e374 Binary files /dev/null and b/app/src/main/res/drawable/icon_actions_cancelextbolus.png differ diff --git a/app/src/main/res/drawable/icon_actions_profileswitch.png b/app/src/main/res/drawable/icon_actions_profileswitch.png new file mode 100644 index 0000000000..eeae6ccfdb Binary files /dev/null and b/app/src/main/res/drawable/icon_actions_profileswitch.png differ diff --git a/app/src/main/res/drawable/icon_actions_refill.png b/app/src/main/res/drawable/icon_actions_refill.png new file mode 100644 index 0000000000..737cca8b00 Binary files /dev/null and b/app/src/main/res/drawable/icon_actions_refill.png differ diff --git a/app/src/main/res/drawable/icon_actions_startextbolus.png b/app/src/main/res/drawable/icon_actions_startextbolus.png new file mode 100644 index 0000000000..338df773c2 Binary files /dev/null and b/app/src/main/res/drawable/icon_actions_startextbolus.png differ diff --git a/app/src/main/res/drawable/icon_actions_starttempbasal.png b/app/src/main/res/drawable/icon_actions_starttempbasal.png new file mode 100644 index 0000000000..18fbd8c111 Binary files /dev/null and b/app/src/main/res/drawable/icon_actions_starttempbasal.png differ diff --git a/app/src/main/res/drawable/icon_actions_temptarget.png b/app/src/main/res/drawable/icon_actions_temptarget.png new file mode 100644 index 0000000000..39170bab37 Binary files /dev/null and b/app/src/main/res/drawable/icon_actions_temptarget.png differ diff --git a/app/src/main/res/drawable/icon_bolus.png b/app/src/main/res/drawable/icon_bolus.png index e0d0204a22..c083219b45 100644 Binary files a/app/src/main/res/drawable/icon_bolus.png 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 index b327e69327..056722a440 100644 Binary files a/app/src/main/res/drawable/icon_calculator.png 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 index 8a6db6f8d1..0929d3690d 100644 Binary files a/app/src/main/res/drawable/icon_calibration.png 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 index 55a39b40e5..c48a20792d 100644 Binary files a/app/src/main/res/drawable/icon_cancelbasal.png and b/app/src/main/res/drawable/icon_cancelbasal.png differ diff --git a/app/src/main/res/drawable/icon_cp_aaps_offline.png b/app/src/main/res/drawable/icon_cp_aaps_offline.png new file mode 100644 index 0000000000..dc50653883 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_aaps_offline.png differ diff --git a/app/src/main/res/drawable/icon_cp_age_battery.png b/app/src/main/res/drawable/icon_cp_age_battery.png new file mode 100644 index 0000000000..6c7fc56139 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_age_battery.png differ diff --git a/app/src/main/res/drawable/icon_cp_age_canula.png b/app/src/main/res/drawable/icon_cp_age_canula.png new file mode 100644 index 0000000000..303ad946cd Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_age_canula.png differ diff --git a/app/src/main/res/drawable/icon_cp_age_insulin.png b/app/src/main/res/drawable/icon_cp_age_insulin.png new file mode 100644 index 0000000000..5cd8598faa Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_age_insulin.png differ diff --git a/app/src/main/res/drawable/icon_cp_age_sensor.png b/app/src/main/res/drawable/icon_cp_age_sensor.png new file mode 100644 index 0000000000..d312b6c572 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_age_sensor.png differ diff --git a/app/src/main/res/drawable/icon_cp_announcement.png b/app/src/main/res/drawable/icon_cp_announcement.png new file mode 100644 index 0000000000..6e1338ac24 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_announcement.png differ diff --git a/app/src/main/res/drawable/icon_cp_basal_end.png b/app/src/main/res/drawable/icon_cp_basal_end.png new file mode 100644 index 0000000000..be8474f002 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_basal_end.png differ diff --git a/app/src/main/res/drawable/icon_cp_basal_start.png b/app/src/main/res/drawable/icon_cp_basal_start.png new file mode 100644 index 0000000000..34cd31f14b Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_basal_start.png differ diff --git a/app/src/main/res/drawable/icon_cp_bgcheck.png b/app/src/main/res/drawable/icon_cp_bgcheck.png new file mode 100644 index 0000000000..0cb14c2f57 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_bgcheck.png differ diff --git a/app/src/main/res/drawable/icon_cp_bolus_carbs.png b/app/src/main/res/drawable/icon_cp_bolus_carbs.png new file mode 100644 index 0000000000..561703fb06 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_bolus_carbs.png differ diff --git a/app/src/main/res/drawable/icon_cp_bolus_combo.png b/app/src/main/res/drawable/icon_cp_bolus_combo.png new file mode 100644 index 0000000000..ce4d8fb9d3 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_bolus_combo.png differ diff --git a/app/src/main/res/drawable/icon_cp_bolus_correction.png b/app/src/main/res/drawable/icon_cp_bolus_correction.png new file mode 100644 index 0000000000..582472dc92 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_bolus_correction.png differ diff --git a/app/src/main/res/drawable/icon_cp_bolus_meal.png b/app/src/main/res/drawable/icon_cp_bolus_meal.png new file mode 100644 index 0000000000..54b51e126e Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_bolus_meal.png differ diff --git a/app/src/main/res/drawable/icon_cp_bolus_snack.png b/app/src/main/res/drawable/icon_cp_bolus_snack.png new file mode 100644 index 0000000000..b2ba41c27d Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_bolus_snack.png differ diff --git a/app/src/main/res/drawable/icon_cp_cgm_insert.png b/app/src/main/res/drawable/icon_cp_cgm_insert.png new file mode 100644 index 0000000000..67c0fb1ba2 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_cgm_insert.png differ diff --git a/app/src/main/res/drawable/icon_cp_cgm_profile.png b/app/src/main/res/drawable/icon_cp_cgm_profile.png new file mode 100644 index 0000000000..e0f0a15cc8 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_cgm_profile.png differ diff --git a/app/src/main/res/drawable/icon_cp_cgm_start.png b/app/src/main/res/drawable/icon_cp_cgm_start.png new file mode 100644 index 0000000000..14a44bc852 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_cgm_start.png differ diff --git a/app/src/main/res/drawable/icon_cp_cgm_target.png b/app/src/main/res/drawable/icon_cp_cgm_target.png new file mode 100644 index 0000000000..86ce00442c Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_cgm_target.png differ diff --git a/app/src/main/res/drawable/icon_cp_exercise.png b/app/src/main/res/drawable/icon_cp_exercise.png new file mode 100644 index 0000000000..1c92c0ebb5 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_exercise.png differ diff --git a/app/src/main/res/drawable/icon_cp_note.png b/app/src/main/res/drawable/icon_cp_note.png new file mode 100644 index 0000000000..7c8663a4fe Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_note.png differ diff --git a/app/src/main/res/drawable/icon_cp_pump_battery.png b/app/src/main/res/drawable/icon_cp_pump_battery.png new file mode 100644 index 0000000000..f4dab169a8 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_pump_battery.png differ diff --git a/app/src/main/res/drawable/icon_cp_pump_canula.png b/app/src/main/res/drawable/icon_cp_pump_canula.png new file mode 100644 index 0000000000..ee512c5fef Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_pump_canula.png differ diff --git a/app/src/main/res/drawable/icon_cp_pump_cartridge.png b/app/src/main/res/drawable/icon_cp_pump_cartridge.png new file mode 100644 index 0000000000..70a90c596f Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_pump_cartridge.png differ diff --git a/app/src/main/res/drawable/icon_cp_question.png b/app/src/main/res/drawable/icon_cp_question.png new file mode 100644 index 0000000000..5d430d9164 Binary files /dev/null and b/app/src/main/res/drawable/icon_cp_question.png differ diff --git a/app/src/main/res/drawable/icon_home_loop.png b/app/src/main/res/drawable/icon_home_loop.png new file mode 100644 index 0000000000..5240cc85db Binary files /dev/null and b/app/src/main/res/drawable/icon_home_loop.png differ diff --git a/app/src/main/res/drawable/icon_home_profile.png b/app/src/main/res/drawable/icon_home_profile.png new file mode 100644 index 0000000000..f689df10c6 Binary files /dev/null and b/app/src/main/res/drawable/icon_home_profile.png differ diff --git a/app/src/main/res/drawable/icon_home_target.png b/app/src/main/res/drawable/icon_home_target.png new file mode 100644 index 0000000000..9fc7086e9d Binary files /dev/null and b/app/src/main/res/drawable/icon_home_target.png differ diff --git a/app/src/main/res/drawable/icon_quickwizard.png b/app/src/main/res/drawable/icon_quickwizard.png index 0487ee2ac1..d65347f235 100644 Binary files a/app/src/main/res/drawable/icon_quickwizard.png and b/app/src/main/res/drawable/icon_quickwizard.png differ diff --git a/app/src/main/res/layout/actions_fragment.xml b/app/src/main/res/layout/actions_fragment.xml index 7fc4661be5..bc8f416770 100644 --- a/app/src/main/res/layout/actions_fragment.xml +++ b/app/src/main/res/layout/actions_fragment.xml @@ -8,77 +8,104 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - -