diff --git a/app/build.gradle b/app/build.gradle
index 1742444504..30158bf591 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -43,10 +43,16 @@ android {
applicationId "info.nightscout.androidaps"
minSdkVersion 21
targetSdkVersion 23
+ multiDexEnabled true
versionCode 1500
version "1.54-dev"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", generateGitBuild()
+
+ ndk {
+ abiFilters "armeabi-v7a", "x86", "armeabi", "mips"
+ moduleName "BleCommandUtil"
+ }
}
lintOptions {
disable 'MissingTranslation'
@@ -58,7 +64,7 @@ android {
}
}
productFlavors {
- flavorDimensions "standard", "wear"
+ flavorDimensions "standard"
full {
dimension "standard"
resValue "string", "app_name", "AndroidAPS"
@@ -107,22 +113,6 @@ android {
buildConfigField "boolean", "NSCLIENTOLNY", "true"
buildConfigField "boolean", "CLOSEDLOOP", "false"
}
- wear {
- dimension "wear"
- buildConfigField "boolean", "WEAR", "true"
- buildConfigField "boolean", "WEAR_CONTROL", "false"
-
- }
- wearcontrol {
- dimension "wear"
- buildConfigField "boolean", "WEAR", "true"
- buildConfigField "boolean", "WEAR_CONTROL", "true"
- }
- nowear {
- dimension "wear"
- buildConfigField "boolean", "WEAR", "false"
- buildConfigField "boolean", "WEAR_CONTROL", "false"
- }
}
}
@@ -136,8 +126,7 @@ allprojects {
}
dependencies {
- wearWearApp project(path: ':wear', configuration: 'restrictedRelease')
- wearcontrolWearApp project(path: ':wear', configuration: 'fullRelease')
+ wearApp project(':wear')
compile fileTree(include: ['*.jar'], dir: 'libs')
compile('com.crashlytics.sdk.android:crashlytics:2.6.7@aar') {
diff --git a/app/libs/rhino-1.7.7.2.jar b/app/libs/rhino-1.7.7.2.jar
new file mode 100644
index 0000000000..4a18d33609
Binary files /dev/null and b/app/libs/rhino-1.7.7.2.jar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7d792556b7..be3c0e5d80 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,6 +17,7 @@
+
@@ -50,6 +51,13 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/OpenAPSAMA/loggerhelper.js b/app/src/main/assets/OpenAPSAMA/loggerhelper.js
new file mode 100644
index 0000000000..e790f465c8
--- /dev/null
+++ b/app/src/main/assets/OpenAPSAMA/loggerhelper.js
@@ -0,0 +1,12 @@
+var console = { };
+console.error = function error(){
+ for (var i = 0, len = arguments.length; i < len; i++) {
+ console2.log(arguments[i]);
+ }
+};
+
+console.log = function log(){
+ for (var i = 0, len = arguments.length; i < len; i++) {
+ console2.log(arguments[i]);
+ }
+};
diff --git a/app/src/main/java/com/cozmo/danar/util/BleCommandUtil.java b/app/src/main/java/com/cozmo/danar/util/BleCommandUtil.java
new file mode 100644
index 0000000000..a417b379e8
--- /dev/null
+++ b/app/src/main/java/com/cozmo/danar/util/BleCommandUtil.java
@@ -0,0 +1,120 @@
+package com.cozmo.danar.util;
+
+import android.content.Context;
+
+import info.nightscout.androidaps.MainApp;
+
+public class BleCommandUtil {
+ public static final int DANAR_PACKET__TYPE_ENCRYPTION_REQUEST = 0x01;
+ public static final int DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE = 0x02;
+ public static final int DANAR_PACKET__TYPE_COMMAND = 0xA1;
+ public static final int DANAR_PACKET__TYPE_RESPONSE = 0xB2;
+ public static final int DANAR_PACKET__TYPE_NOTIFY = 0xC3;
+
+ public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK = 0x00;
+ public static final int DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY = 0xD0;
+ public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST = 0xD1;
+ public static final int DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN = 0xD2;
+ public static final int DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION = 0x01;
+
+ public static final int DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_COMPLETE = 0x01;
+ public static final int DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_RATE_DISPLAY = 0x02;
+ public static final int DANAR_PACKET__OPCODE_NOTIFY__ALARM = 0x03;
+ public static final int DANAR_PACKET__OPCODE_NOTIFY__MISSED_BOLUS_ALARM = 0x04;
+
+ public static final int DANAR_PACKET__OPCODE_REVIEW__INITIAL_SCREEN_INFORMATION = 0x02;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__DELIVERY_STATUS = 0x03;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PASSWORD = 0x04;
+
+ public static final int DANAR_PACKET__OPCODE_REVIEW__BOLUS_AVG = 0x10;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__BOLUS = 0x11;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__DAILY = 0x12;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__PRIME = 0x13;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__REFILL = 0x14;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__BLOOD_GLUCOSE = 0x15;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__CARBOHYDRATE = 0x16;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__TEMPORARY = 0x17;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__SUSPEND = 0x18;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__ALARM = 0x19;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__BASAL = 0x1A;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__ALL_HISTORY = 0x1F;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__GET_SHIPPING_INFORMATION = 0x20;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PUMP_CHECK = 0x21;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__GET_USER_TIME_CHANGE_FLAG = 0x22;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR = 0x23;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__GET_MORE_INFORMATION = 0x24;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__SET_HISTORY_UPLOAD_MODE = 0x25;
+ public static final int DANAR_PACKET__OPCODE_REVIEW__GET_TODAY_DELIVERY_TOTAL = 0x26;
+
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_STEP_BOLUS_INFORMATION = 0x40;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS_STATE = 0x41;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS = 0x42;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_DUAL_BOLUS = 0x43;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_STOP = 0x44;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CARBOHYDRATE_CALCULATION_INFORMATION = 0x45;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_MENU_OPTION_STATE = 0x46;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS = 0x47;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_DUAL_BOLUS = 0x48;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS_CANCEL = 0x49;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_START = 0x4A;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CALCULATION_INFORMATION = 0x4B;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_RATE = 0x4C;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_RATE = 0x4D;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_CIR_CF_ARRAY = 0x4E;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_CIR_CF_ARRAY = 0x4F;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_OPTION = 0x50;
+ public static final int DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_OPTION = 0x51;
+
+ public static final int DANAR_PACKET__OPCODE_BASAL__SET_TEMPORARY_BASAL = 0x60;
+ public static final int DANAR_PACKET__OPCODE_BASAL__TEMPORARY_BASAL_STATE = 0x61;
+ public static final int DANAR_PACKET__OPCODE_BASAL__CANCEL_TEMPORARY_BASAL = 0x62;
+ public static final int DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_NUMBER = 0x63;
+ public static final int DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_NUMBER = 0x64;
+ public static final int DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_BASAL_RATE = 0x65;
+ public static final int DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_BASAL_RATE = 0x66;
+ public static final int DANAR_PACKET__OPCODE_BASAL__GET_BASAL_RATE = 0x67;
+ public static final int DANAR_PACKET__OPCODE_BASAL__SET_BASAL_RATE = 0x68;
+ public static final int DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_ON = 0x69;
+ public static final int DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_OFF = 0x6A;
+
+ public static final int DANAR_PACKET__OPCODE_OPTION__GET_PUMP_TIME = 0x70;
+ public static final int DANAR_PACKET__OPCODE_OPTION__SET_PUMP_TIME = 0x71;
+ public static final int DANAR_PACKET__OPCODE_OPTION__GET_USER_OPTION = 0x72;
+ public static final int DANAR_PACKET__OPCODE_OPTION__SET_USER_OPTION = 0x73;
+
+ public static final int DANAR_PACKET__OPCODE_BASAL__APS_SET_TEMPORARY_BASAL = 0xC1;
+ public static final int DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS = 0xC2;
+ public static final int DANAR_PACKET__OPCODE__APS_SET_EVENT_HISTORY = 0xC3;
+
+ public static final int DANAR_PACKET__OPCODE_ETC__SET_HISTORY_SAVE = 0xE0;
+ public static final int DANAR_PACKET__OPCODE_ETC__KEEP_CONNECTION = 0xFF;
+
+ static {
+ System.loadLibrary("BleCommandUtil");
+ }
+
+ private static native byte[] getEncryptedPacketJni(Object context, int opcode, byte[] bytes, String deviceName);
+
+ private static native byte[] getDecryptedPacketJni(Object context, byte[] bytes);
+
+ // ---------------------------------------------------------
+
+ private static BleCommandUtil mInstance = null;
+
+ public static BleCommandUtil getInstance() {
+ if (mInstance == null) {
+ mInstance = new BleCommandUtil();
+ }
+ return mInstance;
+ }
+
+ // ---------------------------------------------------------
+
+ public byte[] getEncryptedPacket(int opcode, byte[] bytes, String deviceName) {
+ return getEncryptedPacketJni(MainApp.instance().getApplicationContext(), opcode, bytes, deviceName);
+ }
+
+ public byte[] getDecryptedPacket(byte[] bytes) {
+ return getDecryptedPacketJni(MainApp.instance().getApplicationContext(), bytes);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java
index e6c06583c9..abda0ca941 100644
--- a/app/src/main/java/info/nightscout/androidaps/Config.java
+++ b/app/src/main/java/info/nightscout/androidaps/Config.java
@@ -11,7 +11,6 @@ public class Config {
// PLUGINS
public static final boolean OPENAPSENABLED = APS;
public static final boolean LOOPENABLED = APS;
- public static final boolean WEAR = BuildConfig.WEAR;
public static final boolean NSCLIENT = BuildConfig.NSCLIENTOLNY;
@@ -40,10 +39,10 @@ public class Config {
public static final boolean logNSUpload = true;
public static final boolean logPumpActions = true;
public static final boolean logCongigBuilderActions = true;
- public static final boolean logAutosensData = true;
+ public static final boolean logAutosensData = false;
// DanaR specific
public static final boolean logDanaBTComm = true;
- public static final boolean logDanaMessageDetail = true;
+ public static boolean logDanaMessageDetail = true;
public static final boolean logDanaSerialEngine = true;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/Constants.java b/app/src/main/java/info/nightscout/androidaps/Constants.java
index e361e4cc8c..e37a5b4b9f 100644
--- a/app/src/main/java/info/nightscout/androidaps/Constants.java
+++ b/app/src/main/java/info/nightscout/androidaps/Constants.java
@@ -32,6 +32,8 @@ public class Constants {
// Circadian Percentage Profile
public static final int CPP_MIN_PERCENTAGE = 50;
public static final int CPP_MAX_PERCENTAGE = 200;
+ public static final int CPP_MIN_TIMESHIFT = -6;
+ public static final int CPP_MAX_TIMESHIFT = 23;
// Very Hard Limits Ranges
// First value is the Lowest and second value is the Highest a Limit can define
diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
index 68df307dbf..291cdd94ac 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java
@@ -58,8 +58,10 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
static final int CASE_STORAGE = 0x1;
static final int CASE_SMS = 0x2;
+ static final int CASE_LOCATION = 0x3;
private boolean askForSMS = false;
+ private boolean askForLocation = true;
ImageButton menuButton;
@@ -202,6 +204,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
protected void onResume() {
super.onResume();
askForSMSPermissions();
+ askForLocationPermissions();
}
@Override
@@ -256,6 +259,17 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
}
}
+ private synchronized void askForLocationPermissions() {
+ if (askForLocation) { //only when settings were changed an MainActivity resumes.
+ askForLocation = false;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ askForPermission(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION}, CASE_LOCATION);
+ }
+ }
+ }
+
private void askForPermission(String[] permission, Integer requestCode) {
boolean test = false;
for (int i = 0; i < permission.length; i++) {
@@ -279,6 +293,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
alert.setPositiveButton(R.string.ok, null);
alert.show();
break;
+ case CASE_LOCATION:
case CASE_SMS:
break;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index 6ff48818c2..4398f80e75 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -52,6 +52,8 @@ import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.services.DanaRKoreanExecutionService;
+import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaRS.services.DanaRSService;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionService;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
@@ -123,7 +125,8 @@ public class MainApp extends Application {
pluginsList.add(SensitivityWeightedAveragePlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRPlugin.getPlugin());
if (Config.DANAR) pluginsList.add(DanaRKoreanPlugin.getPlugin());
- if (Config.DANARv2) pluginsList.add(DanaRv2Plugin.getPlugin());
+ if (Config.DANAR) pluginsList.add(DanaRv2Plugin.getPlugin());
+ if (Config.DANAR) pluginsList.add(DanaRSPlugin.getPlugin());
pluginsList.add(CareportalFragment.getPlugin());
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
if (Config.VIRTUALPUMP) pluginsList.add(VirtualPumpPlugin.getInstance());
@@ -147,7 +150,7 @@ public class MainApp extends Application {
pluginsList.add(SourceGlimpPlugin.getPlugin());
if (Config.SMSCOMMUNICATORENABLED) pluginsList.add(SmsCommunicatorPlugin.getPlugin());
- if (Config.WEAR) pluginsList.add(WearFragment.getPlugin(this));
+ pluginsList.add(WearFragment.getPlugin(this));
pluginsList.add(StatuslinePlugin.getPlugin(this));
pluginsList.add(new PersistentNotificationPlugin(this));
pluginsList.add(NSClientInternalPlugin.getPlugin());
@@ -207,6 +210,7 @@ public class MainApp extends Application {
startService(new Intent(this, DanaRExecutionService.class));
startService(new Intent(this, DanaRKoreanExecutionService.class));
startService(new Intent(this, DanaRv2ExecutionService.class));
+ startService(new Intent(this, DanaRSService.class));
}
keepAliveReceiver.setAlarm(this);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
index 80cc0e65d9..d77338d36d 100644
--- a/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/PreferencesActivity.java
@@ -21,6 +21,7 @@ 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.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.SensitivityAAPS.SensitivityAAPSPlugin;
@@ -70,6 +71,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
EditTextPreference editTextPref = (EditTextPreference) pref;
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******");
+ } else if (pref.getKey().equals(MainApp.sResources.getString(R.string.key_danars_name))) {
+ pref.setSummary(SP.getString(R.string.key_danars_name,""));
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText());
@@ -130,12 +133,19 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
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)) {
+ DanaRSPlugin danaRSPlugin = MainApp.getSpecificPlugin(DanaRSPlugin.class);
+ if (danaRPlugin.isEnabled(PluginBase.PUMP)) {
addPreferencesFromResource(R.xml.pref_danar);
}
+ if (danaRKoreanPlugin.isEnabled(PluginBase.PUMP)) {
+ addPreferencesFromResource(R.xml.pref_danarkorean);
+ }
if (danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PUMP)) {
addPreferencesFromResource(R.xml.pref_danarv2);
}
+ if (danaRSPlugin != null && danaRSPlugin.isEnabled(PluginBase.PUMP)) {
+ addPreferencesFromResource(R.xml.pref_danars);
+ }
if (danaRPlugin.isEnabled(PluginBase.PROFILE) || danaRKoreanPlugin.isEnabled(PluginBase.PROFILE) || danaRv2Plugin != null && danaRv2Plugin.isEnabled(PluginBase.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile);
}
@@ -145,7 +155,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(R.xml.pref_virtualpump);
}
InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin = MainApp.getSpecificPlugin(InsulinOrefFreePeakPlugin.class);
- if(insulinOrefFreePeakPlugin.isEnabled(PluginBase.INSULIN)){
+ if (insulinOrefFreePeakPlugin.isEnabled(PluginBase.INSULIN)) {
addPreferencesFromResource(R.xml.pref_insulinoreffreepeak);
}
@@ -160,11 +170,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
addPreferencesFromResource(R.xml.pref_advanced);
- if (Config.WEAR) {
- WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class);
- if (wearPlugin != null && wearPlugin.isEnabled(PluginBase.GENERAL)) {
- addPreferencesFromResource(R.xml.pref_wear);
- }
+ WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class);
+ if (wearPlugin != null && wearPlugin.isEnabled(PluginBase.GENERAL)) {
+ addPreferencesFromResource(R.xml.pref_wear);
}
StatuslinePlugin statuslinePlugin = MainApp.getSpecificPlugin(StatuslinePlugin.class);
diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
index 09885448e2..1ec6f54b71 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -22,6 +22,7 @@ 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.SafeParse;
import info.nightscout.utils.ToastUtils;
public class Profile {
@@ -38,10 +39,15 @@ public class Profile {
JSONArray basal;
private LongSparseArray basal_v = null; // oldest at index 0
JSONArray targetLow;
+ private LongSparseArray targetLow_v = null; // oldest at index 0
JSONArray targetHigh;
+ private LongSparseArray targetHigh_v = null; // oldest at index 0
+
+ int percentage = 100;
+ int timeshift = 0;
public Profile(JSONObject json, String units) {
- this(json);
+ this(json, 100, 0);
if (this.units == null) {
if (units != null)
this.units = units;
@@ -52,7 +58,9 @@ public class Profile {
}
}
- public Profile(JSONObject json) {
+ public Profile(JSONObject json, int percentage, int timeshift) {
+ this.percentage = percentage;
+ this.timeshift = timeshift;
this.json = json;
try {
if (json.has("units"))
@@ -148,17 +156,25 @@ public class Profile {
}
private LongSparseArray convertToSparseArray(JSONArray array) {
+ double multiplier = getMultiplier(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");
+ long tas = getShitfTimeSecs((int) o.getLong("timeAsSeconds"));
+ Double value = o.getDouble("value") * multiplier;
sparse.put(tas, value);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
+
+ // check if start is at 0 (midnight)
+ // and add last value before midnight if not
+ if (sparse.keyAt(0) != 0) {
+ sparse.put(0, sparse.valueAt(sparse.size() - 1));
+ }
return sparse;
}
@@ -182,7 +198,47 @@ public class Profile {
return lastValue;
}
- private Double getValueToTime(LongSparseArray array, long timeAsSeconds) {
+ Integer getShitfTimeSecs(Integer originalTime) {
+ Integer shiftedTime = originalTime + timeshift * 60 * 60;
+ shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 60 * 60);
+ if (timeshift != 0)
+ log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime);
+ return shiftedTime;
+ }
+
+ double getMultiplier(LongSparseArray array) {
+ double multiplier = 1d;
+
+ if (array == isf_v)
+ multiplier = 100d / percentage;
+ else if (array == ic_v)
+ multiplier = 100d / percentage;
+ else if (array == basal_v)
+ multiplier = percentage / 100d;
+ else
+ log.error("Unknown array type");
+ return multiplier;
+ }
+
+ double getMultiplier(JSONArray array) {
+ double multiplier = 1d;
+
+ if (array == isf)
+ multiplier = 100d / percentage;
+ else if (array == ic)
+ multiplier = 100d / percentage;
+ else if (array == basal)
+ multiplier = percentage / 100d;
+ else if (array == targetLow)
+ multiplier = 1d;
+ else if (array == targetHigh)
+ multiplier = 1d;
+ else
+ log.error("Unknown array type");
+ return multiplier;
+ }
+
+ private Double getValueToTime(LongSparseArray array, Integer timeAsSeconds) {
Double lastValue = null;
for (Integer index = 0; index < array.size(); index++) {
@@ -197,26 +253,29 @@ public class Profile {
return lastValue;
}
- private String getValuesList(JSONArray array, JSONArray array2, DecimalFormat format, String units) {
+ private String format_HH_MM(Integer timeAsSeconds) {
+ String time;
+ int hour = timeAsSeconds / 60 / 60;
+ int minutes = timeAsSeconds - hour * 60 * 60;
+ DecimalFormat df = new DecimalFormat("00");
+ time = df.format(hour) + ":" + df.format(minutes);
+ return time;
+ }
+
+ private String getValuesList(LongSparseArray array, LongSparseArray 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) {
- log.error("Unhandled exception", e);
+ for (Integer index = 0; index < array.size(); index++) {
+ retValue += format_HH_MM((int) array.keyAt(index));
+ retValue += " ";
+ retValue += format.format(array.valueAt(index));
+ if (array2 != null) {
+ retValue += " - ";
+ retValue += format.format(array2.valueAt(index));
}
+ retValue += " " + units;
+ if (index + 1 < array.size())
+ retValue += "\n";
}
return retValue;
}
@@ -236,7 +295,7 @@ public class Profile {
}
public String getIsfList() {
- return getValuesList(isf, null, new DecimalFormat("0.0"), getUnits() + "/U");
+ return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U");
}
public Double getIc() {
@@ -254,7 +313,7 @@ public class Profile {
}
public String getIcList() {
- return getValuesList(ic, null, new DecimalFormat("0.0"), " g/U");
+ return getValuesList(ic_v, null, new DecimalFormat("0.0"), " g/U");
}
public Double getBasal() {
@@ -272,7 +331,7 @@ public class Profile {
}
public String getBasalList() {
- return getValuesList(basal, null, new DecimalFormat("0.00"), "U");
+ return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U");
}
public class BasalValue {
@@ -286,20 +345,14 @@ public class Profile {
}
public BasalValue[] getBasalValues() {
- try {
- BasalValue[] ret = new BasalValue[basal.length()];
+ BasalValue[] ret = new BasalValue[basal_v.size()];
- 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) {
- log.error("Unhandled exception", e);
+ for (Integer index = 0; index < basal_v.size(); index++) {
+ Integer tas = (int) basal_v.keyAt(index);
+ Double value = basal_v.valueAt(index);
+ ret[index] = new BasalValue(tas, value);
}
- return new BasalValue[0];
+ return ret;
}
public Double getTargetLow() {
@@ -311,7 +364,9 @@ public class Profile {
}
public Double getTargetLow(Integer timeAsSeconds) {
- return getValueToTime(targetLow, timeAsSeconds);
+ if (targetLow_v == null)
+ targetLow_v = convertToSparseArray(targetLow);
+ return getValueToTime(targetLow_v, timeAsSeconds);
}
public Double getTargetHigh() {
@@ -323,11 +378,13 @@ public class Profile {
}
public Double getTargetHigh(Integer timeAsSeconds) {
- return getValueToTime(targetHigh, timeAsSeconds);
+ if (targetHigh_v == null)
+ targetHigh_v = convertToSparseArray(targetHigh);
+ return getValueToTime(targetHigh_v, timeAsSeconds);
}
public String getTargetList() {
- return getValuesList(targetLow, targetHigh, new DecimalFormat("0.0"), getUnits());
+ return getValuesList(targetLow_v, targetHigh_v, new DecimalFormat("0.0"), getUnits());
}
public double getMaxDailyBasal() {
@@ -350,18 +407,6 @@ public class Profile {
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);
@@ -410,4 +455,29 @@ public class Profile {
return toUnitsString(lowMgdl, lowMmol, units) + " - " + toUnitsString(highMgdl, highMmol, units);
}
+
+ public double percentageBasalSum() {
+ double result = 0d;
+ for (int i = 0; i < 24; i++) {
+ result += getBasal((Integer) (i * 60 * 60));
+ }
+ return result;
+ }
+
+
+ public double baseBasalSum() {
+ double result = 0d;
+ for (int i = 0; i < 24; i++) {
+ result += getBasal((Integer) (i * 60 * 60)) / getMultiplier(basal_v);
+ }
+ return result;
+ }
+
+ public int getPercentage() {
+ return percentage;
+ }
+
+ public int getTimeshift() {
+ return timeshift;
+ }
}
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 3a09cb2da4..2767f7611a 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java
@@ -1541,9 +1541,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
old = getDaoProfileSwitch().queryForId(profileSwitch.date);
if (old != null) {
if (!old.isEqual(profileSwitch)) {
+ profileSwitch.source = old.source;
+ profileSwitch.profileName = old.profileName; // preserver profileName to prevent multiple CPP extension
getDaoProfileSwitch().delete(old); // need to delete/create because date may change too
- old.copyFrom(profileSwitch);
- getDaoProfileSwitch().create(old);
+ getDaoProfileSwitch().create(profileSwitch);
log.debug("PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString());
scheduleProfileSwitchChange();
return true;
diff --git a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
index cd5efc7465..8bcd192d59 100644
--- a/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
+++ b/app/src/main/java/info/nightscout/androidaps/db/ProfileSwitch.java
@@ -10,14 +10,15 @@ 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.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.DecimalFormatter;
@DatabaseTable(tableName = DatabaseHelper.DATABASE_PROFILESWITCHES)
public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@@ -58,13 +59,24 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
public Profile getProfileObject() {
if (profile == null)
try {
- profile = new Profile(new JSONObject(profileJson));
+ profile = new Profile(new JSONObject(profileJson), percentage, timeshift);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return profile;
}
+ public String getCustomizedName() {
+ String name = profileName;
+ if(LocalProfilePlugin.LOCAL_PROFILE.equals(name)){
+ name = DecimalFormatter.to2Decimal(getProfileObject().percentageBasalSum()) + "U ";
+ }
+ if (isCPP) {
+ name += "(" + percentage + "%," + timeshift + "h)";
+ }
+ return name;
+ }
+
public boolean isEqual(ProfileSwitch other) {
if (date != other.date) {
return false;
@@ -179,7 +191,7 @@ public class ProfileSwitch implements Interval, DataPointWithLabelInterface {
@Override
public String getLabel() {
- return profileName;
+ return getCustomizedName();
}
@Override
diff --git a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java
index ab697e4840..3cfe7cc6a7 100644
--- a/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java
+++ b/app/src/main/java/info/nightscout/androidaps/events/EventPumpStatusChanged.java
@@ -18,14 +18,24 @@ public class EventPumpStatusChanged {
public int sSecondsElapsed = 0;
public String sPerfomingAction = "";
+ public static String error = "";
+
public EventPumpStatusChanged(int status) {
sStatus = status;
sSecondsElapsed = 0;
+ error = "";
}
public EventPumpStatusChanged(int status, int secondsElapsed) {
sStatus = status;
sSecondsElapsed = secondsElapsed;
+ error = "";
+ }
+
+ public EventPumpStatusChanged(int status, String error) {
+ sStatus = status;
+ sSecondsElapsed = 0;
+ this.error = error;
}
public EventPumpStatusChanged(String action) {
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 2db7564de7..9da9cb0dd0 100644
--- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
+++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java
@@ -31,7 +31,7 @@ public interface PumpInterface {
PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo);
void stopBolusDelivering();
- PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force);
+ PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew);
PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes);
PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes);
//some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
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 ade5e074ba..fdb1953531 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
@@ -194,14 +194,14 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL
switch (view.getId()) {
case R.id.actions_profileswitch:
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.profileswitch;
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(manager, "NewNSTreatmentDialog");
break;
case R.id.actions_temptarget:
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
- final OptionsToShow temptarget = CareportalFragment.temptarget;
+ final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
temptarget.executeTempTarget = true;
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
newTTDialog.show(manager, "NewNSTreatmentDialog");
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 f6e043d3b6..f6c9d4c3d6 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java
@@ -2,11 +2,9 @@ package info.nightscout.androidaps.plugins.Actions.dialogs;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
-import android.preference.PreferenceManager;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
@@ -16,7 +14,6 @@ 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;
import com.crashlytics.android.answers.CustomEvent;
@@ -32,12 +29,11 @@ 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.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.utils.DecimalFormatter;
-import info.nightscout.utils.PlusMinusEditText;
+import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
@@ -45,13 +41,12 @@ public class FillDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(FillDialog.class);
Button deliverButton;
- TextView insulin;
double amount1 = 0d;
double amount2 = 0d;
double amount3 = 0d;
- PlusMinusEditText editInsulin;
+ NumberPicker editInsulin;
Handler mHandler;
public static HandlerThread mHandlerThread;
@@ -73,10 +68,10 @@ public class FillDialog extends DialogFragment implements OnClickListener {
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);
Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
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);
+ editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
+ editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, new DecimalFormat("0.00"), false);
//setup preset buttons
Button button1 = (Button) view.findViewById(R.id.fill_preset_button1);
@@ -88,21 +83,21 @@ public class FillDialog extends DialogFragment implements OnClickListener {
amount2 = SP.getDouble("fill_button2", 0d);
amount3 = SP.getDouble("fill_button3", 0d);
- if(amount1 >0) {
+ if (amount1 > 0) {
button1.setVisibility(View.VISIBLE);
button1.setText(DecimalFormatter.to2Decimal(amount1) + "U");
button1.setOnClickListener(this);
} else {
button1.setVisibility(View.GONE);
}
- if(amount2 >0) {
+ if (amount2 > 0) {
button2.setVisibility(View.VISIBLE);
button2.setText(DecimalFormatter.to2Decimal(amount2) + "U");
button2.setOnClickListener(this);
} else {
button2.setVisibility(View.GONE);
}
- if(amount3 >0) {
+ if (amount3 > 0) {
button3.setVisibility(View.VISIBLE);
button3.setText(DecimalFormatter.to2Decimal(amount3) + "U");
button3.setOnClickListener(this);
@@ -110,7 +105,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
button3.setVisibility(View.GONE);
}
- if (button1.getVisibility() == View.GONE && button2.getVisibility() == View.GONE && button3.getVisibility() == View.GONE ) {
+ if (button1.getVisibility() == View.GONE && button2.getVisibility() == View.GONE && button3.getVisibility() == View.GONE) {
divider.setVisibility(View.GONE);
}
return view;
@@ -127,7 +122,7 @@ public class FillDialog extends DialogFragment implements OnClickListener {
public void onClick(View view) {
switch (view.getId()) {
case R.id.treatments_newtreatment_deliverbutton:
- Double insulin = SafeParse.stringToDouble(this.insulin.getText().toString());
+ Double insulin = SafeParse.stringToDouble(editInsulin.getText().toString());
confirmAndDeliver(insulin);
break;
case R.id.fill_preset_button1:
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 be635e76b6..0b7445e9e7 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
@@ -11,9 +11,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.RadioButton;
import com.crashlytics.android.answers.Answers;
import com.crashlytics.android.answers.CustomEvent;
@@ -30,14 +27,14 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
-import info.nightscout.utils.PlusMinusEditText;
+import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewExtendedBolusDialog.class);
- PlusMinusEditText editInsulin;
- PlusMinusEditText editDuration;
+ NumberPicker editInsulin;
+ NumberPicker editDuration;
Handler mHandler;
public static HandlerThread mHandlerThread;
@@ -56,11 +53,13 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false);
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);
+ editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
+ editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false);
double extendedDurationStep = MainApp.getConfigBuilder().getPumpDescription().extendedBolusDurationStep;
double extendedMaxDuration = MainApp.getConfigBuilder().getPumpDescription().extendedBolusMaxDuration;
- 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);
+ editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
+ editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
@@ -107,11 +106,11 @@ public class NewExtendedBolusDialog extends DialogFragment implements View.OnCli
PumpEnactResult result = pump.setExtendedBolus(finalInsulin, finalDurationInMinutes);
if (!result.success) {
try {
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(context.getString(R.string.treatmentdeliveryerror));
- builder.setMessage(result.comment);
- builder.setPositiveButton(context.getString(R.string.ok), null);
- builder.show();
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(context.getString(R.string.treatmentdeliveryerror));
+ builder.setMessage(result.comment);
+ builder.setPositiveButton(context.getString(R.string.ok), null);
+ builder.show();
} catch (WindowManager.BadTokenException | NullPointerException e) {
// window has been destroyed
Notification notification = new Notification(Notification.BOLUS_DELIVERY_ERROR, MainApp.sResources.getString(R.string.treatmentdeliveryerror), Notification.URGENT);
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 9bd6cd26c9..68652b0a8b 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
@@ -14,7 +14,6 @@ import android.view.ViewGroup;
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;
@@ -26,12 +25,11 @@ import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
-import info.nightscout.androidaps.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 {
@@ -74,7 +72,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
PumpDescription pumpDescription = MainApp.getConfigBuilder().getPumpDescription();
- basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
+ 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);
@@ -159,7 +157,7 @@ public class NewTempBasalDialog extends DialogFragment implements View.OnClickLi
if (setAsPercent) {
result = pump.setTempBasalPercent(finalBasalPercent, finalDurationInMinutes);
} else {
- result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes, false);
+ result = pump.setTempBasalAbsolute(finalBasal, finalDurationInMinutes, true);
}
if (!result.success) {
if (context instanceof Activity) {
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 6550959867..d832d2aab0 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
@@ -3,9 +3,7 @@ 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;
@@ -18,7 +16,6 @@ import com.squareup.otto.Subscribe;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
-import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange;
@@ -47,27 +44,28 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
return careportalPlugin;
}
- // bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget
- 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);
+ // date,bg,insulin,carbs,prebolus,duration,percent,absolute,profile,split,temptarget
+ public static final OptionsToShow BGCHECK = new OptionsToShow(R.id.careportal_bgcheck, R.string.careportal_bgcheck).date().bg();
+ public static final OptionsToShow SNACKBOLUS = new OptionsToShow(R.id.careportal_snackbolus, R.string.careportal_snackbolus).date().bg().insulin().carbs().prebolus();
+ public static final OptionsToShow MEALBOLUS = new OptionsToShow(R.id.careportal_mealbolus, R.string.careportal_mealbolus).date().bg().insulin().carbs().prebolus();
+ public static final OptionsToShow CORRECTIONBOLUS = new OptionsToShow(R.id.careportal_correctionbolus, R.string.careportal_correctionbolus).date().bg().insulin().carbs().prebolus();
+ public static final OptionsToShow CARBCORRECTION = new OptionsToShow(R.id.careportal_carbscorrection, R.string.careportal_carbscorrection).date().bg().carbs();
+ public static final OptionsToShow COMBOBOLUS = new OptionsToShow(R.id.careportal_combobolus, R.string.careportal_combobolus).date().bg().insulin().carbs().prebolus().duration().split();
+ public static final OptionsToShow ANNOUNCEMENT = new OptionsToShow(R.id.careportal_announcement, R.string.careportal_announcement).date().bg();
+ public static final OptionsToShow NOTE = new OptionsToShow(R.id.careportal_note, R.string.careportal_note).date().bg().duration();
+ public static final OptionsToShow QUESTION = new OptionsToShow(R.id.careportal_question, R.string.careportal_question).date().bg();
+ public static final OptionsToShow EXERCISE = new OptionsToShow(R.id.careportal_exercise, R.string.careportal_exercise).date().duration();
+ public static final OptionsToShow SITECHANGE = new OptionsToShow(R.id.careportal_pumpsitechange, R.string.careportal_pumpsitechange).date().bg();
+ public static final OptionsToShow SENSORSTART = new OptionsToShow(R.id.careportal_cgmsensorstart, R.string.careportal_cgmsensorstart).date().bg();
+ public static final OptionsToShow SENSORCHANGE = new OptionsToShow(R.id.careportal_cgmsensorinsert, R.string.careportal_cgmsensorinsert).date().bg();
+ public static final OptionsToShow INSULINCHANGE = new OptionsToShow(R.id.careportal_insulincartridgechange, R.string.careportal_insulincartridgechange).date().bg();
+ public static final OptionsToShow PUMPBATTERYCHANGE = new OptionsToShow(R.id.careportal_pumpbatterychange, R.string.careportal_pumpbatterychange).date().bg();
+ public static final OptionsToShow TEMPBASALSTART = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart).date().bg().duration().percent().absolute();
+ public static final OptionsToShow TEMPBASALEND = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend).date().bg();
+ public static final OptionsToShow PROFILESWITCH = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).date().duration().profile();
+ public static final OptionsToShow PROFILESWITCHDIRECT = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).duration().profile();
+ public static final OptionsToShow OPENAPSOFFLINE = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline).date().duration();
+ public static final OptionsToShow TEMPTARGET = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget).date().duration().tempTarget();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -136,66 +134,66 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
switch (id) {
case R.id.careportal_bgcheck:
- newDialog.setOptions(bgcheck, R.string.careportal_bgcheck);
+ newDialog.setOptions(BGCHECK, R.string.careportal_bgcheck);
break;
case R.id.careportal_announcement:
- newDialog.setOptions(announcement, R.string.careportal_announcement);
+ newDialog.setOptions(ANNOUNCEMENT, R.string.careportal_announcement);
break;
case R.id.careportal_cgmsensorinsert:
- newDialog.setOptions(sensorchange, R.string.careportal_cgmsensorinsert);
+ newDialog.setOptions(SENSORCHANGE, R.string.careportal_cgmsensorinsert);
break;
case R.id.careportal_cgmsensorstart:
- newDialog.setOptions(sensorstart, R.string.careportal_cgmsensorstart);
+ newDialog.setOptions(SENSORSTART, R.string.careportal_cgmsensorstart);
break;
case R.id.careportal_combobolus:
- newDialog.setOptions(combobolus, R.string.careportal_combobolus);
+ newDialog.setOptions(COMBOBOLUS, R.string.careportal_combobolus);
break;
case R.id.careportal_correctionbolus:
- newDialog.setOptions(correctionbolus, R.string.careportal_correctionbolus);
+ newDialog.setOptions(CORRECTIONBOLUS, R.string.careportal_correctionbolus);
break;
case R.id.careportal_carbscorrection:
- newDialog.setOptions(carbcorrection, R.string.careportal_carbscorrection);
+ newDialog.setOptions(CARBCORRECTION, R.string.careportal_carbscorrection);
break;
case R.id.careportal_exercise:
- newDialog.setOptions(exercise, R.string.careportal_exercise);
+ newDialog.setOptions(EXERCISE, R.string.careportal_exercise);
break;
case R.id.careportal_insulincartridgechange:
- newDialog.setOptions(insulinchange, R.string.careportal_insulincartridgechange);
+ newDialog.setOptions(INSULINCHANGE, R.string.careportal_insulincartridgechange);
break;
case R.id.careportal_pumpbatterychange:
- newDialog.setOptions(pumpbatterychange, R.string.careportal_pumpbatterychange);
+ newDialog.setOptions(PUMPBATTERYCHANGE, R.string.careportal_pumpbatterychange);
break;
case R.id.careportal_mealbolus:
- newDialog.setOptions(mealbolus, R.string.careportal_mealbolus);
+ newDialog.setOptions(MEALBOLUS, R.string.careportal_mealbolus);
break;
case R.id.careportal_note:
- newDialog.setOptions(note, R.string.careportal_note);
+ newDialog.setOptions(NOTE, R.string.careportal_note);
break;
case R.id.careportal_profileswitch:
- profileswitch.executeProfileSwitch = false;
- newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
+ PROFILESWITCH.executeProfileSwitch = false;
+ newDialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch);
break;
case R.id.careportal_pumpsitechange:
- newDialog.setOptions(sitechange, R.string.careportal_pumpsitechange);
+ newDialog.setOptions(SITECHANGE, R.string.careportal_pumpsitechange);
break;
case R.id.careportal_question:
- newDialog.setOptions(question, R.string.careportal_question);
+ newDialog.setOptions(QUESTION, R.string.careportal_question);
break;
case R.id.careportal_snackbolus:
- newDialog.setOptions(snackbolus, R.string.careportal_snackbolus);
+ newDialog.setOptions(SNACKBOLUS, R.string.careportal_snackbolus);
break;
case R.id.careportal_tempbasalstart:
- newDialog.setOptions(tempbasalstart, R.string.careportal_tempbasalstart);
+ newDialog.setOptions(TEMPBASALSTART, R.string.careportal_tempbasalstart);
break;
case R.id.careportal_tempbasalend:
- newDialog.setOptions(tempbasalend, R.string.careportal_tempbasalend);
+ newDialog.setOptions(TEMPBASALEND, R.string.careportal_tempbasalend);
break;
case R.id.careportal_openapsoffline:
- newDialog.setOptions(openapsoffline, R.string.careportal_openapsoffline);
+ newDialog.setOptions(OPENAPSOFFLINE, R.string.careportal_openapsoffline);
break;
case R.id.careportal_temporarytarget:
- temptarget.executeTempTarget = false;
- newDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
+ TEMPTARGET.executeTempTarget = false;
+ newDialog.setOptions(TEMPTARGET, R.string.careportal_temporarytarget);
break;
default:
newDialog = null;
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 ec5a267dcc..1b976195ae 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
@@ -16,6 +16,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
@@ -53,7 +54,6 @@ import info.nightscout.androidaps.events.EventNewBasalProfile;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker;
@@ -74,17 +74,11 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
String units;
TextView eventTypeText;
- LinearLayout layoutBg;
- LinearLayout layoutBgSource;
- LinearLayout layoutInsulin;
- LinearLayout layoutCarbs;
- LinearLayout layoutSplit;
- LinearLayout layoutDuration;
LinearLayout layoutPercent;
LinearLayout layoutAbsolute;
- LinearLayout layoutCarbTime;
- LinearLayout layoutProfile;
- LinearLayout layoutTempTarget;
+ LinearLayout layoutReuse;
+
+
TextView dateButton;
TextView timeButton;
@@ -95,6 +89,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
EditText notesEdit;
Spinner profileSpinner;
Spinner reasonSpinner;
+ Button reuseButton;
NumberPicker editBg;
NumberPicker editCarbs;
@@ -105,6 +100,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
NumberPicker editAbsolute;
NumberPicker editCarbTime;
NumberPicker editTemptarget;
+ NumberPicker editPercentage;
+ NumberPicker editTimeshift;
Date eventTime;
@@ -145,17 +142,10 @@ 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 = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bg_layout);
- layoutBgSource = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_bgsource_layout);
- layoutInsulin = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_insulin_layout);
- layoutCarbs = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbs_layout);
- layoutSplit = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_split_layout);
- layoutDuration = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_duration_layout);
layoutPercent = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_percent_layout);
layoutAbsolute = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_absolute_layout);
- layoutCarbTime = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout);
- layoutProfile = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_profile_layout);
- layoutTempTarget = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout);
+
+ layoutReuse = (LinearLayout) view.findViewById(R.id.careportal_newnstreatment_reuse_layout);
eventTypeText = (TextView) view.findViewById(R.id.careportal_newnstreatment_eventtype);
eventTypeText.setText(event);
@@ -165,6 +155,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
otherRadioButton = (RadioButton) view.findViewById(R.id.careportal_newnstreatment_other);
profileSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_profile);
+ reuseButton = (Button) view.findViewById(R.id.careportal_newnstreatment_reusebutton);
+
notesEdit = (EditText) view.findViewById(R.id.careportal_newnstreatment_notes);
reasonSpinner = (Spinner) view.findViewById(R.id.careportal_newnstreatment_temptarget_reason);
@@ -244,19 +236,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
// bg
bgUnitsView.setText(units);
- 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() {
+ TextWatcher bgTextWatcher = new TextWatcher() {
+
public void afterTextChanged(Editable s) {
}
@@ -266,8 +247,20 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (sensorRadioButton.isChecked()) meterRadioButton.setChecked(true);
}
- });
+ };
+ 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, bgTextWatcher);
+ 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, bgTextWatcher);
+ editTemptarget.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false);
+ } else {
+ editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
+ editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
+ }
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -289,10 +282,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
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() {
+ TextWatcher percentTextWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@@ -308,12 +298,13 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutPercent.setVisibility(View.VISIBLE);
layoutAbsolute.setVisibility(View.GONE);
}
- });
+ };
- 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() {
+ 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, percentTextWatcher);
+
+ TextWatcher absoluteTextWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@@ -329,23 +320,50 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
layoutPercent.setVisibility(View.GONE);
layoutAbsolute.setVisibility(View.VISIBLE);
}
- });
+ };
+
+ 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, absoluteTextWatcher);
editCarbTime = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_carbtimeinput);
editCarbTime.setParams(0d, -60d, 60d, 5d, new DecimalFormat("0"), false);
+ editPercentage = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_percentage);
+ editPercentage.setParams(100d, (double) Constants.CPP_MIN_PERCENTAGE, (double) Constants.CPP_MAX_PERCENTAGE, 1d, new DecimalFormat("0"), false);
- showOrHide(layoutBg, options.bg);
- showOrHide(layoutBgSource, options.bg);
- showOrHide(layoutInsulin, options.insulin);
- showOrHide(layoutCarbs, options.carbs);
- showOrHide(layoutSplit, options.split);
- showOrHide(layoutDuration, options.duration);
+ editTimeshift = (NumberPicker) view.findViewById(R.id.careportal_newnstreatment_timeshift);
+ editTimeshift.setParams(0d, (double) Constants.CPP_MIN_TIMESHIFT, (double) Constants.CPP_MAX_TIMESHIFT, 1d, new DecimalFormat("0"), false);
+
+ ProfileSwitch ps = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
+ if(ps!=null && ps.isCPP){
+ final int percentage = ps.percentage;
+ final int timeshift = ps.timeshift;
+ reuseButton.setText(reuseButton.getText() + " " + percentage + "% " + timeshift +"h");
+ reuseButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ editPercentage.setValue((double)percentage);
+ editTimeshift.setValue((double)timeshift);
+ }
+ });
+ }
+
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_eventtime_layout), options.date);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bg_layout), options.bg);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_bgsource_layout), options.bg);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_insulin_layout), options.insulin);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_carbs_layout), options.carbs);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_split_layout), options.split);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_duration_layout), options.duration);
showOrHide(layoutPercent, options.percent);
showOrHide(layoutAbsolute, options.absolute);
- showOrHide(layoutCarbTime, options.prebolus);
- showOrHide(layoutProfile, options.profile);
- showOrHide(layoutTempTarget, options.tempTarget);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_carbtime_layout), options.prebolus);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_profile_layout), options.profile);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_percentage_layout), options.profile);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_timeshift_layout), options.profile);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_reuse_layout), options.profile && ps!=null && ps.isCPP);
+ showOrHide((ViewGroup) view.findViewById(R.id.careportal_newnstreatment_temptarget_layout), options.tempTarget);
return view;
}
@@ -488,7 +506,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
allowZeroDuration = true;
break;
}
- if (SafeParse.stringToDouble(editBg.getText()) != 0d) {
+ if (options.bg && 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");
@@ -506,6 +524,10 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
data.put("absolute", SafeParse.stringToDouble(editAbsolute.getText()));
if (options.profile && profileSpinner.getSelectedItem() != null)
data.put("profile", profileSpinner.getSelectedItem().toString());
+ if (options.profile)
+ data.put("percentage", SafeParse.stringToInt(editPercentage.getText()));
+ if (options.profile)
+ data.put("timeshift", SafeParse.stringToInt(editTimeshift.getText()));
if (SafeParse.stringToDouble(editCarbTime.getText()) != 0d)
data.put("preBolus", SafeParse.stringToDouble(editCarbTime.getText()));
if (!notesEdit.getText().toString().equals(""))
@@ -593,6 +615,18 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
ret += data.get("profile");
ret += "\n";
}
+ if (data.has("percentage")) {
+ ret += getString(R.string.careportal_newnstreatment_percentage_label);
+ ret += ": ";
+ ret += data.get("percentage");
+ ret += " %\n";
+ }
+ if (data.has("timeshift")) {
+ ret += getString(R.string.careportal_newnstreatment_timeshift_label);
+ ret += ": ";
+ ret += data.get("timeshift");
+ ret += " h\n";
+ }
if (data.has("targetBottom") && data.has("targetTop")) {
ret += getString(R.string.target_range);
ret += " ";
@@ -631,7 +665,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
if (options.executeProfileSwitch) {
if (data.has("profile")) {
try {
- doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"));
+ doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"), data.getInt("percentage"), data.getInt("timeshift"));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@@ -678,33 +712,63 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
builder.show();
}
- public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration) {
+ public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
sHandler.post(new Runnable() {
@Override
public void run() {
- ProfileSwitch profileSwitch = new ProfileSwitch();
+ ProfileSwitch profileSwitch = new ProfileSwitch();
+ profileSwitch.date = System.currentTimeMillis();
+ profileSwitch.source = Source.USER;
+ profileSwitch.profileName = profileName;
+ profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
+ profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
+ profileSwitch.durationInMinutes = duration;
+ profileSwitch.isCPP = percentage != 100 || timeshift != 0;
+ profileSwitch.timeshift = timeshift;
+ profileSwitch.percentage = percentage;
+ MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
+
+ PumpInterface pump = MainApp.getConfigBuilder();
+ if (pump != null) {
+ pump.setNewBasalProfile(profileSwitch.getProfileObject());
+ MainApp.bus().post(new EventNewBasalProfile());
+ } else {
+ log.error("No active pump selected");
+ }
+ Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
+ }
+ });
+ }
+
+ public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
+ if (profileSwitch != null) {
+ profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
- profileSwitch.profileName = profileName;
- profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
+ profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
+ profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().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;
- }
+ profileSwitch.isCPP = percentage != 100 || timeshift != 0;
+ profileSwitch.timeshift = timeshift;
+ profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
PumpInterface pump = MainApp.getConfigBuilder();
if (pump != null) {
- pump.setNewBasalProfile(profileStore.getSpecificProfile(profileName));
+ pump.setNewBasalProfile(profileSwitch.getProfileObject());
MainApp.bus().post(new EventNewBasalProfile());
} else {
log.error("No active pump selected");
}
Answers.getInstance().logCustom(new CustomEvent("ProfileSwitch"));
+ } else {
+ log.error("No profile switch existing");
+ }
}
});
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java
index 23ce1dbcde..cbdbe38940 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/OptionsToShow.java
@@ -7,6 +7,7 @@ package info.nightscout.androidaps.plugins.Careportal;
public class OptionsToShow {
public int eventType;
public int eventName;
+ public boolean date;
public boolean bg;
public boolean insulin;
public boolean carbs;
@@ -22,29 +23,63 @@ public class OptionsToShow {
public boolean executeProfileSwitch = false;
public boolean executeTempTarget = false;
- public OptionsToShow(int eventType,
- int eventName,
- boolean bg,
- boolean insulin,
- boolean carbs,
- boolean prebolus,
- boolean duration,
- boolean percent,
- boolean absolute,
- boolean profile,
- boolean split,
- boolean tempTarget) {
+ public OptionsToShow(int eventType, int eventName) {
this.eventType = eventType;
this.eventName = eventName;
- this.bg = bg;
- this.insulin = insulin;
- this.carbs = carbs;
- this.prebolus = prebolus;
- this.duration = duration;
- this.percent = percent;
- this.absolute = absolute;
- this.profile = profile;
- this.split = split;
- this.tempTarget = tempTarget;
+ }
+
+ public OptionsToShow date() {
+ date = true;
+ return this;
+ }
+
+ public OptionsToShow bg() {
+ bg = true;
+ return this;
+ }
+
+ public OptionsToShow insulin() {
+ insulin = true;
+ return this;
+ }
+
+ public OptionsToShow carbs() {
+ carbs = true;
+ return this;
+ }
+
+ public OptionsToShow prebolus() {
+ prebolus = true;
+ return this;
+ }
+
+ public OptionsToShow duration() {
+ duration = true;
+ return this;
+ }
+
+ public OptionsToShow percent() {
+ percent = true;
+ return this;
+ }
+
+ public OptionsToShow absolute() {
+ absolute = true;
+ return this;
+ }
+
+ public OptionsToShow profile() {
+ profile = true;
+ return this;
+ }
+
+ public OptionsToShow split() {
+ split = true;
+ return this;
+ }
+
+ public OptionsToShow tempTarget() {
+ tempTarget = true;
+ return this;
}
}
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 ffc5c3426f..b60ab20d88 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
@@ -216,7 +216,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
return activePump;
}
- public static SensitivityInterface getActiveSensitivity() {
+ public static SensitivityInterface getActiveSensitivity() {
return activeSensitivity;
}
@@ -574,7 +574,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
if (Config.logCongigBuilderActions)
log.debug("applyAPSRequest: Basal set correctly");
}
- } else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < 0.05) {
+ } else if (isTempBasalInProgress() && Math.abs(request.rate - getTempBasalAbsoluteRateHistory()) < getPumpDescription().basalStep) {
result = new PumpEnactResult();
result.absolute = getTempBasalAbsoluteRateHistory();
result.duration = getTempBasalFromHistory(System.currentTimeMillis()).getPlannedRemainingMinutes();
@@ -934,10 +934,14 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
}
public String getProfileName(long time) {
+ return getProfileName(time, true);
+ }
+
+ public String getProfileName(long time, boolean customized) {
ProfileSwitch profileSwitch = getProfileSwitchFromHistory(time);
if (profileSwitch != null) {
if (profileSwitch.profileJson != null) {
- return profileSwitch.profileName;
+ return customized ? profileSwitch.getCustomizedName() : profileSwitch.profileName;
} else {
Profile profile = activeProfile.getProfile().getSpecificProfile(profileSwitch.profileName);
if (profile != null)
@@ -993,7 +997,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
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\"}}"));
+ 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\"}}"), 100, 0);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
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 d4193f3cb7..65a90f3b74 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
@@ -46,22 +46,28 @@ public class BroadcastSgvs {
}
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);
- LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
- if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
- bundle = new Bundle();
- bundle.putString("sgvs", sgvs.toString());
+ List splitted = BroadcastTreatment.splitArray(sgvs);
+ for (JSONArray part : splitted) {
+ Bundle bundle = new Bundle();
+ bundle.putString("sgvs", part.toString());
bundle.putBoolean("delta", isDelta);
- intent = new Intent(Intents.ACTION_NEW_SGV);
+ Intent intent = new Intent(Intents.ACTION_NEW_SGV);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
- context.sendBroadcast(intent);
+ LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
+ }
+
+ if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
+ for (JSONArray part : splitted) {
+ Bundle bundle = new Bundle();
+ bundle.putString("sgvs", part.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);
+ }
}
}
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 3fd608475f..d3d17b510b 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
@@ -9,6 +9,7 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.PowerManager;
+import com.crashlytics.android.Crashlytics;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.j256.ormlite.dao.CloseableIterator;
@@ -322,12 +323,18 @@ public class NSClientService extends Service {
*/
@Override
public void call(final Object... args) {
- JSONObject data = (JSONObject) args[0];
+ JSONObject data;
+ try {
+ data = (JSONObject) args[0];
+ } catch (Exception e) {
+ Crashlytics.log("Wrong Announcement from NS: " + args[0]);
+ return;
+ }
if (Config.detailedLog)
try {
MainApp.bus().post(new EventNSClientNewLog("ANNOUNCEMENT", data.has("message") ? data.getString("message") : "received"));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
+ } catch (Exception e) {
+ Crashlytics.logException(e);
}
BroadcastAnnouncement.handleAnnouncement(data, getApplicationContext());
log.debug(data.toString());
@@ -352,7 +359,13 @@ public class NSClientService extends Service {
public void call(final Object... args) {
if (Config.detailedLog)
MainApp.bus().post(new EventNSClientNewLog("ALARM", "received"));
- JSONObject data = (JSONObject) args[0];
+ JSONObject data;
+ try {
+ data = (JSONObject) args[0];
+ } catch (Exception e) {
+ Crashlytics.log("Wrong alarm from NS: " + args[0]);
+ return;
+ }
BroadcastAlarm.handleAlarm(data, getApplicationContext());
log.debug(data.toString());
}
@@ -374,7 +387,13 @@ public class NSClientService extends Service {
*/
@Override
public void call(final Object... args) {
- JSONObject data = (JSONObject) args[0];
+ JSONObject data;
+ try {
+ data = (JSONObject) args[0];
+ } catch (Exception e) {
+ Crashlytics.log("Wrong Urgent alarm from NS: " + args[0]);
+ return;
+ }
if (Config.detailedLog)
MainApp.bus().post(new EventNSClientNewLog("URGENTALARM", "received"));
BroadcastUrgentAlarm.handleUrgentAlarm(data, getApplicationContext());
@@ -393,9 +412,15 @@ public class NSClientService extends Service {
*/
@Override
public void call(final Object... args) {
+ JSONObject data;
+ try {
+ data = (JSONObject) args[0];
+ } catch (Exception e) {
+ Crashlytics.log("Wrong Urgent alarm from NS: " + args[0]);
+ return;
+ }
if (Config.detailedLog)
MainApp.bus().post(new EventNSClientNewLog("CLEARALARM", "received"));
- JSONObject data = (JSONObject) args[0];
BroadcastClearAlarm.handleClearAlarm(data, getApplicationContext());
log.debug(data.toString());
}
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 44ab8ecb14..3102ac95d6 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java
@@ -1,16 +1,22 @@
package info.nightscout.androidaps.plugins.OpenAPSAMA;
-import com.eclipsesource.v8.JavaVoidCallback;
-import com.eclipsesource.v8.V8;
-import com.eclipsesource.v8.V8Array;
-import com.eclipsesource.v8.V8Object;
-
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeJSON;
+import org.mozilla.javascript.NativeObject;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Undefined;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import info.nightscout.androidaps.Config;
@@ -24,6 +30,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.ScriptReader;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
import info.nightscout.utils.SP;
public class DetermineBasalAdapterAMAJS {
@@ -31,20 +38,13 @@ public class DetermineBasalAdapterAMAJS {
private ScriptReader mScriptReader = null;
- V8 mV8rt;
- private V8Object mProfile;
- private V8Object mGlucoseStatus;
- private V8Array mIobData;
- private V8Object mMealData;
- private V8Object mCurrentTemp;
- private V8Object mAutosensData = null;
- private final String PARAM_currentTemp = "currentTemp";
- private final String PARAM_iobData = "iobData";
- private final String PARAM_glucoseStatus = "glucose_status";
- private final String PARAM_profile = "profile";
- private final String PARAM_meal_data = "meal_data";
- private final String PARAM_autosens_data = "autosens_data";
+ private JSONObject mProfile;
+ private JSONObject mGlucoseStatus;
+ private JSONArray mIobData;
+ private JSONObject mMealData;
+ private JSONObject mCurrentTemp;
+ private JSONObject mAutosensData = null;
private String storedCurrentTemp = null;
private String storedIobData = null;
@@ -55,58 +55,101 @@ public class DetermineBasalAdapterAMAJS {
private String scriptDebug = "";
- /**
- * Main code
- */
-
public DetermineBasalAdapterAMAJS(ScriptReader scriptReader) throws IOException {
- mV8rt = V8.createV8Runtime();
mScriptReader = scriptReader;
-
- initLogCallback();
- initProcessExitCallback();
- initModuleParent();
- loadScript();
}
public DetermineBasalResultAMA invoke() {
+
log.debug(">>> Invoking detemine_basal <<<");
- log.debug("Glucose status: " + (storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");")));
- log.debug("IOB data: " + (storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");")));
- log.debug("Current temp: " + (storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");")));
- log.debug("Profile: " + (storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");")));
- log.debug("Meal data: " + (storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");")));
+ log.debug("Glucose status: " + (storedGlucoseStatus = mGlucoseStatus.toString()));
+ log.debug("IOB data: " + (storedIobData = mIobData.toString()));
+ log.debug("Current temp: " + (storedCurrentTemp = mCurrentTemp.toString()));
+ log.debug("Profile: " + (storedProfile = mProfile.toString()));
+ log.debug("Meal data: " + (storedMeal_data = mMealData.toString()));
if (mAutosensData != null)
- log.debug("Autosens data: " + (storedAutosens_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_autosens_data + ");")));
+ log.debug("Autosens data: " + (storedAutosens_data = mAutosensData.toString()));
else
log.debug("Autosens data: " + (storedAutosens_data = "undefined"));
- mV8rt.executeVoidScript(
- "var rT = determine_basal(" +
- PARAM_glucoseStatus + ", " +
- PARAM_currentTemp + ", " +
- PARAM_iobData + ", " +
- PARAM_profile + ", " +
- PARAM_autosens_data + ", " +
- PARAM_meal_data + ", " +
- "tempBasalFunctions" +
- ");");
+ DetermineBasalResultAMA determineBasalResultAMA = null;
+ Context rhino = Context.enter();
+ Scriptable scope = rhino.initStandardObjects();
+ // Turn off optimization to make Rhino Android compatible
+ rhino.setOptimizationLevel(-1);
- String ret = mV8rt.executeStringScript("JSON.stringify(rT);");
- log.debug("Result: " + ret);
-
- V8Object v8ObjectReuslt = mV8rt.getObject("rT");
-
- DetermineBasalResultAMA result = null;
try {
- result = new DetermineBasalResultAMA(v8ObjectReuslt, new JSONObject(ret));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
+
+ //register logger callback for console.log and console.error
+ ScriptableObject.defineClass(scope, LoggerCallback.class);
+ Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null);
+ scope.put("console2", scope, myLogger);
+ rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null);
+
+ //set module parent
+ rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null);
+ rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null);
+ rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null);
+
+ //generate functions "determine_basal" and "setTempBasal"
+ rhino.evaluateString(scope, readFile("OpenAPSAMA/determine-basal.js"), "JavaScript", 0, null);
+ rhino.evaluateString(scope, readFile("OpenAPSAMA/basal-set-temp.js"), "setTempBasal.js", 0, null);
+ Object determineBasalObj = scope.get("determine_basal", scope);
+ Object setTempBasalFunctionsObj = scope.get("tempBasalFunctions", scope);
+
+ //call determine-basal
+ if (determineBasalObj instanceof Function && setTempBasalFunctionsObj instanceof NativeObject) {
+ Function determineBasalJS = (Function) determineBasalObj;
+
+ //prepare parameters
+ Object[] params = new Object[]{
+ makeParam(mGlucoseStatus, rhino, scope),
+ makeParam(mCurrentTemp, rhino, scope),
+ makeParamArray(mIobData, rhino, scope),
+ makeParam(mProfile, rhino, scope),
+ makeParam(mAutosensData, rhino, scope),
+ makeParam(mMealData, rhino, scope),
+ setTempBasalFunctionsObj};
+
+ NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params);
+ scriptDebug = LoggerCallback.getScriptDebug();
+
+ // Parse the jsResult object to a JSON-String
+ String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString();
+ if (Config.logAPSResult)
+ log.debug("Result: " + result);
+ try {
+ determineBasalResultAMA = new DetermineBasalResultAMA(jsResult, new JSONObject(result));
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+ } else {
+ log.debug("Problem loading JS Functions");
+ }
+ } catch (IOException e) {
+ log.debug("IOException");
+ } catch (RhinoException e) {
+ log.error("RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString());
+ } catch (IllegalAccessException e) {
+ log.error(e.toString());
+ } catch (InstantiationException e) {
+ log.error(e.toString());
+ } catch (InvocationTargetException e) {
+ log.error(e.toString());
+ } finally {
+ Context.exit();
}
- return result;
+ storedGlucoseStatus = mGlucoseStatus.toString();
+ storedIobData = mIobData.toString();
+ storedCurrentTemp = mCurrentTemp.toString();
+ storedProfile = mProfile.toString();
+ storedMeal_data = mMealData.toString();
+
+ return determineBasalResultAMA;
+
}
String getGlucoseStatusParam() {
@@ -137,60 +180,6 @@ public class DetermineBasalAdapterAMAJS {
return scriptDebug;
}
- private void loadScript() throws IOException {
- mV8rt.executeVoidScript("var round_basal = function round_basal(basal, profile) { return basal; };");
- mV8rt.executeVoidScript("require = function() {return round_basal;};");
-
- mV8rt.executeVoidScript(readFile("OpenAPSAMA/basal-set-temp.js"), "OpenAPSAMA/basal-set-temp.js ", 0);
- mV8rt.executeVoidScript("var tempBasalFunctions = module.exports;");
-
- mV8rt.executeVoidScript(
- readFile("OpenAPSAMA/determine-basal.js"),
- "OpenAPSAMA/determine-basal.js",
- 0);
- mV8rt.executeVoidScript("var determine_basal = module.exports;");
- }
-
- private void initModuleParent() {
- mV8rt.executeVoidScript("var module = {\"parent\":Boolean(1)};");
- }
-
- private void initProcessExitCallback() {
- JavaVoidCallback callbackProccessExit = new JavaVoidCallback() {
- @Override
- public void invoke(V8Object arg0, V8Array parameters) {
- if (parameters.length() > 0) {
- Object arg1 = parameters.get(0);
- log.error("ProccessExit " + arg1);
- }
- }
- };
- mV8rt.registerJavaMethod(callbackProccessExit, "proccessExit");
- mV8rt.executeVoidScript("var process = {\"exit\": function () { proccessExit(); } };");
- }
-
- private void initLogCallback() {
- JavaVoidCallback callbackLog = new JavaVoidCallback() {
- @Override
- public void invoke(V8Object arg0, V8Array parameters) {
- int i = 0;
- String s = "";
- while (i < parameters.length()) {
- Object arg = parameters.get(i);
- s += arg + " ";
- i++;
- }
- if (!s.equals("") && Config.logAPSResult) {
- log.debug("Script debug: " + s);
- scriptDebug += s + "\n";
- }
- }
- };
- mV8rt.registerJavaMethod(callbackLog, "log");
- mV8rt.executeVoidScript("var console = {\"log\":log, \"error\":log};");
- }
-
-
public void setData(Profile profile,
double maxIob,
double maxBasal,
@@ -203,89 +192,94 @@ public class DetermineBasalAdapterAMAJS {
MealData mealData,
double autosensDataRatio,
boolean tempTargetSet,
- double min_5m_carbimpact) {
+ double min_5m_carbimpact) throws JSONException {
String units = profile.getUnits();
- mProfile = new V8Object(mV8rt);
- mProfile.add("max_iob", maxIob);
- 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());
- 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);
- mProfile.add("current_basal", pump.getBaseBasalRate());
- mProfile.add("temptargetSet", tempTargetSet);
- mProfile.add("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
- mProfile.add("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));
+ mProfile = new JSONObject();
+ mProfile.put("max_iob", maxIob);
+ mProfile.put("dia", Math.min(profile.getDia(), 3d));
+ mProfile.put("type", "current");
+ mProfile.put("max_daily_basal", profile.getMaxDailyBasal());
+ mProfile.put("max_basal", maxBasal);
+ mProfile.put("min_bg", minBg);
+ mProfile.put("max_bg", maxBg);
+ mProfile.put("target_bg", targetBg);
+ mProfile.put("carb_ratio", profile.getIc());
+ mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
+ mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
+ mProfile.put("current_basal_safety_multiplier", SP.getInt("openapsama_current_basal_safety_multiplier", 4));
+ mProfile.put("skip_neutral_temps", true);
+ mProfile.put("current_basal", pump.getBaseBasalRate());
+ mProfile.put("temptargetSet", tempTargetSet);
+ mProfile.put("autosens_adjust_targets", SP.getBoolean("openapsama_autosens_adjusttargets", true));
+ mProfile.put("min_5m_carbimpact", SP.getDouble("openapsama_min_5m_carbimpact", 3d));
if (units.equals(Constants.MMOL)) {
- mProfile.add("out_units", "mmol/L");
+ mProfile.put("out_units", "mmol/L");
}
- mV8rt.add(PARAM_profile, mProfile);
- mCurrentTemp = new V8Object(mV8rt);
- mCurrentTemp.add("temp", "absolute");
- mCurrentTemp.add("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
- mCurrentTemp.add("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
+ mCurrentTemp = new JSONObject();
+ mCurrentTemp.put("temp", "absolute");
+ mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
+ mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
// as we have non default temps longer than 30 mintues
TemporaryBasal tempBasal = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
if (tempBasal != null) {
- mCurrentTemp.add("minutesrunning", tempBasal.getRealDuration());
+ mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration());
}
- mV8rt.add(PARAM_currentTemp, mCurrentTemp);
+ mIobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray);
- mIobData = mV8rt.executeArrayScript(IobCobCalculatorPlugin.convertToJSONArray(iobArray).toString());
- mV8rt.add(PARAM_iobData, mIobData);
-
- mGlucoseStatus = new V8Object(mV8rt);
- mGlucoseStatus.add("glucose", glucoseStatus.glucose);
+ mGlucoseStatus = new JSONObject();
+ mGlucoseStatus.put("glucose", glucoseStatus.glucose);
if (SP.getBoolean("always_use_shortavg", false)) {
- mGlucoseStatus.add("delta", glucoseStatus.short_avgdelta);
+ mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
} else {
- mGlucoseStatus.add("delta", glucoseStatus.delta);
+ mGlucoseStatus.put("delta", glucoseStatus.delta);
}
- mGlucoseStatus.add("short_avgdelta", glucoseStatus.short_avgdelta);
- mGlucoseStatus.add("long_avgdelta", glucoseStatus.long_avgdelta);
- mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus);
+ mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta);
+ mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta);
- mMealData = new V8Object(mV8rt);
- mMealData.add("carbs", mealData.carbs);
- mMealData.add("boluses", mealData.boluses);
- mMealData.add("mealCOB", mealData.mealCOB);
- mV8rt.add(PARAM_meal_data, mMealData);
+ mMealData = new JSONObject();
+ mMealData.put("carbs", mealData.carbs);
+ mMealData.put("boluses", mealData.boluses);
+ mMealData.put("mealCOB", mealData.mealCOB);
if (MainApp.getConfigBuilder().isAMAModeEnabled()) {
- mAutosensData = new V8Object(mV8rt);
- mAutosensData.add("ratio", autosensDataRatio);
- mV8rt.add(PARAM_autosens_data, mAutosensData);
+ mAutosensData = new JSONObject();
+ mAutosensData.put("ratio", autosensDataRatio);
} else {
- mV8rt.addUndefined(PARAM_autosens_data);
+ mAutosensData = null;
}
}
- public void release() {
- mProfile.release();
- mCurrentTemp.release();
- mIobData.release();
- mMealData.release();
- mGlucoseStatus.release();
- if (mAutosensData != null) {
- mAutosensData.release();
- }
- mV8rt.release();
+ public Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
+
+ if(jsonObject == null) return Undefined.instance;
+
+ Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), new Callable() {
+ @Override
+ public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
+ return objects[1];
+ }
+ });
+ return param;
+ }
+
+ public Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) {
+ //Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() {
+ Object param = NativeJSON.parse(rhino, scope, jsonArray.toString(), new Callable() {
+ @Override
+ public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
+ return objects[1];
+ }
+ });
+ return param;
}
public String readFile(String filename) throws IOException {
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 31501b7032..774ff55401 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
@@ -5,6 +5,7 @@ import com.eclipsesource.v8.V8Object;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.mozilla.javascript.NativeObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,35 +26,34 @@ public class DetermineBasalResultAMA extends APSResult {
public double snoozeBG;
public IobTotal iob;
- public DetermineBasalResultAMA(V8Object result, JSONObject j) {
+ public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
date = new Date();
json = j;
- if (result.contains("error")) {
- reason = result.getString("error");
+ if (result.containsKey("error")) {
+ reason = result.get("error").toString();
changeRequested = false;
rate = -1;
duration = -1;
} else {
- reason = result.getString("reason");
- if (result.contains("eventualBG")) eventualBG = result.getDouble("eventualBG");
- if (result.contains("snoozeBG")) snoozeBG = result.getDouble("snoozeBG");
- if (result.contains("rate")) {
- rate = result.getDouble("rate");
+ reason = result.get("reason").toString();
+ if (result.containsKey("eventualBG")) eventualBG = (Double) result.get("eventualBG");
+ if (result.containsKey("snoozeBG")) snoozeBG = (Double) result.get("snoozeBG");
+ if (result.containsKey("rate")) {
+ rate = (Double) result.get("rate");
if (rate < 0d) rate = 0d;
changeRequested = true;
} else {
rate = -1;
changeRequested = false;
}
- if (result.contains("duration")) {
- duration = result.getInteger("duration");
+ if (result.containsKey("duration")) {
+ duration = ((Double)result.get("duration")).intValue();
//changeRequested as above
} else {
duration = -1;
changeRequested = false;
}
}
- result.release();
}
public DetermineBasalResultAMA() {
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 dfad17de2e..1e574bcc6c 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
@@ -222,11 +222,16 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
Profiler.log(log, "AMA data gathering", start);
start = new Date();
- determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData,
- lastAutosensResult.ratio, //autosensDataRatio
- isTempTarget,
- SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
- );
+
+ try {
+ determineBasalAdapterAMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData,
+ lastAutosensResult.ratio, //autosensDataRatio
+ isTempTarget,
+ SafeParse.stringToDouble(SP.getString("openapsama_min_5m_carbimpact", "3.0"))//min_5m_carbimpact
+ );
+ } catch (JSONException e) {
+ log.error("Unable to set data: " + e.toString());
+ }
DetermineBasalResultAMA determineBasalResultAMA = determineBasalAdapterAMAJS.invoke();
@@ -244,8 +249,6 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
determineBasalResultAMA.iob = iobArray[0];
- determineBasalAdapterAMAJS.release();
-
Date now = new Date();
try {
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 a8f797f8c1..a7e1d5da58 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
@@ -1,16 +1,20 @@
package info.nightscout.androidaps.plugins.OpenAPSMA;
-import com.eclipsesource.v8.JavaVoidCallback;
-import com.eclipsesource.v8.V8;
-import com.eclipsesource.v8.V8Array;
-import com.eclipsesource.v8.V8Object;
-
import org.json.JSONException;
import org.json.JSONObject;
+import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeJSON;
+import org.mozilla.javascript.NativeObject;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
@@ -26,20 +30,12 @@ import info.nightscout.utils.SP;
public class DetermineBasalAdapterMAJS {
private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterMAJS.class);
-
private ScriptReader mScriptReader = null;
- V8 mV8rt;
- private V8Object mProfile;
- private V8Object mGlucoseStatus;
- private V8Object mIobData;
- private V8Object mMealData;
- private V8Object mCurrentTemp;
-
- private final String PARAM_currentTemp = "currentTemp";
- private final String PARAM_iobData = "iobData";
- private final String PARAM_glucoseStatus = "glucose_status";
- private final String PARAM_profile = "profile";
- private final String PARAM_meal_data = "meal_data";
+ private JSONObject mProfile;
+ private JSONObject mGlucoseStatus;
+ private JSONObject mIobData;
+ private JSONObject mMealData;
+ private JSONObject mCurrentTemp;
private String storedCurrentTemp = null;
public String storedIobData = null;
@@ -47,104 +43,90 @@ public class DetermineBasalAdapterMAJS {
private String storedProfile = null;
private String storedMeal_data = null;
- /**
- * Main code
- */
-
public DetermineBasalAdapterMAJS(ScriptReader scriptReader) throws IOException {
- mV8rt = V8.createV8Runtime();
mScriptReader = scriptReader;
-
- init();
- initLogCallback();
- initProcessExitCallback();
- initModuleParent();
- loadScript();
- }
-
- public void init() {
- // Profile
- mProfile = new V8Object(mV8rt);
- mProfile.add("max_iob", 0);
- mProfile.add("dia", 0);
- mProfile.add("type", "current");
- mProfile.add("max_daily_basal", 0);
- mProfile.add("max_basal", 0);
- mProfile.add("max_bg", 0);
- mProfile.add("min_bg", 0);
- mProfile.add("carb_ratio", 0);
- mProfile.add("sens", 0);
- mProfile.add("current_basal", 0);
- mV8rt.add(PARAM_profile, mProfile);
- // Current temp
- mCurrentTemp = new V8Object(mV8rt);
- mCurrentTemp.add("temp", "absolute");
- mCurrentTemp.add("duration", 0);
- mCurrentTemp.add("rate", 0);
- mV8rt.add(PARAM_currentTemp, mCurrentTemp);
- // IOB data
- mIobData = new V8Object(mV8rt);
- mIobData.add("iob", 0); //netIob
- mIobData.add("activity", 0); //netActivity
- mIobData.add("bolussnooze", 0); //bolusIob
- mIobData.add("basaliob", 0);
- mIobData.add("netbasalinsulin", 0);
- mIobData.add("hightempinsulin", 0);
- mV8rt.add(PARAM_iobData, mIobData);
- // Glucose status
- mGlucoseStatus = new V8Object(mV8rt);
- mGlucoseStatus.add("glucose", 0);
- mGlucoseStatus.add("delta", 0);
- mGlucoseStatus.add("avgdelta", 0);
- mV8rt.add(PARAM_glucoseStatus, mGlucoseStatus);
- // Meal data
- mMealData = new V8Object(mV8rt);
- mMealData.add("carbs", 0);
- mMealData.add("boluses", 0);
- mV8rt.add(PARAM_meal_data, mMealData);
}
public DetermineBasalResultMA invoke() {
- 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 + ")+ \") \");"
- );
- mV8rt.executeVoidScript(
- "var rT = determine_basal(" +
- PARAM_glucoseStatus + ", " +
- PARAM_currentTemp + ", " +
- PARAM_iobData + ", " +
- PARAM_profile + ", " +
- "undefined, " +
- PARAM_meal_data + ", " +
- "setTempBasal" +
- ");");
+ DetermineBasalResultMA determineBasalResultMA = null;
+ Context rhino = Context.enter();
+ Scriptable scope = rhino.initStandardObjects();
+ // Turn off optimization to make Rhino Android compatible
+ rhino.setOptimizationLevel(-1);
- String ret = mV8rt.executeStringScript("JSON.stringify(rT);");
- if (Config.logAPSResult)
- log.debug("Result: " + ret);
-
- V8Object v8ObjectReuslt = mV8rt.getObject("rT");
-
- DetermineBasalResultMA result = null;
try {
- result = new DetermineBasalResultMA(v8ObjectReuslt, new JSONObject(ret));
- } catch (JSONException e) {
- log.error("Unhandled exception", e);
+
+ //register logger callback for console.log and console.error
+ ScriptableObject.defineClass(scope, LoggerCallback.class);
+ Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null);
+ scope.put("console", scope, myLogger);
+
+ //set module parent
+ rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null);
+
+ //generate functions "determine_basal" and "setTempBasal"
+ rhino.evaluateString(scope, readFile("OpenAPSMA/determine-basal.js"), "JavaScript", 0, null);
+
+ String setTempBasalCode = "var setTempBasal = function (rate, duration, profile, rT, offline) {" +
+ "rT.duration = duration;\n" +
+ " rT.rate = rate;" +
+ "return rT;" +
+ "};";
+ rhino.evaluateString(scope, setTempBasalCode, "setTempBasal.js", 0, null);
+ Object determineBasalObj = scope.get("determine_basal", scope);
+ Object setTempBasalObj = scope.get("setTempBasal", scope);
+
+ //call determine-basal
+ if (determineBasalObj instanceof Function && setTempBasalObj instanceof Function) {
+ Function determineBasalJS = (Function) determineBasalObj;
+ Function setTempBasalJS = (Function) setTempBasalObj;
+
+ //prepare parameters
+ Object[] params = new Object[]{
+ makeParam(mGlucoseStatus, rhino, scope),
+ makeParam(mCurrentTemp, rhino, scope),
+ makeParam(mIobData, rhino, scope),
+ makeParam(mProfile, rhino, scope),
+ "undefined",
+ makeParam(mMealData, rhino, scope),
+ setTempBasalJS};
+
+ NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params);
+
+ // Parse the jsResult object to a JSON-String
+ String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString();
+ if (Config.logAPSResult)
+ log.debug("Result: " + result);
+ try {
+ determineBasalResultMA = new DetermineBasalResultMA(jsResult, new JSONObject(result));
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+ } else {
+ log.debug("Problem loading JS Functions");
+ }
+ } catch (IOException e) {
+ log.debug("IOException");
+ } catch (RhinoException e) {
+ log.error("RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString());
+ } catch (IllegalAccessException e) {
+ log.error(e.toString());
+ } catch (InstantiationException e) {
+ log.error(e.toString());
+ } catch (InvocationTargetException e) {
+ log.error(e.toString());
+ } finally {
+ Context.exit();
}
- storedGlucoseStatus = mV8rt.executeStringScript("JSON.stringify(" + PARAM_glucoseStatus + ");");
- storedIobData = mV8rt.executeStringScript("JSON.stringify(" + PARAM_iobData + ");");
- storedCurrentTemp = mV8rt.executeStringScript("JSON.stringify(" + PARAM_currentTemp + ");");
- storedProfile = mV8rt.executeStringScript("JSON.stringify(" + PARAM_profile + ");");
- storedMeal_data = mV8rt.executeStringScript("JSON.stringify(" + PARAM_meal_data + ");");
+ storedGlucoseStatus = mGlucoseStatus.toString();
+ storedIobData = mIobData.toString();
+ storedCurrentTemp = mCurrentTemp.toString();
+ storedProfile = mProfile.toString();
+ storedMeal_data = mMealData.toString();
- return result;
+ return determineBasalResultMA;
}
String getGlucoseStatusParam() {
@@ -167,57 +149,6 @@ public class DetermineBasalAdapterMAJS {
return storedMeal_data;
}
- private void loadScript() throws IOException {
- mV8rt.executeVoidScript(
- readFile("OpenAPSMA/determine-basal.js"),
- "OpenAPSMA/bin/oref0-determine-basal.js",
- 0);
- mV8rt.executeVoidScript("var determine_basal = module.exports;");
- mV8rt.executeVoidScript(
- "var setTempBasal = function (rate, duration, profile, rT, offline) {" +
- "rT.duration = duration;\n" +
- " rT.rate = rate;" +
- "return rT;" +
- "};",
- "setTempBasal.js",
- 0
- );
- }
-
- private void initModuleParent() {
- mV8rt.executeVoidScript("var module = {\"parent\":Boolean(1)};");
- }
-
- private void initProcessExitCallback() {
- JavaVoidCallback callbackProccessExit = new JavaVoidCallback() {
- @Override
- public void invoke(V8Object arg0, V8Array parameters) {
- if (parameters.length() > 0) {
- Object arg1 = parameters.get(0);
- log.error("ProccessExit " + arg1);
- }
- }
- };
- mV8rt.registerJavaMethod(callbackProccessExit, "proccessExit");
- mV8rt.executeVoidScript("var process = {\"exit\": function () { proccessExit(); } };");
- }
-
- private void initLogCallback() {
- JavaVoidCallback callbackLog = new JavaVoidCallback() {
- @Override
- public void invoke(V8Object arg0, V8Array parameters) {
- if (parameters.length() > 0) {
- Object arg1 = parameters.get(0);
- if (Config.logAPSResult)
- log.debug("Input params: " + arg1);
- }
- }
- };
- mV8rt.registerJavaMethod(callbackLog, "log");
- mV8rt.executeVoidScript("var console = {\"log\":log, \"error\":log};");
- }
-
-
public void setData(Profile profile,
double maxIob,
double maxBasal,
@@ -227,57 +158,52 @@ public class DetermineBasalAdapterMAJS {
PumpInterface pump,
IobTotal iobData,
GlucoseStatus glucoseStatus,
- MealData mealData) {
+ MealData mealData) throws JSONException {
String units = profile.getUnits();
- mProfile.add("max_iob", maxIob);
- 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());
- mProfile.add("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
+ mProfile = new JSONObject();
+ mProfile.put("max_iob", maxIob);
+ mProfile.put("dia", Math.min(profile.getDia(), 3d));
+ mProfile.put("type", "current");
+ mProfile.put("max_daily_basal", profile.getMaxDailyBasal());
+ mProfile.put("max_basal", maxBasal);
+ mProfile.put("min_bg", minBg);
+ mProfile.put("max_bg", maxBg);
+ mProfile.put("target_bg", targetBg);
+ mProfile.put("carb_ratio", profile.getIc());
+ mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
- mProfile.add("current_basal", pump.getBaseBasalRate());
+ mProfile.put("current_basal", pump.getBaseBasalRate());
if (units.equals(Constants.MMOL)) {
- mProfile.add("out_units", "mmol/L");
+ mProfile.put("out_units", "mmol/L");
}
- mCurrentTemp.add("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
- mCurrentTemp.add("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
+ mCurrentTemp = new JSONObject();
+ mCurrentTemp.put("duration", MainApp.getConfigBuilder().getTempBasalRemainingMinutesFromHistory());
+ mCurrentTemp.put("rate", MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory());
- mIobData.add("iob", iobData.iob); //netIob
- mIobData.add("activity", iobData.activity); //netActivity
- mIobData.add("bolussnooze", iobData.bolussnooze); //bolusIob
- mIobData.add("basaliob", iobData.basaliob);
- mIobData.add("netbasalinsulin", iobData.netbasalinsulin);
- mIobData.add("hightempinsulin", iobData.hightempinsulin);
+ mIobData = new JSONObject();
+ mIobData.put("iob", iobData.iob); //netIob
+ mIobData.put("activity", iobData.activity); //netActivity
+ mIobData.put("bolussnooze", iobData.bolussnooze); //bolusIob
+ mIobData.put("basaliob", iobData.basaliob);
+ mIobData.put("netbasalinsulin", iobData.netbasalinsulin);
+ mIobData.put("hightempinsulin", iobData.hightempinsulin);
- mGlucoseStatus.add("glucose", glucoseStatus.glucose);
+ mGlucoseStatus = new JSONObject();
+ mGlucoseStatus.put("glucose", glucoseStatus.glucose);
if (SP.getBoolean("always_use_shortavg", false)) {
- mGlucoseStatus.add("delta", glucoseStatus.short_avgdelta);
+ mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta);
} else {
- mGlucoseStatus.add("delta", glucoseStatus.delta);
+ mGlucoseStatus.put("delta", glucoseStatus.delta);
}
- mGlucoseStatus.add("avgdelta", glucoseStatus.avgdelta);
+ mGlucoseStatus.put("avgdelta", glucoseStatus.avgdelta);
- mMealData.add("carbs", mealData.carbs);
- mMealData.add("boluses", mealData.boluses);
- }
-
-
- public void release() {
- mProfile.release();
- mCurrentTemp.release();
- mIobData.release();
- mMealData.release();
- mGlucoseStatus.release();
- mV8rt.release();
+ mMealData = new JSONObject();
+ mMealData.put("carbs", mealData.carbs);
+ mMealData.put("boluses", mealData.boluses);
}
public String readFile(String filename) throws IOException {
@@ -289,4 +215,14 @@ public class DetermineBasalAdapterMAJS {
return string;
}
+ public Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
+ Object param = NativeJSON.parse(rhino, scope, jsonObject.toString(), new Callable() {
+ @Override
+ public Object call(Context context, Scriptable scriptable, Scriptable scriptable1, Object[] objects) {
+ return objects[1];
+ }
+ });
+ return param;
+ }
+
}
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 23f7c14a88..e132c9f953 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
@@ -1,12 +1,8 @@
package info.nightscout.androidaps.plugins.OpenAPSMA;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.eclipsesource.v8.V8Object;
-
import org.json.JSONException;
import org.json.JSONObject;
+import org.mozilla.javascript.NativeObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,38 +18,37 @@ public class DetermineBasalResultMA extends APSResult {
public String mealAssist;
public IobTotal iob;
- public DetermineBasalResultMA(V8Object result, JSONObject j) {
+ public DetermineBasalResultMA(NativeObject result, JSONObject j) {
json = j;
- if (result.contains("error")) {
- reason = result.getString("error");
+ if (result.containsKey("error")) {
+ reason = (String) result.get("error");
changeRequested = false;
rate = -1;
duration = -1;
mealAssist = "";
} else {
- reason = result.getString("reason");
- eventualBG = result.getDouble("eventualBG");
- snoozeBG = result.getDouble("snoozeBG");
- if (result.contains("rate")) {
- rate = result.getDouble("rate");
+ reason = result.get("reason").toString();
+ eventualBG = (Double) result.get("eventualBG");
+ snoozeBG = (Double) result.get("snoozeBG");
+ if (result.containsKey("rate")) {
+ rate = (Double) result.get("rate");
if (rate < 0d) rate = 0d;
changeRequested = true;
} else {
rate = -1;
changeRequested = false;
}
- if (result.contains("duration")) {
- duration = result.getInteger("duration");
+ if (result.containsKey("duration")) {
+ duration = ((Double) result.get("duration")).intValue();
//changeRequested as above
} else {
duration = -1;
changeRequested = false;
}
- if (result.contains("mealAssist")) {
- mealAssist = result.getString("mealAssist");
+ if (result.containsKey("mealAssist")) {
+ mealAssist = result.get("mealAssist").toString();
} else mealAssist = "";
}
- result.release();
}
public DetermineBasalResultMA() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/LoggerCallback.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/LoggerCallback.java
new file mode 100644
index 0000000000..991ec2b25e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/LoggerCallback.java
@@ -0,0 +1,63 @@
+package info.nightscout.androidaps.plugins.OpenAPSMA;
+
+import org.mozilla.javascript.ScriptableObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.utils.ToastUtils;
+
+/**
+ * Created by adrian on 15/10/17.
+ */
+
+
+public class LoggerCallback extends ScriptableObject {
+
+ private static Logger log = LoggerFactory.getLogger(DetermineBasalAdapterMAJS.class);
+
+ static StringBuffer errorBuffer = new StringBuffer();
+ static StringBuffer logBuffer = new StringBuffer();
+
+
+ public LoggerCallback() {
+ //empty constructor needed for Rhino
+ errorBuffer = new StringBuffer();
+ logBuffer = new StringBuffer();
+ }
+
+ @Override
+ public String getClassName() {
+ return "LoggerCallback";
+ }
+
+ public void jsConstructor() {
+ //empty constructor on JS site; could work as setter
+ }
+
+ public void jsFunction_log(Object obj1) {
+ log.debug(obj1.toString());
+ logBuffer.append(obj1.toString());
+ logBuffer.append(' ');
+ }
+
+ public void jsFunction_error(Object obj1) {
+ log.error(obj1.toString());
+ errorBuffer.append(obj1.toString());
+ errorBuffer.append(' ');
+ }
+
+
+
+ public static String getScriptDebug(){
+ String ret = "";
+ if(errorBuffer.length() > 0){
+ ret += "e:\n" + errorBuffer.toString();
+ }
+ if(ret.length() > 0 && logBuffer.length() > 0) ret += '\n';
+ if(logBuffer.length() > 0){
+ ret += "d:\n" + logBuffer.toString();
+ }
+ return ret;
+ }
+}
\ No newline at end of file
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 42741340b5..9b9bdcbbf8 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
@@ -211,12 +211,16 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
start = new Date();
- determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData);
+ try {
+ determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobTotal, glucoseStatus, mealData);
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
Profiler.log(log, "MA calculation", start);
DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke();
- // Fix bug determine basal
+ // Fix bug determinef basal
if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !MainApp.getConfigBuilder().isTempBasalInProgress())
determineBasalResultMA.changeRequested = false;
// limit requests on openloop mode
@@ -229,8 +233,6 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
determineBasalResultMA.iob = iobTotal;
- determineBasalAdapterMAJS.release();
-
try {
determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now));
} catch (JSONException e) {
@@ -241,8 +243,6 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
lastAPSResult = determineBasalResultMA;
lastAPSRun = now;
MainApp.bus().post(new EventOpenAPSUpdateGui());
-
- //deviceStatus.suggested = determineBasalResultMA.json;
}
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 6cc8decfa3..dec763beff 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
@@ -7,7 +7,9 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
+import android.text.Editable;
import android.text.Html;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -36,22 +38,53 @@ import info.nightscout.androidaps.plugins.Overview.Notification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SafeParse;
+import info.nightscout.utils.ToastUtils;
public class NewTreatmentDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewTreatmentDialog.class);
- NumberPicker editCarbs;
- NumberPicker editInsulin;
+ private NumberPicker editCarbs;
+ private NumberPicker editInsulin;
- Handler mHandler;
- public static HandlerThread mHandlerThread;
+ private Integer maxCarbs;
+ private Double maxInsulin;
+
+ private Handler mHandler;
public NewTreatmentDialog() {
- mHandlerThread = new HandlerThread(NewTreatmentDialog.class.getSimpleName());
+ HandlerThread mHandlerThread = new HandlerThread(NewTreatmentDialog.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
}
+ final private TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ validateInputs();
+ }
+ };
+
+ private void validateInputs() {
+ Integer carbs = SafeParse.stringToInt(editCarbs.getText());
+ if (carbs > maxCarbs) {
+ editCarbs.setValue(0d);
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.carbsconstraintapplied));
+ }
+ Double insulin = SafeParse.stringToDouble(editInsulin.getText());
+ if (insulin > maxInsulin) {
+ editInsulin.setValue(0d);
+ ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.bolusconstraintapplied));
+ }
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -63,14 +96,14 @@ public class NewTreatmentDialog extends DialogFragment implements OnClickListene
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
- Integer maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
- Double maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
+ maxCarbs = MainApp.getConfigBuilder().applyCarbsConstraints(Constants.carbsOnlyForCheckLimit);
+ maxInsulin = MainApp.getConfigBuilder().applyBolusConstraints(Constants.bolusOnlyForCheckLimit);
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);
+ editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
+ editInsulin.setParams(0d, 0d, maxInsulin, MainApp.getConfigBuilder().getPumpDescription().bolusStep, new DecimalFormat("0.00"), false, textWatcher);
return view;
}
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 54f526288b..308965a5ea 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
@@ -344,7 +344,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
}
pump.cancelTempBasal(true);
- result = pump.setTempBasalAbsolute(0d, 120);
+ result = pump.setTempBasalAbsolute(0d, 120, true);
if (!result.success) {
OKDialog.show(getActivity(), MainApp.sResources.getString(R.string.tempbasaldeliveryerror), result.comment, null);
}
@@ -420,15 +420,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
BgReading lastBg = DatabaseHelper.actualBg();
if (lastBg != null) {
- editBg.removeTextChangedListener(textWatcher);
- //bgInput.setText(lastBg.valueToUnitsToString(units));
editBg.setValue(lastBg.valueToUnits(units));
- editBg.addTextChangedListener(textWatcher);
} else {
- editBg.removeTextChangedListener(textWatcher);
- //bgInput.setText("");
editBg.setValue(0d);
- editBg.addTextChangedListener(textWatcher);
}
ttCheckbox.setEnabled(MainApp.getConfigBuilder().getTempTargetFromHistory() != null);
@@ -465,19 +459,13 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
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
- 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) {
- editCarbs.removeTextChangedListener(textWatcher);
editCarbs.setValue(0d);
- editCarbs.addTextChangedListener(textWatcher);
- //wizardDialogDeliverButton.setVisibility(Button.GONE);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.carbsconstraintapplied));
return;
}
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 0201d9cabe..a857153c73 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
@@ -49,9 +49,9 @@ public class Notification {
public static final int NSURGENTALARM = 20;
public static final int SHORT_DIA = 21;
public static final int TOAST_ALARM = 22;
+ public static final int WRONGBASALSTEP = 23;
public static final int BOLUS_DELIVERY_ERROR = 24;
-
public int id;
public Date date;
public String text;
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 c331cd0445..67ab9227ed 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
@@ -121,6 +121,7 @@ import info.nightscout.androidaps.plugins.Overview.graphExtensions.FixedLineGrap
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.Treatments.fragments.ProfileViewerDialog;
import info.nightscout.utils.BolusWizard;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
@@ -351,27 +352,33 @@ 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 = ConfigBuilderPlugin.getActiveLoop();
- if (activeloop == null)
- return;
- menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop));
- if (activeloop.isEnabled(PluginBase.LOOP)) {
- menu.add(MainApp.sResources.getString(R.string.disableloop));
- if (!activeloop.isSuspended()) {
- menu.add(MainApp.sResources.getString(R.string.suspendloopfor1h));
- menu.add(MainApp.sResources.getString(R.string.suspendloopfor2h));
- menu.add(MainApp.sResources.getString(R.string.suspendloopfor3h));
- menu.add(MainApp.sResources.getString(R.string.suspendloopfor10h));
- menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor30m));
- menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor1h));
- menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor2h));
- menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor3h));
- } else {
- menu.add(MainApp.sResources.getString(R.string.resume));
+ if (v == apsModeView) {
+ final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
+ if (activeloop == null)
+ return;
+ menu.setHeaderTitle(MainApp.sResources.getString(R.string.loop));
+ if (activeloop.isEnabled(PluginBase.LOOP)) {
+ menu.add(MainApp.sResources.getString(R.string.disableloop));
+ if (!activeloop.isSuspended()) {
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor1h));
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor2h));
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor3h));
+ menu.add(MainApp.sResources.getString(R.string.suspendloopfor10h));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor30m));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor1h));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor2h));
+ menu.add(MainApp.sResources.getString(R.string.disconnectpumpfor3h));
+ } else {
+ menu.add(MainApp.sResources.getString(R.string.resume));
+ }
}
+ if (!activeloop.isEnabled(PluginBase.LOOP))
+ menu.add(MainApp.sResources.getString(R.string.enableloop));
+ } else if (v == activeProfileView) {
+ menu.setHeaderTitle(MainApp.sResources.getString(R.string.profile));
+ menu.add(MainApp.sResources.getString(R.string.danar_viewprofile));
+ menu.add(MainApp.sResources.getString(R.string.careportal_profileswitch));
}
- if (!activeloop.isEnabled(PluginBase.LOOP))
- menu.add(MainApp.sResources.getString(R.string.enableloop));
}
@Override
@@ -555,6 +562,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
});
NSUpload.uploadOpenAPSOffline(180);
return true;
+ } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.careportal_profileswitch))) {
+ NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
+ profileswitch.executeProfileSwitch = true;
+ newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
+ newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
+ } else if (item.getTitle().equals(MainApp.sResources.getString(R.string.danar_viewprofile))) {
+ ProfileViewerDialog pvd = ProfileViewerDialog.newInstance(System.currentTimeMillis());
+ FragmentManager manager = getFragmentManager();
+ pvd.show(manager, "ProfileViewDialog");
}
return super.onContextItemSelected(item);
@@ -739,6 +756,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
MainApp.bus().unregister(this);
sLoopHandler.removeCallbacksAndMessages(null);
unregisterForContextMenu(apsModeView);
+ unregisterForContextMenu(activeProfileView);
}
@Override
@@ -754,6 +772,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
};
sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
registerForContextMenu(apsModeView);
+ registerForContextMenu(activeProfileView);
updateGUI("onResume");
}
@@ -1089,27 +1108,12 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
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 = CareportalFragment.profileswitch;
- profileswitch.executeProfileSwitch = true;
- newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
- newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
- return true;
- }
- });
- activeProfileView.setLongClickable(true);
-
-
tempTargetView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
- final OptionsToShow temptarget = CareportalFragment.temptarget;
+ final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
temptarget.executeTempTarget = true;
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
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 c7d7333aba..53ceed17a8 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
@@ -2,11 +2,12 @@ package info.nightscout.androidaps.plugins.ProfileCircadianPercentage;
import android.app.Activity;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
-import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.text.Editable;
import android.text.Html;
@@ -33,7 +34,6 @@ 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;
@@ -125,6 +125,9 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
+
+ showDeprecatedDialog();
+
View layout = inflater.inflate(R.layout.circadianpercentageprofile_fragment, container, false);
fl = (FrameLayout) layout.findViewById(R.id.circadianpercentageprofile_framelayout);
fl.requestFocusFromTouch();
@@ -178,7 +181,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
@Override
public void onClick(View view) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.profileswitch;
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
@@ -232,7 +235,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
}
});
- timeshiftView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ /*timeshiftView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
@@ -268,7 +271,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
}
}
}
- });
+ });*/
diaView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@@ -317,6 +320,25 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
return layout;
}
+ private void showDeprecatedDialog() {
+ AlertDialog.Builder adb = new AlertDialog.Builder(getContext());
+ adb.setTitle("DEPRECATED! Please migrate!");
+ adb.setMessage("CircadianPercentageProfile has been deprecated. " +
+ "It is recommended to migrate to LocalProfile.\n\n" +
+ "Good news: You won't lose any functionality! Percentage and Timeshift have been ported to the ProfileSwitch :) \n\n " +
+ "How to migrate:\n" +
+ "1) Press MIGRATE, the system will automatically fill the LocalProfile for you.\n" +
+ "2) Switch to LocalProfile in the ConfigBuilder\n" +
+ "3) CHECK that all settings are correct in the LocalProfile!!!");
+ adb.setIcon(android.R.drawable.ic_dialog_alert);
+ adb.setPositiveButton("MIGRATE", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ CircadianPercentageProfilePlugin.migrateToLP();
+ } });
+ adb.setNegativeButton("Cancel", null);
+ adb.show();
+ }
+
public void updateGUI() {
updateProfileInfo();
@@ -502,11 +524,7 @@ public class CircadianPercentageProfileFragment extends SubscriberFragment {
public void run() {
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/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileCircadianPercentage/CircadianPercentageProfilePlugin.java
index e88089fdb7..62b0326eae 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
@@ -21,6 +21,8 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
+import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
@@ -199,7 +201,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
//send profile to pumpe
new NewNSTreatmentDialog(); //init
- NewNSTreatmentDialog.doProfileSwitch(this.getProfile(), this.getProfileName(), 0);
+ NewNSTreatmentDialog.doProfileSwitch(this.getProfile(), this.getProfileName(), 0, percentage, timeshift);
//return formatted string
/*msg += "%: " + this.percentage + " h: +" + this.timeshift;
@@ -211,6 +213,91 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
return msg;
}
+ public static void migrateToLP(){
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putBoolean("LocalProfile" + "mmol", SP.getBoolean(SETTINGS_PREFIX + "mmol", false));
+ editor.putBoolean("LocalProfile" + "mgdl", SP.getBoolean(SETTINGS_PREFIX + "mgdl", true));
+ editor.putString("LocalProfile" + "dia", "" + SP.getDouble(SETTINGS_PREFIX + "dia", Constants.defaultDIA));
+ editor.putString("LocalProfile" + "ic", getLPic());
+ editor.putString("LocalProfile" + "isf", getLPisf());
+ editor.putString("LocalProfile" + "basal", getLPbasal());
+ try {
+ JSONArray targetLow = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targetlow", 120d)));
+ JSONArray targetHigh = new JSONArray().put(new JSONObject().put("time", "00:00").put("timeAsSeconds", 0).put("value", SP.getDouble(SETTINGS_PREFIX + "targethigh", 120d)));
+ editor.putString("LocalProfile" + "targetlow", targetLow.toString());
+ editor.putString("LocalProfile" + "targethigh", targetHigh.toString());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ editor.commit();
+ LocalProfilePlugin lp = MainApp.getSpecificPlugin(LocalProfilePlugin.class);
+ lp.loadSettings();
+
+ /* TODO: remove Settings and switch to LP later on
+ * For now only nag the user every time (s)he opens the CPP fragment and offer to migrate.
+ * Keep settings for now in order to allow the user to check that the migration went well.
+ */
+ //removeSettings();
+
+ }
+
+ public static String getLPisf(){
+ return getLPConversion("baseisf", 35d);
+ }
+
+ public static String getLPic(){
+ return getLPConversion("baseic", 4);
+ }
+
+ public static String getLPbasal(){
+ return getLPConversion("basebasal", 1);
+ }
+
+ public static String getLPConversion(String type, double defaultValue){
+ try {
+ JSONArray jsonArray = new JSONArray();
+ double last = -1d;
+
+ for (int i = 0; i < 24; i++) {
+ double value = SP.getDouble(SETTINGS_PREFIX + type + i, defaultValue);
+ String time;
+ DecimalFormat df = new DecimalFormat("00");
+ time = df.format(i) + ":00";
+ if(last != value) {
+ jsonArray.put(new JSONObject().put("time", time).put("timeAsSeconds", i * 60 * 60).put("value", value));
+ }
+ last = value;
+ }
+ return jsonArray.toString();
+ } catch (JSONException e) {
+ log.error("Unhandled exception", e);
+ }
+ return LocalProfilePlugin.DEFAULTARRAY;
+ }
+
+ static void removeSettings() {
+ if (Config.logPrefsChange)
+ log.debug("Removing settings");
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
+ SharedPreferences.Editor editor = settings.edit();
+ editor.remove(SETTINGS_PREFIX + "mmol");
+ editor.remove(SETTINGS_PREFIX + "mgdl");
+ editor.remove(SETTINGS_PREFIX + "dia");
+ editor.remove(SETTINGS_PREFIX + "targetlow");
+ editor.remove(SETTINGS_PREFIX + "targethigh");
+ editor.remove(SETTINGS_PREFIX + "timeshift");
+ editor.remove(SETTINGS_PREFIX + "percentage");
+
+
+ for (int i = 0; i < 24; i++) {
+ editor.remove(SETTINGS_PREFIX + "basebasal");
+ editor.remove(SETTINGS_PREFIX + "baseisf" + i);
+ editor.remove(SETTINGS_PREFIX + "baseic" + i);
+ }
+ editor.commit();
+ }
+
private void createConvertedProfile() {
JSONObject json = new JSONObject();
JSONObject store = new JSONObject();
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 e491a41b1b..24965861df 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
@@ -3,16 +3,16 @@ package info.nightscout.androidaps.plugins.ProfileLocal;
import android.app.Activity;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
+import android.support.annotation.NonNull;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.EditText;
import android.widget.RadioButton;
+import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@@ -28,6 +28,8 @@ 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.NumberPicker;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.TimeListEdit;
@@ -40,7 +42,7 @@ public class LocalProfileFragment extends SubscriberFragment {
return localProfilePlugin;
}
- EditText diaView;
+ NumberPicker diaView;
RadioButton mgdlView;
RadioButton mmolView;
TimeListEdit icView;
@@ -52,88 +54,101 @@ public class LocalProfileFragment extends SubscriberFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- Runnable save = new Runnable() {
- @Override
- public void run() {
- localProfilePlugin.storeSettings();
+ try {
+ Runnable save = new Runnable() {
+ @Override
+ public void run() {
+ localProfilePlugin.storeSettings();
+ if(basalView!=null){
+ basalView.updateLabel(MainApp.sResources.getString(R.string.nsprofileview_basal_label)+ ": "+ getSumLabel());
+ }
+ }
+ };
+
+ 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) {
+ localProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
+ localProfilePlugin.storeSettings();
+ }
+ };
+
+ View layout = inflater.inflate(R.layout.localprofile_fragment, container, false);
+ diaView = (NumberPicker) layout.findViewById(R.id.localprofile_dia);
+ diaView.setParams(localProfilePlugin.dia, 2d, 48d, 0.1d, new DecimalFormat("0.0"), false, textWatch);
+ mgdlView = (RadioButton) layout.findViewById(R.id.localprofile_mgdl);
+ mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol);
+ icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label) + ":", getPlugin().ic, null, 0.1d, new DecimalFormat("0.0"), save);
+ isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label) + ":", getPlugin().isf, null, 0.1d, new DecimalFormat("0.0"), save);
+ basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label)+ ": " + getSumLabel(), getPlugin().basal, null, 0.01d, new DecimalFormat("0.00"), save);
+ targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label)+ ":", getPlugin().targetLow, getPlugin().targetHigh, 0.1d, new DecimalFormat("0.0"), save);
+ profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch);
+
+ PumpInterface pump = MainApp.getConfigBuilder();
+ if (!pump.getPumpDescription().isTempBasalCapable) {
+ layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE);
}
- };
- View layout = inflater.inflate(R.layout.localprofile_fragment, container, false);
- diaView = (EditText) layout.findViewById(R.id.localprofile_dia);
- mgdlView = (RadioButton) layout.findViewById(R.id.localprofile_mgdl);
- mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol);
- icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label), getPlugin().ic, null, new DecimalFormat("0.0"), save);
- isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label), getPlugin().isf, null, new DecimalFormat("0.0"), save);
- basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label), getPlugin().basal, null, new DecimalFormat("0.00"), save);
- targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label), getPlugin().targetLow, getPlugin().targetHigh, new DecimalFormat("0.0"), save);
- profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch);
+ updateGUI();
- PumpInterface pump = MainApp.getConfigBuilder();
- if (!pump.getPumpDescription().isTempBasalCapable) {
- layout.findViewById(R.id.localprofile_basal).setVisibility(View.GONE);
+ mgdlView.setChecked(localProfilePlugin.mgdl);
+ mmolView.setChecked(localProfilePlugin.mmol);
+
+ mgdlView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ localProfilePlugin.mgdl = mgdlView.isChecked();
+ localProfilePlugin.mmol = !localProfilePlugin.mgdl;
+ mmolView.setChecked(localProfilePlugin.mmol);
+ localProfilePlugin.storeSettings();
+ }
+ });
+ mmolView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ localProfilePlugin.mmol = mmolView.isChecked();
+ localProfilePlugin.mgdl = !localProfilePlugin.mmol;
+ mgdlView.setChecked(localProfilePlugin.mgdl);
+ localProfilePlugin.storeSettings();
+ }
+ });
+
+ profileswitchButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
+ profileswitch.executeProfileSwitch = true;
+ newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
+ newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
+ }
+ });
+
+
+ updateGUI();
+ return layout;
+ } catch (Exception e) {
+ log.error("Unhandled exception: ", e);
+ Crashlytics.logException(e);
}
- updateGUI();
+ return null;
+ }
- mgdlView.setChecked(localProfilePlugin.mgdl);
- mmolView.setChecked(localProfilePlugin.mmol);
- diaView.setText(localProfilePlugin.dia.toString());
-
- mgdlView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- localProfilePlugin.mgdl = mgdlView.isChecked();
- localProfilePlugin.mmol = !localProfilePlugin.mgdl;
- mmolView.setChecked(localProfilePlugin.mmol);
- localProfilePlugin.storeSettings();
- }
- });
- mmolView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- localProfilePlugin.mmol = mmolView.isChecked();
- localProfilePlugin.mgdl = !localProfilePlugin.mmol;
- mgdlView.setChecked(localProfilePlugin.mgdl);
- localProfilePlugin.storeSettings();
- }
- });
-
- profileswitchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.profileswitch;
- profileswitch.executeProfileSwitch = true;
- newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
- newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
- }
- });
-
- 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) {
- localProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
- localProfilePlugin.storeSettings();
- }
- };
-
- diaView.addTextChangedListener(textWatch);
-
- updateGUI();
-
- return layout;
+ @NonNull
+ public String getSumLabel() {
+ return " ∑" + DecimalFormatter.to2Decimal(localProfilePlugin.getProfile().getDefaultProfile().baseBasalSum()) +"U";
}
@Subscribe
@@ -150,11 +165,7 @@ public class LocalProfileFragment extends SubscriberFragment {
public void run() {
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 5b7cdcac5d..db22677a82 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
@@ -16,21 +16,23 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SP;
/**
* Created by mike on 05.08.2016.
*/
public class LocalProfilePlugin implements PluginBase, ProfileInterface {
+ public static final String LOCAL_PROFILE = "LocalProfile";
private static Logger log = LoggerFactory.getLogger(LocalProfilePlugin.class);
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
- private static ProfileStore convertedProfile = null;
- private static String convertedProfileName = null;
+ private ProfileStore convertedProfile = null;
+ private String convertedProfileName = null;
- final private String DEFAULTARRAY = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]";
+ public static final String DEFAULTARRAY = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]";
boolean mgdl;
boolean mmol;
@@ -107,68 +109,68 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
}
public void storeSettings() {
- if (Config.logPrefsChange)
- log.debug("Storing settings");
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
SharedPreferences.Editor editor = settings.edit();
- editor.putBoolean("LocalProfile" + "mmol", mmol);
- editor.putBoolean("LocalProfile" + "mgdl", mgdl);
- editor.putString("LocalProfile" + "dia", dia.toString());
- editor.putString("LocalProfile" + "ic", ic.toString());
- editor.putString("LocalProfile" + "isf", isf.toString());
- editor.putString("LocalProfile" + "basal", basal.toString());
- editor.putString("LocalProfile" + "targetlow", targetLow.toString());
- editor.putString("LocalProfile" + "targethigh", targetHigh.toString());
+ editor.putBoolean(LOCAL_PROFILE + "mmol", mmol);
+ editor.putBoolean(LOCAL_PROFILE + "mgdl", mgdl);
+ editor.putString(LOCAL_PROFILE + "dia", dia.toString());
+ editor.putString(LOCAL_PROFILE + "ic", ic.toString());
+ editor.putString(LOCAL_PROFILE + "isf", isf.toString());
+ editor.putString(LOCAL_PROFILE + "basal", basal.toString());
+ editor.putString(LOCAL_PROFILE + "targetlow", targetLow.toString());
+ editor.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString());
- editor.commit();
+ editor.apply();
createConvertedProfile();
+ if (Config.logPrefsChange)
+ log.debug("Storing settings: " + getProfile().getData().toString());
}
- private void loadSettings() {
+ public void loadSettings() {
if (Config.logPrefsChange)
log.debug("Loading stored settings");
- mgdl = SP.getBoolean("LocalProfile" + "mgdl", false);
- mmol = SP.getBoolean("LocalProfile" + "mmol", true);
- dia = SP.getDouble("LocalProfile" + "dia", Constants.defaultDIA);
+ mgdl = SP.getBoolean(LOCAL_PROFILE + "mgdl", false);
+ mmol = SP.getBoolean(LOCAL_PROFILE + "mmol", true);
+ dia = SP.getDouble(LOCAL_PROFILE + "dia", Constants.defaultDIA);
try {
- ic = new JSONArray(SP.getString("LocalProfile" + "ic", DEFAULTARRAY));
+ ic = new JSONArray(SP.getString(LOCAL_PROFILE + "ic", DEFAULTARRAY));
} catch (JSONException e1) {
try {
ic = new JSONArray(DEFAULTARRAY);
- } catch (JSONException e2) {
+ } catch (JSONException ignored) {
}
}
try {
- isf = new JSONArray(SP.getString("LocalProfile" + "isf", DEFAULTARRAY));
+ isf = new JSONArray(SP.getString(LOCAL_PROFILE + "isf", DEFAULTARRAY));
} catch (JSONException e1) {
try {
isf = new JSONArray(DEFAULTARRAY);
- } catch (JSONException e2) {
+ } catch (JSONException ignored) {
}
}
try {
- basal = new JSONArray(SP.getString("LocalProfile" + "basal", DEFAULTARRAY));
+ basal = new JSONArray(SP.getString(LOCAL_PROFILE + "basal", DEFAULTARRAY));
} catch (JSONException e1) {
try {
basal = new JSONArray(DEFAULTARRAY);
- } catch (JSONException e2) {
+ } catch (JSONException ignored) {
}
}
try {
- targetLow = new JSONArray(SP.getString("LocalProfile" + "targetlow", DEFAULTARRAY));
+ targetLow = new JSONArray(SP.getString(LOCAL_PROFILE + "targetlow", DEFAULTARRAY));
} catch (JSONException e1) {
try {
targetLow = new JSONArray(DEFAULTARRAY);
- } catch (JSONException e2) {
+ } catch (JSONException ignored) {
}
}
try {
- targetHigh = new JSONArray(SP.getString("LocalProfile" + "targethigh", DEFAULTARRAY));
+ targetHigh = new JSONArray(SP.getString(LOCAL_PROFILE + "targethigh", DEFAULTARRAY));
} catch (JSONException e1) {
try {
targetHigh = new JSONArray(DEFAULTARRAY);
- } catch (JSONException e2) {
+ } catch (JSONException ignored) {
}
}
createConvertedProfile();
@@ -212,13 +214,13 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
"created_at": "2016-06-16T08:34:41.256Z"
}
*/
- void createConvertedProfile() {
+ private void createConvertedProfile() {
JSONObject json = new JSONObject();
JSONObject store = new JSONObject();
JSONObject profile = new JSONObject();
try {
- json.put("defaultProfile", "LocalProfile");
+ json.put("defaultProfile", LOCAL_PROFILE);
json.put("store", store);
profile.put("dia", dia);
profile.put("carbratio", ic);
@@ -227,12 +229,12 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
profile.put("target_low", targetLow);
profile.put("target_high", targetHigh);
profile.put("units", mgdl ? Constants.MGDL : Constants.MMOL);
- store.put("LocalProfile", profile);
+ store.put(LOCAL_PROFILE, profile);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
convertedProfile = new ProfileStore(json);
- convertedProfileName = "LocalProfile";
+ convertedProfileName = LOCAL_PROFILE;
}
@Override
@@ -247,7 +249,7 @@ public class LocalProfilePlugin implements PluginBase, ProfileInterface {
@Override
public String getProfileName() {
- return convertedProfileName;
+ return DecimalFormatter.to2Decimal(convertedProfile.getDefaultProfile().percentageBasalSum()) + "U ";
}
}
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 4c4fea419c..546a232ca4 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
@@ -5,19 +5,27 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.squareup.otto.Subscribe;
+import java.util.ArrayList;
+
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ProfileNS.events.EventNSProfileUpdateGUI;
import info.nightscout.utils.DecimalFormatter;
-public class NSProfileFragment extends SubscriberFragment {
+
+public class NSProfileFragment extends SubscriberFragment implements AdapterView.OnItemSelectedListener {
+ private Spinner profileSpinner;
private TextView noProfile;
private TextView units;
private TextView dia;
@@ -31,8 +39,9 @@ public class NSProfileFragment extends SubscriberFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
try {
- View layout = inflater.inflate(R.layout.nsprofileviewer_fragment, container, false);
+ View layout = inflater.inflate(R.layout.nsprofile_fragment, container, false);
+ profileSpinner = (Spinner) layout.findViewById(R.id.nsprofile_spinner);
noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile);
units = (TextView) layout.findViewById(R.id.profileview_units);
dia = (TextView) layout.findViewById(R.id.profileview_dia);
@@ -42,6 +51,8 @@ public class NSProfileFragment extends SubscriberFragment {
basal = (TextView) layout.findViewById(R.id.profileview_basal);
target = (TextView) layout.findViewById(R.id.profileview_target);
+ profileSpinner.setOnItemSelectedListener(this);
+
updateGUI();
return layout;
} catch (Exception e) {
@@ -72,14 +83,42 @@ public class NSProfileFragment extends SubscriberFragment {
noProfile.setVisibility(View.GONE);
}
- Profile profile = MainApp.getConfigBuilder().getProfile();
+ ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile();
+ ArrayList 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);
+ }
+
+ }
+
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ String name = parent.getItemAtPosition(position).toString();
+
+ Profile profile = NSProfilePlugin.getPlugin().getProfile().getSpecificProfile(name);
units.setText(profile.getUnits());
dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h");
- activeProfile.setText(MainApp.getConfigBuilder().getProfileName());
+ activeProfile.setText(name);
ic.setText(profile.getIcList());
isf.setText(profile.getIsfList());
basal.setText(profile.getBasalList());
target.setText(profile.getTargetList());
}
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ noProfile.setVisibility(View.VISIBLE);
+ units.setText("");
+ dia.setText("");
+ activeProfile.setText("");
+ ic.setText("");
+ isf.setText("");
+ basal.setText("");
+ target.setText("");
+ }
}
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 b6d24741a0..88057a68c1 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
@@ -96,7 +96,7 @@ public class SimpleProfileFragment extends SubscriberFragment {
@Override
public void onClick(View view) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
- final OptionsToShow profileswitch = CareportalFragment.profileswitch;
+ final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCH;
profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
@@ -158,11 +158,7 @@ public class SimpleProfileFragment extends SubscriberFragment {
public void run() {
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/PumpDanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRFragment.java
index c5c87f194e..d48013b0e6 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
@@ -12,6 +12,7 @@ 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.Crashlytics;
@@ -56,10 +57,21 @@ public class DanaRFragment extends SubscriberFragment {
TextView firmwareView;
TextView basalStepView;
TextView bolusStepView;
+ TextView serialNumberView;
Button viewProfileButton;
Button historyButton;
Button statsButton;
+ LinearLayout pumpStatusLayout;
+ TextView pumpStatusView;
+
+ static Runnable connectRunnable = new Runnable() {
+ @Override
+ public void run() {
+ MainApp.getConfigBuilder().refreshDataFromPump("Connect request from GUI");
+ }
+ };
+
public DanaRFragment() {
if (sHandlerThread == null) {
@@ -105,7 +117,11 @@ public class DanaRFragment extends SubscriberFragment {
statsButton = (Button) view.findViewById(R.id.danar_stats);
basalStepView = (TextView) view.findViewById(R.id.danar_basalstep);
bolusStepView = (TextView) view.findViewById(R.id.danar_bolusstep);
+ serialNumberView = (TextView) view.findViewById(R.id.danar_serialnumber);
+ pumpStatusView = (TextView) view.findViewById(R.id.overview_pumpstatus);
+ pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
+ pumpStatusLayout = (LinearLayout) view.findViewById(R.id.overview_pumpstatuslayout);
viewProfileButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -133,13 +149,8 @@ public class DanaRFragment extends SubscriberFragment {
btConnectionView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- sHandler.post(new Runnable() {
- @Override
- public void run() {
- MainApp.getConfigBuilder().refreshDataFromPump("Connect request from GUI");
- }
- }
- );
+ log.debug("Clicked connect to pump");
+ sHandler.post(connectRunnable);
}
});
@@ -155,6 +166,7 @@ public class DanaRFragment extends SubscriberFragment {
@Subscribe
public void onStatusEvent(final EventPumpStatusChanged c) {
Activity activity = getActivity();
+ final String status = c.textStatus();
if (activity != null) {
activity.runOnUiThread(
new Runnable() {
@@ -166,6 +178,13 @@ public class DanaRFragment extends SubscriberFragment {
btConnectionView.setText("{fa-bluetooth}");
else if (c.sStatus == EventPumpStatusChanged.DISCONNECTED)
btConnectionView.setText("{fa-bluetooth-b}");
+
+ if (!status.equals("")) {
+ pumpStatusView.setText(status);
+ pumpStatusLayout.setVisibility(View.VISIBLE);
+ } else {
+ pumpStatusLayout.setVisibility(View.GONE);
+ }
}
}
);
@@ -246,6 +265,7 @@ public class DanaRFragment extends SubscriberFragment {
}
basalStepView.setText("" + pump.basalStep);
bolusStepView.setText("" + pump.bolusStep);
+ serialNumberView.setText("" + pump.serialNumber);
}
});
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 7ea3308469..65dd5192e4 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
@@ -342,7 +342,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
// This is called from APS
@Override
- public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
// Recheck pump status if older than 30 min
if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
doConnect("setTempBasalAbsolute old data");
@@ -408,7 +408,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
if (Config.logPumpActions)
log.debug("setTempBasalAbsolute: currently running: " + running.toString());
if (running.percentRate == percentRate) {
- if (force) {
+ if (enforceNew) {
cancelTempBasal(true);
} else {
result.success = true;
@@ -649,7 +649,11 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C
}
public static void doConnect(String from) {
- if (sExecutionService != null) sExecutionService.connect(from);
+ if (sExecutionService != null) {
+ sExecutionService.connect(from);
+ pumpDescription.basalStep = pump.basalStep;
+ pumpDescription.bolusStep = pump.bolusStep;
+ }
}
public static boolean isConnected() {
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 7948d00d96..9f88011c96 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,8 +9,10 @@ import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.Date;
+import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.utils.SP;
@@ -52,6 +54,7 @@ public class DanaRPump {
public static final int PRIME = 12;
public static final int PROFILECHANGE = 13;
public static final int CARBS = 14;
+ public static final int PRIMECANNULA = 15;
public Date lastConnection = new Date(0);
public Date lastSettingsRead = new Date(0);
@@ -78,10 +81,12 @@ public class DanaRPump {
public boolean pumpSuspended;
public boolean calculatorEnabled;
public double dailyTotalUnits;
+ public double dailyTotalBolusUnits = 0; // RS only
+ public double dailyTotalBasalUnits = 0; // RS only
public int maxDailyTotalUnits;
- public double bolusStep;
- public double basalStep;
+ public double bolusStep = 0.1;
+ public double basalStep = 0.1;
public double iob;
@@ -108,6 +113,7 @@ public class DanaRPump {
public int extendedBolusSoFarInMinutes;
public Date extendedBolusStart;
public int extendedBolusRemainingMinutes;
+ public double extendedBolusDeliveredSoFar; //RS only
// Profile
public int units;
@@ -136,6 +142,27 @@ public class DanaRPump {
public double maxBolus;
public double maxBasal;
+ // DanaRS specific
+
+ public String rs_password = "";
+
+ // User settings
+ public int timeDisplayType;
+ public int buttonScrollOnOff;
+ public int beepAndAlarm;
+ public int lcdOnTimeSec;
+ public int backlightOnTimeSec;
+ public int selectedLanguage;
+ public int shutdownHour;
+ public int lowReservoirRate;
+ public int cannulaVolume;
+ public int refillAmount;
+
+ public double initialBolusAmount;
+ // Bolus settings
+ public int bolusCalculationOption;
+ public int missedBolusConfig;
+
public String getUnits() {
return units == UNITS_MGDL ? Constants.MGDL : Constants.MMOL;
}
@@ -205,4 +232,17 @@ public class DanaRPump {
return PROFILE_PREFIX + (activeProfile + 1);
}
+ public static 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((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;
+ }
+
}
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 a20934fdb7..fc7a9a2411 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
@@ -57,7 +57,7 @@ public class ProfileViewDialog extends DialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- View layout = inflater.inflate(R.layout.nsprofileviewer_fragment, container, false);
+ View layout = inflater.inflate(R.layout.profileviewer_fragment, container, false);
noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile);
units = (TextView) layout.findViewById(R.id.profileview_units);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java
index 5fc022bcc6..0612b9e1c3 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRHistoryActivity.java
@@ -42,6 +42,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionServi
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.ToastUtils;
@@ -122,6 +123,7 @@ public class DanaRHistoryActivity extends Activity {
statusView.setVisibility(View.GONE);
boolean isKorean = MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP);
+ boolean isRS = MainApp.getSpecificPlugin(DanaRSPlugin.class).isEnabled(PluginBase.PUMP);
// Types
@@ -132,8 +134,12 @@ 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) {
+ if (!isKorean && !isRS) {
typeList.add(new TypeList(RecordTypes.RECORD_TYPE_ERROR, getString(R.string.danar_history_errors)));
+ }
+ if (isRS)
+ typeList.add(new TypeList(RecordTypes.RECORD_TYPE_PRIME, getString(R.string.danar_history_prime)));
+ if (!isKorean) {
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)));
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java
index fbe828a25f..5240005dc0 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/activities/DanaRStatsActivity.java
@@ -1,16 +1,11 @@
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.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.IBinder;
import android.support.v7.widget.LinearLayoutManager;
import android.text.TextUtils;
import android.view.KeyEvent;
@@ -42,16 +37,14 @@ 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.DanaRHistoryRecord;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.DanaRInterface;
-import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
-import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus;
-import info.nightscout.androidaps.plugins.PumpDanaR.services.DanaRExecutionService;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
@@ -134,15 +127,14 @@ public class DanaRStatsActivity extends Activity {
llm = new LinearLayoutManager(this);
TBB = SP.getString("TBB", "10.00");
- totalBaseBasal.setText(TBB);
- ProfileInterface pi = ConfigBuilderPlugin.getActiveProfileInterface();
- if (pi != null && pi instanceof CircadianPercentageProfilePlugin) {
- double cppTBB = ((CircadianPercentageProfilePlugin) pi).baseBasalSum();
- totalBaseBasal.setText(decimalFormat.format(cppTBB));
- SP.putString("TBB", totalBaseBasal.getText().toString());
- TBB = SP.getString("TBB", "");
+ Profile profile = MainApp.getConfigBuilder().getProfile();
+ if (profile != null) {
+ double cppTBB = profile.baseBasalSum();
+ TBB = decimalFormat.format(cppTBB);
+ SP.putString("TBB", TBB);
}
+ totalBaseBasal.setText(TBB);
// stats table
tl = (TableLayout) findViewById(R.id.main_table);
@@ -241,7 +233,7 @@ public class DanaRStatsActivity extends Activity {
reloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- final PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
+ final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (pump.isBusy()) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), getString(R.string.pumpbusy));
return;
@@ -258,7 +250,7 @@ public class DanaRStatsActivity extends Activity {
statsMessage.setText(getString(R.string.danar_stats_warning_Message));
}
});
- ((DanaRInterface)pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY);
+ ((DanaRInterface) pump).loadHistory(RecordTypes.RECORD_TYPE_DAILY);
loadDataFromDB(RecordTypes.RECORD_TYPE_DAILY);
runOnUiThread(new Runnable() {
@Override
@@ -311,15 +303,15 @@ public class DanaRStatsActivity extends Activity {
//fill single gaps
dummies = new LinkedList();
DateFormat df = new SimpleDateFormat("dd.MM.");
- for(int i = 0; i < historyList.size()-1; i++){
+ for (int i = 0; i < historyList.size() - 1; i++) {
DanaRHistoryRecord elem1 = historyList.get(i);
- DanaRHistoryRecord elem2 = historyList.get(i+1);
+ DanaRHistoryRecord elem2 = historyList.get(i + 1);
- if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25*60*60*1000)))){
+ if (!df.format(new Date(elem1.recordDate)).equals(df.format(new Date(elem2.recordDate + 25 * 60 * 60 * 1000)))) {
DanaRHistoryRecord dummy = new DanaRHistoryRecord();
- dummy.recordDate = elem1.recordDate - 24*60*60*1000;
- dummy.recordDailyBasal = elem1.recordDailyBasal/2;
- dummy.recordDailyBolus = elem1.recordDailyBolus/2;
+ dummy.recordDate = elem1.recordDate - 24 * 60 * 60 * 1000;
+ dummy.recordDailyBasal = elem1.recordDailyBasal / 2;
+ dummy.recordDailyBolus = elem1.recordDailyBolus / 2;
dummies.add(dummy);
elem1.recordDailyBasal /= 2;
elem1.recordDailyBolus /= 2;
@@ -329,7 +321,7 @@ public class DanaRStatsActivity extends Activity {
Collections.sort(historyList, new Comparator() {
@Override
public int compare(DanaRHistoryRecord lhs, DanaRHistoryRecord rhs) {
- return (int) (rhs.recordDate-lhs.recordDate);
+ return (int) (rhs.recordDate - lhs.recordDate);
}
});
@@ -363,7 +355,7 @@ public class DanaRStatsActivity extends Activity {
// Create the table row
TableRow tr = new TableRow(DanaRStatsActivity.this);
if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY);
- if(dummies.contains(record)){
+ if (dummies.contains(record)) {
tr.setBackgroundColor(Color.argb(125, 255, 0, 0));
}
tr.setId(100 + i);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java
index debdd8a35f..10d2c0b091 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MessageHashTable.java
@@ -18,6 +18,7 @@ public class MessageHashTable {
messages = new HashMap();
put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP
put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA
+ put(new MsgBolusStartWithSpeed()); // 0x0104 CMD_MEALINS_START_DATA_SPEED
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
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java
new file mode 100644
index 0000000000..b04d501ef0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgBolusStartWithSpeed.java
@@ -0,0 +1,43 @@
+package info.nightscout.androidaps.plugins.PumpDanaR.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.utils.HardLimits;
+
+public class MsgBolusStartWithSpeed extends MessageBase {
+ private static Logger log = LoggerFactory.getLogger(MsgBolusStartWithSpeed.class);
+
+ public MsgBolusStartWithSpeed() {
+ SetCommand(0x0104);
+ }
+
+ public MsgBolusStartWithSpeed(double amount, int speed) {
+ this();
+
+ // HARDCODED LIMIT
+ amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
+ if (amount < 0) amount = 0d;
+ if (amount > HardLimits.maxBolus()) amount = HardLimits.maxBolus();
+
+ AddParamInt((int) (amount * 100));
+ AddParamByte((byte) speed);
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Bolus start : " + amount + " speed: " + speed);
+ }
+
+ @Override
+ public void handleMessage(byte[] bytes) {
+ int result = intFromBuff(bytes, 0, 1);
+ if (result != 2) {
+ failed = true;
+ log.debug("Messsage response: " + result + " FAILED!!");
+ } else {
+ if (Config.logDanaMessageDetail)
+ log.debug("Messsage response: " + result);
+ }
+ }
+}
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 4ed5de2920..727b6cd7fb 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
@@ -40,6 +40,13 @@ public class MsgSettingMeal extends MessageBase {
log.debug("Is Config U/d: " + pump.isConfigUD);
}
+ if (pump.basalStep != 0.01d) {
+ Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.sResources.getString(R.string.danar_setbasalstep001), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(notification));
+ } else {
+ MainApp.bus().post(new EventDismissNotification(Notification.WRONGBASALSTEP));
+ }
+
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));
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 ba8374f383..2aba028250 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
@@ -24,9 +24,10 @@ public class MsgStatusBasic extends MessageBase {
pump.reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750d;
pump.bolusBlocked = intFromBuff(bytes, 10, 1) == 1;
pump.currentBasal = intFromBuff(bytes, 11, 2) / 100d;
- pump.tempBasalPercent = intFromBuff(bytes, 13, 1);
- pump.isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1;
- pump.isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1;
+ // removed. info taken from tempstatus message
+ //pump.tempBasalPercent = intFromBuff(bytes, 13, 1);
+ //pump.isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1;
+ //pump.isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1;
pump.batteryRemaining = intFromBuff(bytes, 20, 1);
if (Config.logDanaMessageDetail) {
@@ -37,9 +38,9 @@ public class MsgStatusBasic extends MessageBase {
log.debug("Reservoir remaining units: " + pump.reservoirRemainingUnits);
log.debug("Bolus blocked: " + pump.bolusBlocked);
log.debug("Current basal: " + pump.currentBasal);
- log.debug("Current temp basal percent: " + pump.tempBasalPercent);
- log.debug("Is extended bolus running: " + pump.isExtendedInProgress);
- log.debug("Is temp basal running: " + pump.isTempBasalInProgress);
+ //log.debug("Current temp basal percent: " + pump.tempBasalPercent);
+ //log.debug("Is extended bolus running: " + pump.isExtendedInProgress);
+ //log.debug("Is temp basal running: " + pump.isTempBasalInProgress);
}
}
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java
index 419d5feb2c..9d94634094 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/services/DanaRExecutionService.java
@@ -40,6 +40,7 @@ import info.nightscout.androidaps.plugins.PumpDanaR.SerialIOThread;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MessageBase;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusProgress;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStart;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStartWithSpeed;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgBolusStop;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgCheckValue;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.MsgHistoryAlarm;
@@ -109,7 +110,7 @@ public class DanaRExecutionService extends Service {
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
+ log.debug("Device was disconnected " + device.getName());//Device was disconnected
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
if (mSerialIOThread != null) {
mSerialIOThread.disconnect("BT disconnection broadcast");
@@ -290,10 +291,13 @@ public class DanaRExecutionService extends Service {
}
}
- mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
- mSerialIOThread.sendMessage(exStatusMsg);
mSerialIOThread.sendMessage(statusMsg);
mSerialIOThread.sendMessage(statusBasicMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus)));
+ mSerialIOThread.sendMessage(tempStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus)));
+ mSerialIOThread.sendMessage(exStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
if (!statusMsg.received) {
mSerialIOThread.sendMessage(statusMsg);
@@ -319,6 +323,7 @@ public class DanaRExecutionService extends Service {
Date now = new Date();
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRPlugin.class).isInitialized()) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
mSerialIOThread.sendMessage(new MsgSettingMeal());
@@ -329,6 +334,7 @@ public class DanaRExecutionService extends Service {
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
log.debug("Pump time difference: " + timeDiff + " seconds");
@@ -404,7 +410,12 @@ public class DanaRExecutionService extends Service {
public boolean bolus(double amount, int carbs, Treatment t) {
bolusingTreatment = t;
- MsgBolusStart start = new MsgBolusStart(amount);
+ int speed = SP.getInt(R.string.key_danars_bolusspeed, 0);
+ MessageBase start;
+ if (speed == 0)
+ start = new MsgBolusStart(amount);
+ else
+ start = new MsgBolusStartWithSpeed(amount, speed);
MsgBolusStop stop = new MsgBolusStop(amount, t);
connect("bolus");
@@ -526,7 +537,7 @@ public class DanaRExecutionService extends Service {
connect("updateBasalsInPump");
if (!isConnected()) return false;
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates)));
- double[] basal = buildDanaRProfileRecord(profile);
+ double[] basal = DanaRPump.buildDanaRProfileRecord(profile);
MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal);
mSerialIOThread.sendMessage(msgSet);
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
@@ -537,19 +548,6 @@ public class DanaRExecutionService extends Service {
return true;
}
- 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((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) {
SystemClock.sleep(msecs);
}
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 d8c840f262..c8b2d04759 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
@@ -68,7 +68,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
private static DanaRKoreanExecutionService sExecutionService;
- private DanaRPump pump = DanaRPump.getInstance();
+ private static DanaRPump pump = DanaRPump.getInstance();
private boolean useExtendedBoluses = false;
private static DanaRKoreanPlugin plugin = null;
@@ -345,7 +345,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
// This is called from APS
@Override
- public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
// Recheck pump status if older than 30 min
if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
doConnect("setTempBasalAbsolute old data");
@@ -405,7 +405,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
// Correct basal already set ?
if (MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).percentRate == percentRate) {
- if (force) {
+ if (enforceNew) {
cancelTempBasal(true);
} else {
result.success = true;
@@ -646,7 +646,11 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf
}
public static void doConnect(String from) {
- if (sExecutionService != null) sExecutionService.connect(from);
+ if (sExecutionService != null) {
+ sExecutionService.connect(from);
+ pumpDescription.basalStep = pump.basalStep;
+ pumpDescription.bolusStep = pump.bolusStep;
+ }
}
public static boolean isConnected() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java
index 470d526360..f77c03e337 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/services/DanaRKoreanExecutionService.java
@@ -105,7 +105,7 @@ public class DanaRKoreanExecutionService extends Service {
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
+ log.debug("Device was disconnected " + device.getName());//Device was disconnected
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
if (mSerialIOThread != null) {
mSerialIOThread.disconnect("BT disconnection broadcast");
@@ -286,11 +286,13 @@ public class DanaRKoreanExecutionService extends Service {
}
}
- mSerialIOThread.sendMessage(new MsgSettingShippingInfo()); // TODO: show it somewhere
- mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
- mSerialIOThread.sendMessage(exStatusMsg);
//mSerialIOThread.sendMessage(statusMsg);
mSerialIOThread.sendMessage(statusBasicMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus)));
+ mSerialIOThread.sendMessage(tempStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus)));
+ mSerialIOThread.sendMessage(exStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
// if (!statusMsg.received) {
// mSerialIOThread.sendMessage(statusMsg);
@@ -316,6 +318,7 @@ public class DanaRKoreanExecutionService extends Service {
Date now = new Date();
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isInitialized()) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingMeal());
mSerialIOThread.sendMessage(new MsgSettingBasal_k());
@@ -323,6 +326,8 @@ public class DanaRKoreanExecutionService extends Service {
mSerialIOThread.sendMessage(new MsgSettingMaxValues());
mSerialIOThread.sendMessage(new MsgSettingGlucose());
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
+ mSerialIOThread.sendMessage(new MsgSettingPumpTime());
long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
log.debug("Pump time difference: " + timeDiff + " seconds");
if (Math.abs(timeDiff) > 10) {
@@ -502,7 +507,7 @@ public class DanaRKoreanExecutionService extends Service {
connect("updateBasalsInPump");
if (!isConnected()) return false;
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates)));
- double[] basal = buildDanaRProfileRecord(profile);
+ double[] basal = DanaRPump.buildDanaRProfileRecord(profile);
MsgSetSingleBasalProfile msgSet = new MsgSetSingleBasalProfile(basal);
mSerialIOThread.sendMessage(msgSet);
danaRPump.lastSettingsRead = new Date(0); // force read full settings
@@ -511,17 +516,6 @@ public class DanaRKoreanExecutionService extends Service {
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) {
SystemClock.sleep(msecs);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
new file mode 100644
index 0000000000..04a82ed1bd
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java
@@ -0,0 +1,818 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+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.data.DetailedBolusInfo;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.data.ProfileStore;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.db.ExtendedBolus;
+import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.db.Treatment;
+import info.nightscout.androidaps.events.EventPumpStatusChanged;
+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.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.DanaRFragment;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventAppExit;
+import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSDeviceChange;
+import info.nightscout.androidaps.plugins.PumpDanaRS.services.DanaRSService;
+import info.nightscout.utils.DateUtil;
+import info.nightscout.utils.Round;
+import info.nightscout.utils.SP;
+
+/**
+ * Created by mike on 03.09.2017.
+ */
+
+public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, ConstraintsInterface, ProfileInterface {
+ private static Logger log = LoggerFactory.getLogger(DanaRSPlugin.class);
+
+ @Override
+ public int getType() {
+ return PluginBase.PUMP;
+ }
+
+ @Override
+ public String getFragmentClass() {
+ return DanaRFragment.class.getName();
+ }
+
+ @Override
+ public String getName() {
+ return MainApp.instance().getString(R.string.danarspump);
+ }
+
+ @Override
+ public String getNameShort() {
+ String name = MainApp.sResources.getString(R.string.danarspump_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;
+ }
+
+ static boolean fragmentPumpEnabled = false;
+ static boolean fragmentProfileEnabled = false;
+ static boolean fragmentPumpVisible = false;
+
+ public static DanaRSService danaRSService;
+
+ public static String mDeviceAddress = "";
+ public static String mDeviceName = "";
+
+ private static DanaRSPlugin plugin = null;
+ private static DanaRPump pump = DanaRPump.getInstance();
+ public static PumpDescription pumpDescription = new PumpDescription();
+
+ public static DanaRSPlugin getPlugin() {
+ if (plugin == null)
+ plugin = new DanaRSPlugin();
+ return plugin;
+ }
+
+ DanaRSPlugin() {
+ Context context = MainApp.instance().getApplicationContext();
+ Intent intent = new Intent(context, DanaRSService.class);
+ context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ MainApp.bus().register(this);
+ onStatusEvent(new EventDanaRSDeviceChange()); // load device name
+
+ pumpDescription.isBolusCapable = true;
+ pumpDescription.bolusStep = 0.05d;
+
+ 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");
+ danaRSService = null;
+ }
+
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ log.debug("Service is connected");
+ DanaRSService.LocalBinder mLocalBinder = (DanaRSService.LocalBinder) service;
+ danaRSService = mLocalBinder.getServiceInstance();
+ }
+ };
+
+ @SuppressWarnings("UnusedParameters")
+ @Subscribe
+ public void onStatusEvent(final EventAppExit e) {
+ MainApp.instance().getApplicationContext().unbindService(mConnection);
+ }
+
+ @Subscribe
+ public void onStatusEvent(final EventDanaRSDeviceChange e) {
+ mDeviceAddress = SP.getString(R.string.key_danars_address, "");
+ mDeviceName = SP.getString(R.string.key_danars_name, "");
+ }
+
+ public static void connectIfNotConnected(String from) {
+ if (!isConnected())
+ connect(from);
+ }
+
+ public static synchronized void connect(String from) {
+ log.debug("RS connect from: " + from);
+ if (danaRSService != null && !mDeviceAddress.equals("") && !mDeviceName.equals("")) {
+ final Object o = new Object();
+
+ danaRSService.connect(from, mDeviceAddress, o);
+ synchronized (o) {
+ try {
+ o.wait(20000);
+ } catch (InterruptedException e) {
+ log.error("InterruptedException " + e);
+ }
+ }
+ pumpDescription.basalStep = pump.basalStep;
+ pumpDescription.bolusStep = pump.bolusStep;
+ if (isConnected())
+ log.debug("RS connected: " + from);
+ else {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.connectiontimedout)));
+ danaRSService.stopConnecting();
+ log.debug("RS connect failed from: " + from);
+ }
+ }
+ }
+
+ public static boolean isConnected() {
+ return danaRSService != null && danaRSService.isConnected();
+ }
+
+ public static boolean isConnecting() {
+ return danaRSService != null && danaRSService.isConnecting();
+ }
+
+ public static void disconnect(String from) {
+ if (danaRSService != null) danaRSService.disconnect(from);
+ }
+
+ public static void sendMessage(DanaRS_Packet message) {
+ if (danaRSService != null) danaRSService.sendMessage(message);
+ }
+
+ // DanaR interface
+
+ @Override
+ public boolean loadHistory(byte type) {
+ connectIfNotConnected("loadHistory");
+ return danaRSService.loadHistory(type);
+ }
+
+ // Constraints 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;
+ }
+
+ @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;
+ }
+
+ @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;
+ }
+
+ @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;
+ }
+
+ // Profile interface
+
+ @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();
+ }
+
+ // Pump interface
+
+ @Override
+ public boolean isInitialized() {
+ return pump.lastConnection.getTime() > 0;
+ }
+
+ @Override
+ public boolean isSuspended() {
+ return pump.pumpSuspended;
+ }
+
+ @Override
+ public boolean isBusy() {
+ if (danaRSService == null) return false;
+ return danaRSService.isConnected() || danaRSService.isConnecting();
+ }
+
+ @Override
+ public int setNewBasalProfile(Profile profile) {
+ if (danaRSService == 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));
+ }
+ connectIfNotConnected("updateBasalsInPump");
+ if (!danaRSService.updateBasalsInPump(profile)) {
+ Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(notification));
+ 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) {
+ log.debug("Refreshing data from pump");
+ if (!isConnected() && !isConnecting()) {
+ connect(reason);
+ } else
+ log.debug("Already connecting ...");
+ }
+
+ @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
+ int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0);
+ int speed = 12;
+ switch (preferencesSpeed) {
+ case 0:
+ speed = 12;
+ break;
+ case 1:
+ speed = 30;
+ break;
+ case 2:
+ speed = 60;
+ break;
+ }
+ // v2 stores end time for bolus, we need to adjust time
+ // default delivery speed is 12 U/min
+ detailedBolusInfo.date += detailedBolusInfo.insulin / speed * 60d * 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;
+ connectIfNotConnected("bolus");
+ if (detailedBolusInfo.insulin > 0 || carbs > 0)
+ connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, System.currentTimeMillis() + carbTime * 60 * 1000 + 1000, t); // +1000 to make the record different
+ PumpEnactResult result = new PumpEnactResult();
+ 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 (danaRSService == null) {
+ log.error("stopBolusDelivering sExecutionService is null");
+ return;
+ }
+ danaRSService.bolusStop();
+ }
+
+ // This is called from APS
+ @Override
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
+ // Recheck pump status if older than 30 min
+ if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
+ connect("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 (!enforceNew) {
+ 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;
+ TemporaryBasal runningTB = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
+ if (runningTB != null && runningTB.percentRate == 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);
+ connectIfNotConnected("tempbasal");
+ boolean connectionOK = danaRSService.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();
+ connectIfNotConnected("hightempbasal");
+ boolean connectionOK = danaRSService.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();
+ ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
+ if (runningEB != null && Math.abs(runningEB.insulin - 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;
+ }
+ connectIfNotConnected("extendedBolus");
+ boolean connectionOK = danaRSService.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();
+ TemporaryBasal runningTB = MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis());
+ if (runningTB != null) {
+ connectIfNotConnected("tempBasalStop");
+ danaRSService.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();
+ ExtendedBolus runningEB = MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis());
+ if (runningEB != null) {
+ connectIfNotConnected("extendedBolusStop");
+ danaRSService.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;
+ }
+ }
+
+ @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) {
+ log.error("Unhandled exception", e);
+ }
+ return pumpjson;
+ }
+
+ @Override
+ public String deviceID() {
+ return pump.serialNumber;
+ }
+
+ @Override
+ public PumpDescription getPumpDescription() {
+ return pumpDescription;
+ }
+
+ @Override
+ public String shortStatus(boolean veryShort) {
+ return null;
+ }
+
+ @Override
+ public boolean isFakingTempsByExtendedBoluses() {
+ return false;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java
new file mode 100644
index 0000000000..8e973903f9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java
@@ -0,0 +1,232 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.activities;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanResult;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSDeviceChange;
+import info.nightscout.utils.SP;
+
+public class BLEScanActivity extends AppCompatActivity {
+ private static Logger log = LoggerFactory.getLogger(BLEScanActivity.class);
+
+ private Context mContext = null;
+
+ private ListView listView = null;
+ private ListAdapter mListAdapter = null;
+ private ArrayList mDevices = new ArrayList<>();
+ ;
+
+ private BluetoothAdapter mBluetoothAdapter = null;
+ private BluetoothLeScanner mBluetoothLeScanner = null;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.danars_blescanner_activity);
+
+ mListAdapter = new ListAdapter();
+
+ listView = (ListView) findViewById(R.id.danars_blescanner_listview);
+ listView.setEmptyView(findViewById(R.id.danars_blescanner_nodevice));
+ listView.setAdapter(mListAdapter);
+
+ initView();
+ }
+
+ private void initView() {
+ mContext = getApplicationContext();
+
+ BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = bluetoothManager.getAdapter();
+ mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
+
+ // MIKE: test mBluetoothLeScanner for null (bt disabled)
+
+ mListAdapter.notifyDataSetChanged();
+
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ startScan();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ stopScan();
+ }
+
+ private void startScan() {
+ mBluetoothLeScanner.startScan(mBleScanCallback);
+ }
+
+ private void stopScan() {
+ mBluetoothLeScanner.stopScan(mBleScanCallback);
+ }
+
+ private void addBleDevice(BluetoothDevice device) {
+ if (device == null || device.getName() == null || device.getName().equals("")) {
+ return;
+ }
+ BluetoothDeviceItem item = new BluetoothDeviceItem(device);
+ if (!isSNCheck(device.getName()) || mDevices.contains(item)) {
+ return;
+ }
+
+ mDevices.add(item);
+ new Handler().post(new Runnable() {
+ public void run() {
+ mListAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+
+ private ScanCallback mBleScanCallback = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ addBleDevice(result.getDevice());
+ }
+ };
+
+ class ListAdapter extends BaseAdapter {
+
+ @Override
+ public int getCount() {
+ return mDevices.size();
+ }
+
+ @Override
+ public BluetoothDeviceItem getItem(int i) {
+ return mDevices.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int i, View convertView, ViewGroup parent) {
+ View v = convertView;
+ ViewHolder holder;
+
+ if (v == null) {
+ v = View.inflate(mContext, R.layout.danars_blescanner_item, null);
+ holder = new ViewHolder(v);
+ v.setTag(holder);
+ } else {
+ holder = (ViewHolder) v.getTag();
+ }
+
+ BluetoothDeviceItem item = getItem(i);
+ holder.setData(i, item);
+ return v;
+ }
+
+ private class ViewHolder implements View.OnClickListener {
+ private BluetoothDeviceItem item = null;
+
+ private TextView mName = null;
+ private TextView mAddress = null;
+
+ public ViewHolder(View v) {
+ mName = (TextView) v.findViewById(R.id.ble_name);
+ mAddress = (TextView) v.findViewById(R.id.ble_address);
+
+ v.setOnClickListener(ViewHolder.this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ SP.putString(R.string.key_danars_address, item.device.getAddress());
+ SP.putString(R.string.key_danars_name, mName.getText().toString());
+ MainApp.bus().post(new EventDanaRSDeviceChange());
+ finish();
+ }
+
+ public void setData(int pos, BluetoothDeviceItem data) {
+ if (data != null) {
+ try {
+ String tTitle = data.device.getName();
+ if (tTitle == null || tTitle.equals("")) {
+ tTitle = "(unknown)";
+ } else if (tTitle.length() > 10) {
+ tTitle = tTitle.substring(0, 10);
+ }
+ mName.setText(tTitle);
+
+ mAddress.setText(data.device.getAddress());
+
+ item = data;
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+ }
+
+ //
+ private class BluetoothDeviceItem {
+ private BluetoothDevice device;
+
+ public BluetoothDeviceItem(BluetoothDevice device) {
+ super();
+ this.device = device;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (device == null || o == null || !(o instanceof BluetoothDeviceItem)) {
+ return false;
+ }
+ BluetoothDeviceItem checkItem = (BluetoothDeviceItem) o;
+ if (checkItem.device == null) {
+ return false;
+ }
+ return stringEquals(device.getAddress(), checkItem.device.getAddress());
+ }
+
+ public boolean stringEquals(String arg1, String arg2) {
+ try {
+ return arg1.equals(arg2);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ }
+
+ public static boolean isSNCheck(String sn) {
+ String regex = "^([a-zA-Z]{3})([0-9]{5})([a-zA-Z]{2})$";
+ Pattern p = Pattern.compile(regex);
+ Matcher m = p.matcher(sn);
+
+ return m.matches();
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingHelperActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingHelperActivity.java
new file mode 100644
index 0000000000..c67534ac75
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingHelperActivity.java
@@ -0,0 +1,15 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.activities;
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+public class PairingHelperActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ PairingProgressDialog bolusProgressDialog = new PairingProgressDialog();
+ bolusProgressDialog.setHelperActivity(this);
+ bolusProgressDialog.show(this.getSupportFragmentManager(), "PairingProgress");
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingProgressDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingProgressDialog.java
new file mode 100644
index 0000000000..00cbdb4628
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/PairingProgressDialog.java
@@ -0,0 +1,148 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.activities;
+
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.squareup.otto.Subscribe;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPairingSuccess;
+
+
+public class PairingProgressDialog extends DialogFragment implements View.OnClickListener {
+
+ TextView statusView;
+ ProgressBar progressBar;
+ Button button;
+ PairingHelperActivity helperActivity;
+
+ static int secondsPassed = 0;
+ public static boolean pairingEnded = false;
+ public static boolean running = true;
+
+ private static Handler sHandler;
+ private static HandlerThread sHandlerThread;
+
+ public PairingProgressDialog() {
+ super();
+ // Required empty public constructor
+ if (sHandlerThread == null) {
+ sHandlerThread = new HandlerThread(PairingProgressDialog.class.getSimpleName());
+ sHandlerThread.start();
+ sHandler = new Handler(sHandlerThread.getLooper());
+ }
+ secondsPassed = 0;
+ }
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.danars_pairingprogressdialog, container, false);
+ getDialog().setTitle(MainApp.sResources.getString(R.string.pairing));
+ statusView = (TextView) view.findViewById(R.id.danars_paringprogress_status);
+ progressBar = (ProgressBar) view.findViewById(R.id.danars_paringprogress_progressbar);
+ button = (Button) view.findViewById(R.id.ok);
+
+ progressBar.setMax(100);
+ progressBar.setProgress(0);
+ statusView.setText(MainApp.sResources.getString(R.string.waitingforpairing));
+ button.setVisibility(View.GONE);
+ button.setOnClickListener(this);
+ setCancelable(false);
+
+ sHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < 20; i++) {
+ if (pairingEnded) {
+ Activity activity = getActivity();
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ progressBar.setProgress(100);
+ statusView.setText(R.string.pairingok);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ dismiss();
+ }
+ });
+ } else
+ dismiss();
+ return;
+ }
+ progressBar.setProgress(i * 5);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ Activity activity = getActivity();
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ progressBar.setProgress(100);
+ statusView.setText(R.string.pairingtimedout);
+ button.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+ }
+ });
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ MainApp.bus().register(this);
+ running = true;
+ if (pairingEnded) dismiss();
+ }
+
+ @Override
+ public void dismiss() {
+ super.dismiss();
+ if (helperActivity != null) {
+ helperActivity.finish();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ MainApp.bus().unregister(this);
+ running = false;
+ }
+
+ @Subscribe
+ public void onStatusEvent(final EventDanaRSPairingSuccess ev) {
+ pairingEnded = true;
+ }
+
+ public void setHelperActivity(PairingHelperActivity activity) {
+ this.helperActivity = activity;
+ }
+
+ @Override
+ public void onClick(View v) {
+ running = false;
+ dismiss();
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRSMessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRSMessageHashTable.java
new file mode 100644
index 0000000000..5457bb4155
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRSMessageHashTable.java
@@ -0,0 +1,108 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+
+import info.nightscout.androidaps.Config;
+
+/**
+ * Created by mike on 28.05.2016.
+ */
+public class DanaRSMessageHashTable {
+ private static Logger log = LoggerFactory.getLogger(DanaRSMessageHashTable.class);
+
+ public static HashMap messages = null;
+
+ static {
+ if (messages == null) {
+ boolean savedState = Config.logDanaMessageDetail;
+ Config.logDanaMessageDetail = false;
+
+ messages = new HashMap<>();
+ put(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal());
+ put(new DanaRS_Packet_Basal_Get_Basal_Rate());
+ put(new DanaRS_Packet_Basal_Get_Profile_Basal_Rate());
+ put(new DanaRS_Packet_Basal_Get_Profile_Number());
+ put(new DanaRS_Packet_Basal_Set_Basal_Rate());
+ put(new DanaRS_Packet_Basal_Set_Profile_Basal_Rate());
+ put(new DanaRS_Packet_Basal_Set_Profile_Number());
+ put(new DanaRS_Packet_Basal_Set_Suspend_Off());
+ put(new DanaRS_Packet_Basal_Set_Suspend_On());
+ put(new DanaRS_Packet_Basal_Set_Temporary_Basal());
+ put(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+ put(new DanaRS_Packet_Bolus_Get_Bolus_Option());
+ put(new DanaRS_Packet_Bolus_Get_Initial_Bolus());
+ put(new DanaRS_Packet_Bolus_Get_Calculation_Information());
+ put(new DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information());
+ put(new DanaRS_Packet_Bolus_Get_CIR_CF_Array());
+ put(new DanaRS_Packet_Bolus_Get_Dual_Bolus());
+ put(new DanaRS_Packet_Bolus_Get_Extended_Bolus());
+ put(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State());
+ put(new DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State());
+ put(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information());
+ put(new DanaRS_Packet_Bolus_Set_Bolus_Option());
+ put(new DanaRS_Packet_Bolus_Set_Initial_Bolus());
+ put(new DanaRS_Packet_Bolus_Set_CIR_CF_Array());
+ put(new DanaRS_Packet_Bolus_Set_Dual_Bolus());
+ put(new DanaRS_Packet_Bolus_Set_Extended_Bolus());
+ put(new DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel());
+ put(new DanaRS_Packet_Bolus_Set_Step_Bolus_Start());
+ put(new DanaRS_Packet_Bolus_Set_Step_Bolus_Stop());
+ put(new DanaRS_Packet_Etc_Keep_Connection());
+ put(new DanaRS_Packet_Etc_Set_History_Save());
+ put(new DanaRS_Packet_General_Delivery_Status());
+ put(new DanaRS_Packet_General_Get_Password());
+ put(new DanaRS_Packet_General_Initial_Screen_Information());
+ put(new DanaRS_Packet_Notify_Alarm());
+ put(new DanaRS_Packet_Notify_Delivery_Complete());
+ put(new DanaRS_Packet_Notify_Delivery_Rate_Display());
+ put(new DanaRS_Packet_Notify_Missed_Bolus_Alarm());
+ put(new DanaRS_Packet_Option_Get_Pump_Time());
+ put(new DanaRS_Packet_Option_Get_User_Option());
+ put(new DanaRS_Packet_Option_Set_Pump_Time());
+ put(new DanaRS_Packet_Option_Set_User_Option());
+ //put(new DanaRS_Packet_History_());
+ put(new DanaRS_Packet_History_Alarm());
+ put(new DanaRS_Packet_History_All_History());
+ put(new DanaRS_Packet_History_Basal());
+ put(new DanaRS_Packet_History_Blood_Glucose());
+ put(new DanaRS_Packet_History_Bolus());
+ put(new DanaRS_Packet_Review_Bolus_Avg());
+ put(new DanaRS_Packet_History_Carbohydrate());
+ put(new DanaRS_Packet_History_Daily());
+ put(new DanaRS_Packet_General_Get_More_Information());
+ put(new DanaRS_Packet_General_Get_Pump_Check());
+ put(new DanaRS_Packet_General_Get_Shipping_Information());
+ put(new DanaRS_Packet_General_Get_Today_Delivery_Total());
+ put(new DanaRS_Packet_General_Get_User_Time_Change_Flag());
+ put(new DanaRS_Packet_History_Prime());
+ put(new DanaRS_Packet_History_Refill());
+ put(new DanaRS_Packet_General_Set_History_Upload_Mode());
+ put(new DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear());
+ put(new DanaRS_Packet_History_Suspend());
+ put(new DanaRS_Packet_History_Temporary());
+
+ // APS
+ put(new DanaRS_Packet_APS_Basal_Set_Temporary_Basal());
+ put(new DanaRS_Packet_APS_History_Events());
+ put(new DanaRS_Packet_APS_Set_Event_History());
+
+ Config.logDanaMessageDetail = savedState;
+ }
+ }
+
+ public static void put(DanaRS_Packet message) {
+ int command = message.getCommand();
+ messages.put(command, message);
+ }
+
+ public static DanaRS_Packet findMessage(Integer command) {
+ if (messages.containsKey(command)) {
+ return messages.get(command);
+ } else {
+ return new DanaRS_Packet();
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet.java
new file mode 100644
index 0000000000..8ac5bfac13
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet.java
@@ -0,0 +1,207 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import android.annotation.TargetApi;
+import android.os.Build;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+public class DanaRS_Packet {
+ protected static final int TYPE_START = 0;
+ protected static final int OPCODE_START = 1;
+ protected static final int DATA_START = 2;
+
+ private boolean received;
+ protected boolean failed;
+ protected int type = BleCommandUtil.DANAR_PACKET__TYPE_RESPONSE; // most of the messages, should be changed for others
+ protected int opCode;
+
+ public DanaRS_Packet() {
+ received = false;
+ failed = false;
+ }
+
+ public void setReceived() {
+ received = true;
+ }
+
+ public boolean isReceived() {
+ return received;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public int getOpCode() {
+ return opCode;
+ }
+
+ public int getCommand() {
+ return ((type & 0xFF) << 8) + (opCode & 0xFF);
+ }
+
+ public byte[] getRequestParams() {
+ return null;
+ }
+
+ ;
+
+ // STATIC FUNCTIONS
+
+ public static int getCommand(byte[] data) {
+ int type = byteArrayToInt(getBytes(data, TYPE_START, 1));
+ int opCode = byteArrayToInt(getBytes(data, OPCODE_START, 1));
+ return ((type & 0xFF) << 8) + (opCode & 0xFF);
+ }
+
+ public void handleMessage(byte[] data) {
+ }
+
+ public String getFriendlyName() {
+ return "UNKNOWN_PACKET";
+ }
+
+ protected static byte[] getBytes(byte[] data, int srcStart, int srcLength) {
+ try {
+ byte[] ret = new byte[srcLength];
+
+ System.arraycopy(data, srcStart, ret, 0, srcLength);
+
+ return ret;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ protected static int byteArrayToInt(byte[] b) {
+ int ret;
+
+ switch (b.length) {
+ case 1:
+ ret = b[0] & 0x000000FF;
+ break;
+ case 2:
+ ret = ((b[1] & 0x000000FF) << 8) + (b[0] & 0x000000FF);
+ break;
+ case 3:
+ ret = ((b[2] & 0x000000FF) << 16) + ((b[1] & 0x000000FF) << 8) + (b[0] & 0x000000FF);
+ break;
+ case 4:
+ ret = ((b[3] & 0x000000FF) << 24) + ((b[2] & 0x000000FF) << 16) + ((b[1] & 0x000000FF) << 8) + (b[0] & 0x000000FF);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ return ret;
+ }
+
+ public static Date dateTimeSecFromBuff(byte[] buff, int offset) {
+ Date date =
+ new Date(
+ 100 + intFromBuff(buff, offset, 1),
+ intFromBuff(buff, offset + 1, 1) - 1,
+ intFromBuff(buff, offset + 2, 1),
+ intFromBuff(buff, offset + 3, 1),
+ intFromBuff(buff, offset + 4, 1),
+ intFromBuff(buff, offset + 5, 1)
+ );
+ return date;
+ }
+
+ protected static int intFromBuff(byte[] b, int srcStart, int srcLength) {
+ int ret;
+
+ switch (srcLength) {
+ case 1:
+ ret = b[DATA_START + srcStart + 0] & 0x000000FF;
+ break;
+ case 2:
+ ret = ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 0] & 0x000000FF);
+ break;
+ case 3:
+ ret = ((b[DATA_START + srcStart + 2] & 0x000000FF) << 16) + ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 0] & 0x000000FF);
+ break;
+ case 4:
+ ret = ((b[DATA_START + srcStart + 3] & 0x000000FF) << 24) + ((b[DATA_START + srcStart + 2] & 0x000000FF) << 16) + ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 0] & 0x000000FF);
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ return ret;
+ }
+
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ public static String stringFromBuff(byte[] buff, int offset, int length) {
+ byte[] strbuff = new byte[length];
+ System.arraycopy(buff, offset, strbuff, 0, length);
+ return new String(strbuff, StandardCharsets.UTF_8);
+ }
+
+ public static Date dateFromBuff(byte[] buff, int offset) {
+ Date date =
+ new Date(
+ 100 + byteArrayToInt(getBytes(buff, offset, 1)),
+ byteArrayToInt(getBytes(buff, offset + 1, 1)) - 1,
+ byteArrayToInt(getBytes(buff, offset + 2, 1))
+ );
+ return date;
+ }
+
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+
+ public static String asciiStringFromBuff(byte[] buff, int offset, int length) {
+ byte[] strbuff = new byte[length];
+ System.arraycopy(buff, offset, strbuff, 0, length);
+ for (int pos = 0; pos < length; pos++)
+ strbuff[pos] += 65; // "A"
+ return new String(strbuff, StandardCharsets.UTF_8);
+ }
+
+ public static String toHexString(byte[] buff) {
+ if (buff == null)
+ return "";
+
+ StringBuffer sb = new StringBuffer();
+
+ int count = 0;
+ for (byte element : buff) {
+ sb.append(String.format("%02X ", element));
+ if (++count % 4 == 0) sb.append(" ");
+ }
+
+ return sb.toString();
+ }
+
+ final private static char[] hexArray = "0123456789ABCDEF".toCharArray();
+
+ public static String bytesToHex(byte[] bytes) {
+ char[] hexChars = new char[bytes.length * 2];
+ for (int j = 0; j < bytes.length; j++) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+ public static byte[] hexToBytes(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i + 1), 16));
+ }
+ return data;
+ }
+
+ public static int ByteToInt(byte b) {
+ return b & 0x000000FF;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java
new file mode 100644
index 0000000000..7ce847dc58
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Basal_Set_Temporary_Basal.java
@@ -0,0 +1,67 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+public class DanaRS_Packet_APS_Basal_Set_Temporary_Basal extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Basal_Set_Temporary_Basal.class);
+
+ private int temporaryBasalRatio;
+ private int temporaryBasalDuration;
+ public int error;
+
+ public DanaRS_Packet_APS_Basal_Set_Temporary_Basal() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__APS_SET_TEMPORARY_BASAL;
+ }
+
+ public DanaRS_Packet_APS_Basal_Set_Temporary_Basal(int percent) {
+ this();
+
+ //HARDCODED LIMITS
+ if (percent < 0) percent = 0;
+ if (percent > 500) percent = 500;
+
+ temporaryBasalRatio = percent;
+ if (percent < 100) {
+ temporaryBasalDuration = 160;
+ if (Config.logDanaMessageDetail)
+ log.debug("APS Temp basal start percent: " + percent + " duration 30 min");
+ } else {
+ temporaryBasalDuration = 150;
+ if (Config.logDanaMessageDetail)
+ log.debug("APS Temp basal start percent: " + percent + " duration 15 min");
+ }
+
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[3];
+ request[0] = (byte) (temporaryBasalRatio & 0xff);
+ request[1] = (byte) ((temporaryBasalRatio >>> 8) & 0xff);
+ request[2] = (byte) (temporaryBasalDuration & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int result = byteArrayToInt(getBytes(data, DATA_START, 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);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__APS_SET_TEMPORARY_BASAL";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java
new file mode 100644
index 0000000000..fe010eb72f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_History_Events.java
@@ -0,0 +1,190 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.data.DetailedBolusInfo;
+import info.nightscout.androidaps.db.DanaRHistoryRecord;
+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.RecordTypes;
+import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus;
+import info.nightscout.utils.DateUtil;
+
+public class DanaRS_Packet_APS_History_Events extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_History_Events.class);
+
+ private int year = 0;
+ private int month = 0;
+ private int day = 0;
+ private int hour = 0;
+ private int min = 0;
+ private int sec = 0;
+
+ public boolean done;
+ public int totalCount;
+
+ public static long lastEventTimeLoaded = 0;
+
+ public DanaRS_Packet_APS_History_Events() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS;
+ done = false;
+ totalCount = 0;
+ }
+
+ public DanaRS_Packet_APS_History_Events(long from) {
+ this();
+ GregorianCalendar cal = new GregorianCalendar();
+ if (from != 0)
+ cal.setTimeInMillis(from);
+ else
+ cal.set(2000, 0, 1, 0, 0, 0);
+ year = cal.get(Calendar.YEAR) - 1900 - 100;
+ month = cal.get(Calendar.MONTH) + 1;
+ day = cal.get(Calendar.DAY_OF_MONTH);
+ hour = cal.get(Calendar.HOUR_OF_DAY);
+ min = cal.get(Calendar.MINUTE);
+ sec = cal.get(Calendar.SECOND);
+ log.debug("Loading event history from: " + new Date(cal.getTimeInMillis()).toLocaleString());
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[6];
+ request[0] = (byte) (year & 0xff);
+ request[1] = (byte) (month & 0xff);
+ request[2] = (byte) (day & 0xff);
+ request[3] = (byte) (hour & 0xff);
+ request[4] = (byte) (min & 0xff);
+ request[5] = (byte) (sec & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ byte recordCode = (byte) intFromBuff(data, 0, 1);
+
+ // Last record
+ if (recordCode == (byte) 0xFF) {
+ done = true;
+ return;
+ }
+
+ Date datetime = dateTimeSecFromBuff(data, 1); // 6 bytes
+ int param1 = ((intFromBuff(data, 7, 1) << 8) & 0xFF00) + (intFromBuff(data, 8, 1) & 0xFF);
+ int param2 = ((intFromBuff(data, 9, 1) << 8) & 0xFF00) + (intFromBuff(data, 10, 1) & 0xFF);
+
+ 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;
+ case DanaRPump.PRIMECANNULA:
+ log.debug("EVENT PRIME CANNULA(" + recordCode + ") " + datetime.toLocaleString() + " Amount: " + param1 / 100d + "U");
+ break;
+ default:
+ log.debug("Event: " + recordCode + " " + datetime.toLocaleString() + " Param1: " + param1 + " Param2: " + param2);
+ break;
+ }
+
+ if (datetime.getTime() > lastEventTimeLoaded)
+ lastEventTimeLoaded = datetime.getTime();
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "APS_HISTORY_EVENTS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java
new file mode 100644
index 0000000000..0f102090a7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_APS_Set_Event_History.java
@@ -0,0 +1,77 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import info.nightscout.androidaps.Config;
+
+public class DanaRS_Packet_APS_Set_Event_History extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_APS_Set_Event_History.class);
+
+ private int type;
+ private long time;
+ public int param1;
+ public int param2;
+
+ public DanaRS_Packet_APS_Set_Event_History() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE__APS_SET_EVENT_HISTORY;
+ }
+
+ public DanaRS_Packet_APS_Set_Event_History(int type, long time, int param1, int param2) {
+ this();
+
+ this.type = type;
+ this.time = time;
+ this.param1 = param1;
+ this.param2 = param2;
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTimeInMillis(time);
+ int year = cal.get(Calendar.YEAR) - 1900 - 100;
+ int month = cal.get(Calendar.MONTH) + 1;
+ int day = cal.get(Calendar.DAY_OF_MONTH);
+ int hour = cal.get(Calendar.HOUR_OF_DAY);
+ int min = cal.get(Calendar.MINUTE);
+ int sec = cal.get(Calendar.SECOND);
+
+ byte[] request = new byte[11];
+ request[0] = (byte) (type & 0xff);
+ request[1] = (byte) (year & 0xff);
+ request[2] = (byte) (month & 0xff);
+ request[3] = (byte) (day & 0xff);
+ request[4] = (byte) (hour & 0xff);
+ request[5] = (byte) (min & 0xff);
+ request[6] = (byte) (sec & 0xff);
+ request[7] = (byte) ((param1 >>> 8) & 0xff);
+ request[8] = (byte) (param1 & 0xff);
+ request[9] = (byte) ((param2 >>> 8) & 0xff);
+ request[10] = (byte) (param2 & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int result = intFromBuff(data, 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);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "APS_SET_EVENT_HISTORY";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java
new file mode 100644
index 0000000000..efc87d3834
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Basal_Rate.java
@@ -0,0 +1,68 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.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.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 com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Get_Basal_Rate extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.class);
+
+
+ public DanaRS_Packet_Basal_Get_Basal_Rate() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__GET_BASAL_RATE;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Requesting basal rates");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 2;
+ pump.maxBasal = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.basalStep = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][];
+ pump.pumpProfiles[pump.activeProfile] = new double[24];
+ for (int i = 0, size = 24; i < size; i++) {
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.pumpProfiles[pump.activeProfile][i] = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+ }
+ if (Config.logDanaMessageDetail) {
+ log.debug("Max basal: " + pump.maxBasal + " U");
+ log.debug("Basal step: " + pump.basalStep + " U");
+ for (int index = 0; index < 24; index++)
+ log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[pump.activeProfile][index]);
+ }
+
+ if (pump.basalStep != 0.01d) {
+ Notification notification = new Notification(Notification.WRONGBASALSTEP, MainApp.sResources.getString(R.string.danar_setbasalstep001), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(notification));
+ } else {
+ MainApp.bus().post(new EventDismissNotification(Notification.WRONGBASALSTEP));
+ }
+
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__GET_BASAL_RATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java
new file mode 100644
index 0000000000..8eadb8298d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Basal_Rate.java
@@ -0,0 +1,61 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Basal_Get_Profile_Basal_Rate extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Get_Profile_Basal_Rate.class);
+
+ private int profileNumber;
+
+ public DanaRS_Packet_Basal_Get_Profile_Basal_Rate() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_BASAL_RATE;
+ }
+
+ // 0 - 4
+ public DanaRS_Packet_Basal_Get_Profile_Basal_Rate(int profileNumber) {
+ this();
+ this.profileNumber = profileNumber;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Requesting basal rates for profile " + profileNumber);
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[1];
+ request[0] = (byte) (profileNumber & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 2;
+
+ if (pump.pumpProfiles == null) pump.pumpProfiles = new double[4][];
+ pump.pumpProfiles[profileNumber] = new double[24];
+ for (int i = 0, size = 24; i < size; i++) {
+ pump.pumpProfiles[profileNumber][i] = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+ dataIndex += dataSize;
+ dataSize = 2;
+ }
+ if (Config.logDanaMessageDetail) {
+ for (int index = 0; index < 24; index++)
+ log.debug("Basal " + String.format("%02d", index) + "h: " + pump.pumpProfiles[profileNumber][index]);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__GET_PROFILE_BASAL_RATE";
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java
new file mode 100644
index 0000000000..39e230a29e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Profile_Number.java
@@ -0,0 +1,37 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Basal_Get_Profile_Number extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Get_Profile_Number.class);
+
+ public DanaRS_Packet_Basal_Get_Profile_Number() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__GET_PROFILE_NUMBER;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Requesting active profile");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ pump.activeProfile = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Active profile: " + pump.activeProfile);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__GET_PROFILE_NUMBER";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java
new file mode 100644
index 0000000000..dbf917874d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Get_Temporary_Basal_State.java
@@ -0,0 +1,77 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import android.support.annotation.NonNull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Basal_Get_Temporary_Basal_State extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Get_Temporary_Basal_State.class);
+
+ public DanaRS_Packet_Basal_Get_Temporary_Basal_State() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__TEMPORARY_BASAL_STATE;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Requesting temporary basal status");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.isTempBasalInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01;
+ boolean isAPSTempBasalInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x02;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.tempBasalPercent = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (pump.tempBasalPercent > 200) pump.tempBasalPercent = (pump.tempBasalPercent - 200) * 10;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int durationHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (durationHour == 150) pump.tempBasalTotalSec = 15 * 60;
+ else if (durationHour == 160) pump.tempBasalTotalSec = 30 * 60;
+ else pump.tempBasalTotalSec = durationHour * 60 * 60;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ int runningMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ int tempBasalRemainingMin = (pump.tempBasalTotalSec - runningMin * 60) / 60;
+ Date tempBasalStart = pump.isTempBasalInProgress ? getDateFromTempBasalSecAgo(runningMin * 60) : new Date(0);
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Error code: " + error);
+ log.debug("Is temp basal running: " + pump.isTempBasalInProgress);
+ log.debug("Is APS temp basal running: " + isAPSTempBasalInProgress);
+ log.debug("Current temp basal percent: " + pump.tempBasalPercent);
+ log.debug("Current temp basal remaining min: " + tempBasalRemainingMin);
+ log.debug("Current temp basal total sec: " + pump.tempBasalTotalSec);
+ log.debug("Current temp basal start: " + tempBasalStart);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__TEMPORARY_BASAL_STATE";
+ }
+
+ @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/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java
new file mode 100644
index 0000000000..6f56464c51
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Basal_Rate.java
@@ -0,0 +1,53 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Basal_Rate extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Basal_Rate.class);
+
+ private double[] profileBasalRate;
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Basal_Rate() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__SET_BASAL_RATE;
+ }
+
+ public DanaRS_Packet_Basal_Set_Basal_Rate(double[] profileBasalRate) {
+ this();
+ this.profileBasalRate = profileBasalRate;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting new basal rates");
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[48];
+ for (int i = 0, size = 24; i < size; i++) {
+ int rate = (int) (profileBasalRate[i] * 100d);
+ request[0 + (i * 2)] = (byte) (rate & 0xff);
+ request[1 + (i * 2)] = (byte) ((rate >>> 8) & 0xff);
+ }
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__SET_BASAL_RATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java
new file mode 100644
index 0000000000..70a8b02826
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.java
@@ -0,0 +1,36 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal.class);
+
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__CANCEL_TEMPORARY_BASAL;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Canceling temp basal");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ error = byteArrayToInt(getBytes(data, DATA_START, 1));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__CANCEL_TEMPORARY_BASAL";
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java
new file mode 100644
index 0000000000..82a63f0ca7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Basal_Rate.java
@@ -0,0 +1,56 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Profile_Basal_Rate extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Profile_Basal_Rate.class);
+
+ private int profileNumber; // 0 - 4
+ private double[] profileBasalRate;
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Profile_Basal_Rate() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_BASAL_RATE;
+ }
+
+ public DanaRS_Packet_Basal_Set_Profile_Basal_Rate(int profileNumber, double[] profileBasalRate) {
+ this();
+ this.profileNumber = profileNumber;
+ this.profileBasalRate = profileBasalRate;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting new basal rates for profile " + profileNumber);
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[49];
+ request[0] = (byte) (profileNumber & 0xff);
+ for (int i = 0, size = 24; i < size; i++) {
+ int rate = (int) (profileBasalRate[i] * 100d);
+ request[1 + (i * 2)] = (byte) (rate & 0xff);
+ request[2 + (i * 2)] = (byte) ((rate >>> 8) & 0xff);
+ }
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__SET_PROFILE_BASAL_RATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java
new file mode 100644
index 0000000000..fe47f89dfc
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Profile_Number.java
@@ -0,0 +1,48 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Profile_Number extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Profile_Number.class);
+ private int profileNumber;
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Profile_Number() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__SET_PROFILE_NUMBER;
+ }
+ public DanaRS_Packet_Basal_Set_Profile_Number(int profileNumber) {
+ this();
+ this.profileNumber = profileNumber;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting profile number " + profileNumber);
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[1];
+ request[0] = (byte) (profileNumber & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__SET_PROFILE_NUMBER";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java
new file mode 100644
index 0000000000..1b9444c2d3
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_Off.java
@@ -0,0 +1,35 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Suspend_Off extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Suspend_Off.class);
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Suspend_Off() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_OFF;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Turning off suspend");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__SET_SUSPEND_OFF";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java
new file mode 100644
index 0000000000..01e90e026c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Suspend_On.java
@@ -0,0 +1,35 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Suspend_On extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Suspend_On.class);
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Suspend_On() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__SET_SUSPEND_ON;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Turning on suspend");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__SET_SUSPEND_ON";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java
new file mode 100644
index 0000000000..a81d85f016
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Basal_Set_Temporary_Basal.java
@@ -0,0 +1,52 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Basal_Set_Temporary_Basal extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Basal_Set_Temporary_Basal.class);
+
+ private int temporaryBasalRatio;
+ private int temporaryBasalDuration;
+ public int error;
+
+ public DanaRS_Packet_Basal_Set_Temporary_Basal() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BASAL__SET_TEMPORARY_BASAL;
+ }
+
+ public DanaRS_Packet_Basal_Set_Temporary_Basal(int temporaryBasalRatio, int temporaryBasalDuration) {
+ this();
+ this.temporaryBasalRatio = temporaryBasalRatio;
+ this.temporaryBasalDuration = temporaryBasalDuration;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting temporary basal of " + temporaryBasalRatio + "% for " + temporaryBasalDuration + " hours");
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[2];
+ request[0] = (byte) (temporaryBasalRatio & 0xff);
+ request[1] = (byte) (temporaryBasalDuration & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BASAL__SET_TEMPORARY_BASAL";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java
new file mode 100644
index 0000000000..61296f42ed
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Bolus_Option.java
@@ -0,0 +1,137 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.Overview.Notification;
+import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
+import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Bolus_Option extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Bolus_Option.class);
+
+ public DanaRS_Packet_Bolus_Get_Bolus_Option() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_OPTION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ pump.isExtendedBolusEnabled = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 1;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.bolusCalculationOption = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.missedBolusConfig = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus01StartHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus01StartMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus01EndHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus01EndMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus02StartHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus02StartMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus02EndHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus02EndMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus03StartHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus03StartMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus03EndHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus03EndMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus04StartHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus04StartMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus04EndHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int missedBolus04EndMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (!pump.isExtendedBolusEnabled) {
+ Notification notification = new Notification(Notification.EXTENDED_BOLUS_DISABLED, MainApp.sResources.getString(R.string.danar_enableextendedbolus), Notification.URGENT);
+ MainApp.bus().post(new EventNewNotification(notification));
+ } else {
+ MainApp.bus().post(new EventDismissNotification(Notification.EXTENDED_BOLUS_DISABLED));
+ }
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Extended bolus enabled: " + pump.isExtendedBolusEnabled);
+ log.debug("Missed bolus config: " + pump.missedBolusConfig);
+ log.debug("missedBolus01StartHour: " + missedBolus01StartHour);
+ log.debug("missedBolus01StartMin: " + missedBolus01StartMin);
+ log.debug("missedBolus01EndHour: " + missedBolus01EndHour);
+ log.debug("missedBolus01EndMin: " + missedBolus01EndMin);
+ log.debug("missedBolus02StartHour: " + missedBolus02StartHour);
+ log.debug("missedBolus02StartMin: " + missedBolus02StartMin);
+ log.debug("missedBolus02EndHour: " + missedBolus02EndHour);
+ log.debug("missedBolus02EndMin: " + missedBolus02EndMin);
+ log.debug("missedBolus03StartHour: " + missedBolus03StartHour);
+ log.debug("missedBolus03StartMin: " + missedBolus03StartMin);
+ log.debug("missedBolus03EndHour: " + missedBolus03EndHour);
+ log.debug("missedBolus03EndMin: " + missedBolus03EndMin);
+ log.debug("missedBolus04StartHour: " + missedBolus04StartHour);
+ log.debug("missedBolus04StartMin: " + missedBolus04StartMin);
+ log.debug("missedBolus04EndHour: " + missedBolus04EndHour);
+ log.debug("missedBolus04EndMin: " + missedBolus04EndMin);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_BOLUS_OPTION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java
new file mode 100644
index 0000000000..b8a86cc078
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_CIR_CF_Array.java
@@ -0,0 +1,145 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_CIR_CF_Array extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_CIR_CF_Array.class);
+
+ public DanaRS_Packet_Bolus_Get_CIR_CF_Array() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_CIR_CF_ARRAY;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int language = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.units = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.morningCIR = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ int cir02 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.afternoonCIR = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ int cir04 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.eveningCIR = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ int cir06 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.nightCIR = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ double cf02, cf04, cf06;
+
+ if (pump.units == DanaRPump.UNITS_MGDL) {
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.morningCF = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ cf02 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.afternoonCF = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ cf04 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.eveningCF = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ cf06 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.nightCF = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ } else {
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.morningCF = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ cf02 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.afternoonCF = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ cf04 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.eveningCF = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ cf06 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.nightCF = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+ }
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Language: " + language);
+ 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);
+ log.debug("cir02: " + cir02);
+ log.debug("cir04: " + cir04);
+ log.debug("cir06: " + cir06);
+ log.debug("cf02: " + cf02);
+ log.debug("cf04: " + cf04);
+ log.debug("cf06: " + cf06);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_CIR_CF_ARRAY";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java
new file mode 100644
index 0000000000..f5acedf3ba
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Calculation_Information.java
@@ -0,0 +1,77 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Calculation_Information extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Calculation_Information.class);
+
+ public DanaRS_Packet_Bolus_Get_Calculation_Information() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_CALCULATION_INFORMATION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double currentBG = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ int carbohydrate = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.currentTarget = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.currentCIR = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.currentCF = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.iob = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.units = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (pump.units == DanaRPump.UNITS_MMOL) {
+ pump.currentCF = pump.currentCF / 100d;
+ pump.currentTarget = pump.currentTarget / 100d;
+ currentBG = currentBG / 100d;
+ }
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ log.debug("Pump units: " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
+ log.debug("Current BG: " + currentBG);
+ log.debug("Carbs: " + carbohydrate);
+ log.debug("Current target: " + pump.currentTarget);
+ log.debug("Current CIR: " + pump.currentCIR);
+ log.debug("Current CF: " + pump.currentCF);
+ log.debug("Pump IOB: " + pump.iob);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_CALCULATION_INFORMATION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java
new file mode 100644
index 0000000000..c581320c54
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.java
@@ -0,0 +1,47 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information.class);
+
+ public DanaRS_Packet_Bolus_Get_Carbohydrate_Calculation_Information() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_CARBOHYDRATE_CALCULATION_INFORMATION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ int carbs = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.currentCIR = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ log.debug("Carbs: " + carbs);
+ log.debug("Current CIR: " + pump.currentCIR);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_CARBOHYDRATE_CALCULATION_INFORMATION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java
new file mode 100644
index 0000000000..bd7a0b9ee6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Dual_Bolus.java
@@ -0,0 +1,55 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Dual_Bolus extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Dual_Bolus.class);
+
+ public DanaRS_Packet_Bolus_Get_Dual_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_DUAL_BOLUS;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.bolusStep = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.maxBolus = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ double bolusIncrement = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ log.debug("Bolus step: " + pump.bolusStep + " U");
+ log.debug("Extended bolus running: " + pump.extendedBolusAbsoluteRate + " U/h");
+ log.debug("Max bolus: " + pump.maxBolus + " U");
+ log.debug("bolusIncrement: " + bolusIncrement + " U");
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_DUAL_BOLUS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java
new file mode 100644
index 0000000000..682d9b14bb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus.java
@@ -0,0 +1,52 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Extended_Bolus extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Extended_Bolus.class);
+
+ public DanaRS_Packet_Bolus_Get_Extended_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.maxBolus = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.bolusStep = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ log.debug("Extended bolus running: " + pump.extendedBolusAbsoluteRate + " U/h");
+ log.debug("Max bolus: " + pump.maxBolus + " U");
+ log.debug("Bolus step: " + pump.bolusStep + " U");
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_EXTENDED_BOLUS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java
new file mode 100644
index 0000000000..b22a9dfb47
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Bolus_State.java
@@ -0,0 +1,62 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Extended_Bolus_State extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Extended_Bolus_State.class);
+
+ public DanaRS_Packet_Bolus_Get_Extended_Bolus_State() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_BOLUS_STATE;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.extendedBolusMinutes = byteArrayToInt(getBytes(data, dataIndex, dataSize)) * 30;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusSoFarInMinutes = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusDeliveredSoFar = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ log.debug("Is extended bolus running: " + pump.isExtendedInProgress);
+ log.debug("Extended bolus running: " + pump.extendedBolusAbsoluteRate + " U/h");
+ log.debug("Extended bolus duration: " + pump.extendedBolusMinutes + " min");
+ log.debug("Extended bolus so far: " + pump.extendedBolusSoFarInMinutes + " min");
+ log.debug("Extended bolus delivered so far: " + pump.extendedBolusDeliveredSoFar + " U");
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_EXTENDED_BOLUS_STATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java
new file mode 100644
index 0000000000..5a7ca55e30
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.java
@@ -0,0 +1,42 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State.class);
+
+ public DanaRS_Packet_Bolus_Get_Extended_Menu_Option_State() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_EXTENDED_MENU_OPTION_STATE;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int extendedMenuOption = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("extendedMenuOption: " + extendedMenuOption);
+ log.debug("Is extended bolus running: " + pump.isExtendedInProgress);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_EXTENDED_MENU_OPTION_STATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java
new file mode 100644
index 0000000000..58fa4674ad
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Initial_Bolus.java
@@ -0,0 +1,46 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Get_Initial_Bolus extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Initial_Bolus.class);
+
+ public DanaRS_Packet_Bolus_Get_Initial_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_BOLUS_RATE;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 2;
+ double initialBolusValue01 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double initialBolusValue02 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double initialBolusValue03 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double initialBolusValue04 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Initial bolus amount 01: " + initialBolusValue01);
+ log.debug("Initial bolus amount 02: " + initialBolusValue02);
+ log.debug("Initial bolus amount 03: " + initialBolusValue03);
+ log.debug("Initial bolus amount 04: " + initialBolusValue04);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_BOLUS_RATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java
new file mode 100644
index 0000000000..922b7886f2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Get_Step_Bolus_Information.java
@@ -0,0 +1,72 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Bolus_Get_Step_Bolus_Information extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Step_Bolus_Information.class);
+
+ public DanaRS_Packet_Bolus_Get_Step_Bolus_Information() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__GET_STEP_BOLUS_INFORMATION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int bolusType = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.initialBolusAmount = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ Date lastBolusTime = new Date(); // it doesn't provide day only hour+min, workaround: expecting today
+ dataIndex += dataSize;
+ dataSize = 1;
+ lastBolusTime.setHours(byteArrayToInt(getBytes(data, dataIndex, dataSize)));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ lastBolusTime.setMinutes(byteArrayToInt(getBytes(data, dataIndex, dataSize)));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.lastBolusAmount = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.maxBolus = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.bolusStep = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ log.debug("BolusType: " + bolusType);
+ log.debug("Initial bolus amount: " + pump.initialBolusAmount + " U");
+ log.debug("Last bolus time: " + lastBolusTime.toLocaleString());
+ log.debug("Last bolus amount: " + pump.lastBolusAmount);
+ log.debug("Max bolus: " + pump.maxBolus + " U");
+ log.debug("Bolus step: " + pump.bolusStep + " U");
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__GET_STEP_BOLUS_INFORMATION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java
new file mode 100644
index 0000000000..e20baeaee6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Bolus_Option.java
@@ -0,0 +1,127 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Set_Bolus_Option extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Bolus_Option.class);
+ private int extendedBolusOptionOnOff;
+
+ private int bolusCalculationOption;
+ private int missedBolusConfig;
+ private int missedBolus01StartHour;
+ private int missedBolus01StartMin;
+ private int missedBolus01EndHour;
+ private int missedBolus01EndMin;
+ private int missedBolus02StartHour;
+ private int missedBolus02StartMin;
+ private int missedBolus02EndHour;
+ private int missedBolus02EndMin;
+ private int missedBolus03StartHour;
+ private int missedBolus03StartMin;
+ private int missedBolus03EndHour;
+ private int missedBolus03EndMin;
+ private int missedBolus04StartHour;
+ private int missedBolus04StartMin;
+ private int missedBolus04EndHour;
+ private int missedBolus04EndMin;
+
+ public DanaRS_Packet_Bolus_Set_Bolus_Option() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_OPTION;
+ }
+
+ public DanaRS_Packet_Bolus_Set_Bolus_Option(
+ int extendedBolusOptionOnOff,
+ int bolusCalculationOption,
+ int missedBolusConfig,
+ int missedBolus01StartHour,
+ int missedBolus01StartMin,
+ int missedBolus01EndHour,
+ int missedBolus01EndMin,
+ int missedBolus02StartHour,
+ int missedBolus02StartMin,
+ int missedBolus02EndHour,
+ int missedBolus02EndMin,
+ int missedBolus03StartHour,
+ int missedBolus03StartMin,
+ int missedBolus03EndHour,
+ int missedBolus03EndMin,
+ int missedBolus04StartHour,
+ int missedBolus04StartMin,
+ int missedBolus04EndHour,
+ int missedBolus04EndMin) {
+ this();
+ this.extendedBolusOptionOnOff = extendedBolusOptionOnOff;
+ this.bolusCalculationOption = bolusCalculationOption;
+ this.missedBolusConfig = missedBolusConfig;
+ this.missedBolus01StartHour = missedBolus01StartHour;
+ this.missedBolus01StartMin = missedBolus01StartMin;
+ this.missedBolus01EndHour = missedBolus01EndHour;
+ this.missedBolus01EndMin = missedBolus01EndMin;
+ this.missedBolus02StartHour = missedBolus02StartHour;
+ this.missedBolus02StartMin = missedBolus02StartMin;
+ this.missedBolus02EndHour = missedBolus02EndHour;
+ this.missedBolus02EndMin = missedBolus02EndMin;
+ this.missedBolus03StartHour = missedBolus03StartHour;
+ this.missedBolus03StartMin = missedBolus03StartMin;
+ this.missedBolus03EndHour = missedBolus03EndHour;
+ this.missedBolus03EndMin = missedBolus03EndMin;
+ this.missedBolus04StartHour = missedBolus04StartHour;
+ this.missedBolus04StartMin = missedBolus04StartMin;
+ this.missedBolus04EndHour = missedBolus04EndHour;
+ this.missedBolus04EndMin = missedBolus04EndMin;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting bolus options");
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[19];
+ request[0] = (byte) (extendedBolusOptionOnOff & 0xff);
+ request[1] = (byte) (bolusCalculationOption & 0xff);
+ request[2] = (byte) (missedBolusConfig & 0xff);
+
+ request[3] = (byte) (missedBolus01StartHour & 0xff);
+ request[4] = (byte) (missedBolus01StartMin & 0xff);
+ request[5] = (byte) (missedBolus01EndHour & 0xff);
+ request[6] = (byte) (missedBolus01EndMin & 0xff);
+
+ request[7] = (byte) (missedBolus02StartHour & 0xff);
+ request[8] = (byte) (missedBolus02StartMin & 0xff);
+ request[9] = (byte) (missedBolus02EndHour & 0xff);
+ request[10] = (byte) (missedBolus02EndMin & 0xff);
+
+ request[11] = (byte) (missedBolus03StartHour & 0xff);
+ request[12] = (byte) (missedBolus03StartMin & 0xff);
+ request[13] = (byte) (missedBolus03EndHour & 0xff);
+ request[14] = (byte) (missedBolus03EndMin & 0xff);
+
+ request[15] = (byte) (missedBolus04StartHour & 0xff);
+ request[16] = (byte) (missedBolus04StartMin & 0xff);
+ request[17] = (byte) (missedBolus04EndHour & 0xff);
+ request[18] = (byte) (missedBolus04EndMin & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_BOLUS_OPTION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java
new file mode 100644
index 0000000000..cf6a459d83
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_CIR_CF_Array.java
@@ -0,0 +1,100 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Set_CIR_CF_Array extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_CIR_CF_Array.class);
+
+ private int cir01;
+ private int cir02;
+ private int cir03;
+ private int cir04;
+ private int cir05;
+ private int cir06;
+ private int cir07;
+ private int cf01;
+ private int cf02;
+ private int cf03;
+ private int cf04;
+ private int cf05;
+ private int cf06;
+ private int cf07;
+
+ public DanaRS_Packet_Bolus_Set_CIR_CF_Array() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_CIR_CF_ARRAY;
+ }
+
+ public DanaRS_Packet_Bolus_Set_CIR_CF_Array(int cir01, int cir02, int cir03, int cir04, int cir05, int cir06, int cir07, int cf01, int cf02, int cf03, int cf04, int cf05, int cf06, int cf07) {
+ this();
+ this.cir01 = cir01;
+ this.cir02 = cir02;
+ this.cir03 = cir03;
+ this.cir04 = cir04;
+ this.cir05 = cir05;
+ this.cir06 = cir06;
+ this.cir07 = cir07;
+ this.cf01 = cf01;
+ this.cf02 = cf02;
+ this.cf03 = cf03;
+ this.cf04 = cf04;
+ this.cf05 = cf05;
+ this.cf06 = cf06;
+ this.cf07 = cf07;
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[28];
+ request[0] = (byte) (cir01 & 0xff);
+ request[1] = (byte) ((cir01 >>> 8) & 0xff);
+ request[2] = (byte) (cir02 & 0xff);
+ request[3] = (byte) ((cir02 >>> 8) & 0xff);
+ request[4] = (byte) (cir03 & 0xff);
+ request[5] = (byte) ((cir03 >>> 8) & 0xff);
+ request[6] = (byte) (cir04 & 0xff);
+ request[7] = (byte) ((cir04 >>> 8) & 0xff);
+ request[8] = (byte) (cir05 & 0xff);
+ request[9] = (byte) ((cir05 >>> 8) & 0xff);
+ request[10] = (byte) (cir06 & 0xff);
+ request[11] = (byte) ((cir06 >>> 8) & 0xff);
+ request[12] = (byte) (cir07 & 0xff);
+ request[13] = (byte) ((cir07 >>> 8) & 0xff);
+ request[14] = (byte) (cf01 & 0xff);
+ request[15] = (byte) ((cf01 >>> 8) & 0xff);
+ request[16] = (byte) (cf02 & 0xff);
+ request[17] = (byte) ((cf02 >>> 8) & 0xff);
+ request[18] = (byte) (cf03 & 0xff);
+ request[19] = (byte) ((cf03 >>> 8) & 0xff);
+ request[20] = (byte) (cf04 & 0xff);
+ request[21] = (byte) ((cf04 >>> 8) & 0xff);
+ request[22] = (byte) (cf05 & 0xff);
+ request[23] = (byte) ((cf05 >>> 8) & 0xff);
+ request[24] = (byte) (cf06 & 0xff);
+ request[25] = (byte) ((cf06 >>> 8) & 0xff);
+ request[26] = (byte) (cf07 & 0xff);
+ request[27] = (byte) ((cf07 >>> 8) & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_CIR_CF_ARRAY";
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java
new file mode 100644
index 0000000000..31c80a702a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Dual_Bolus.java
@@ -0,0 +1,60 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Set_Dual_Bolus extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Dual_Bolus.class);
+
+ private double amount;
+ private double extendedAmount;
+ private int extendedBolusDurationInHalfHours;
+
+ public DanaRS_Packet_Bolus_Set_Dual_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_DUAL_BOLUS;
+ }
+
+ public DanaRS_Packet_Bolus_Set_Dual_Bolus(double amount, double extendedAmount, int extendedBolusDurationInHalfHours) {
+ this();
+ this.amount = amount;
+ this.extendedAmount = extendedAmount;
+ this.extendedBolusDurationInHalfHours = extendedBolusDurationInHalfHours;
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Dual bolus start : " + amount + " U extended: " + extendedAmount + " U halfhours: " + extendedBolusDurationInHalfHours);
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ int stepBolusRate = (int) (amount / 100d);
+ int extendedBolusRate = (int) (extendedAmount / 100d);
+
+ byte[] request = new byte[5];
+ request[0] = (byte) (stepBolusRate & 0xff);
+ request[1] = (byte) ((stepBolusRate >>> 8) & 0xff);
+ request[2] = (byte) (extendedBolusRate & 0xff);
+ request[3] = (byte) ((extendedBolusRate >>> 8) & 0xff);
+ request[4] = (byte) (extendedBolusDurationInHalfHours & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_DUAL_BOLUS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java
new file mode 100644
index 0000000000..d5f61c0946
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus.java
@@ -0,0 +1,56 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Set_Extended_Bolus extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Extended_Bolus.class);
+
+ private double extendedAmount;
+ private int extendedBolusDurationInHalfHours;
+
+ public DanaRS_Packet_Bolus_Set_Extended_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS;
+ }
+
+ public DanaRS_Packet_Bolus_Set_Extended_Bolus(double extendedAmount, int extendedBolusDurationInHalfHours) {
+ this();
+ this.extendedAmount = extendedAmount;
+ this.extendedBolusDurationInHalfHours = extendedBolusDurationInHalfHours;
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Extended bolus start : " + extendedAmount + " U halfhours: " + extendedBolusDurationInHalfHours);
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ int extendedBolusRate = (int) (extendedAmount * 100d);
+
+ byte[] request = new byte[3];
+ request[0] = (byte) (extendedBolusRate & 0xff);
+ request[1] = (byte) ((extendedBolusRate >>> 8) & 0xff);
+ request[2] = (byte) (extendedBolusDurationInHalfHours & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_EXTENDED_BOLUS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java
new file mode 100644
index 0000000000..10aa5f4979
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.java
@@ -0,0 +1,35 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel.class);
+
+ public DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_EXTENDED_BOLUS_CANCEL;
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Cancel extended bolus");
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_EXTENDED_BOLUS_CANCEL";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java
new file mode 100644
index 0000000000..a475e7675d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Initial_Bolus.java
@@ -0,0 +1,60 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Bolus_Set_Initial_Bolus extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Initial_Bolus.class);
+
+ private int bolusRate01;
+ private int bolusRate02;
+ private int bolusRate03;
+ private int bolusRate04;
+
+ public DanaRS_Packet_Bolus_Set_Initial_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_BOLUS_RATE;
+ }
+
+ public DanaRS_Packet_Bolus_Set_Initial_Bolus(double bolusRate01, double bolusRate02, double bolusRate03, double bolusRate04) {
+ this();
+ this.bolusRate01 = (int) (bolusRate01 / 100d);
+ this.bolusRate02 = (int) (bolusRate02 / 100d);
+ this.bolusRate03 = (int) (bolusRate03 / 100d);
+ this.bolusRate04 = (int) (bolusRate04 / 100d);
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[8];
+ request[0] = (byte) (bolusRate01 & 0xff);
+ request[1] = (byte) ((bolusRate01 >>> 8) & 0xff);
+ request[2] = (byte) (bolusRate02 & 0xff);
+ request[3] = (byte) ((bolusRate02 >>> 8) & 0xff);
+ request[4] = (byte) (bolusRate03 & 0xff);
+ request[5] = (byte) ((bolusRate03 >>> 8) & 0xff);
+ request[6] = (byte) (bolusRate04 & 0xff);
+ request[7] = (byte) ((bolusRate04 >>> 8) & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_BOLUS_RATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java
new file mode 100644
index 0000000000..1263aeb629
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Start.java
@@ -0,0 +1,66 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.MainApp;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.utils.HardLimits;
+
+public class DanaRS_Packet_Bolus_Set_Step_Bolus_Start extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Step_Bolus_Start.class);
+
+ private double amount;
+ private int speed;
+
+ public boolean failed;
+
+ public DanaRS_Packet_Bolus_Set_Step_Bolus_Start() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_START;
+ }
+
+ // Speed 0 => 12 sec/U, 1 => 30 sec/U, 2 => 60 sec/U
+ public DanaRS_Packet_Bolus_Set_Step_Bolus_Start(double amount, int speed) {
+ this();
+
+ // HARDCODED LIMIT
+ amount = MainApp.getConfigBuilder().applyBolusConstraints(amount);
+ if (amount < 0) amount = 0d;
+ if (amount > HardLimits.maxBolus()) amount = HardLimits.maxBolus();
+
+ this.amount = amount;
+ this.speed = speed;
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Bolus start : " + amount + " speed: " + speed);
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ int stepBolusRate = (int) (amount * 100);
+ byte[] request = new byte[3];
+ request[0] = (byte) (stepBolusRate & 0xff);
+ request[1] = (byte) ((stepBolusRate >>> 8) & 0xff);
+ request[2] = (byte) (speed & 0xff);
+ return request;
+ }
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ failed = status != 0x00;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_STEP_BOLUS_START";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java
new file mode 100644
index 0000000000..61ddd05c9b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.java
@@ -0,0 +1,61 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.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 com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.db.Treatment;
+import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
+
+public class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.class);
+ private static Treatment t;
+ private static Double amount;
+
+ public static boolean stopped = false;
+ public static boolean forced = false;
+
+ public DanaRS_Packet_Bolus_Set_Step_Bolus_Stop() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_BOLUS__SET_STEP_BOLUS_STOP;
+ }
+
+ public DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(Double amount, Treatment t) {
+ this();
+ this.t = t;
+ this.amount = amount;
+ forced = false;
+ stopped = false;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
+ stopped = true;
+ if (!forced) {
+ t.insulin = amount;
+ bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusprogress_delivered);
+ bolusingEvent.percent = 100;
+ } else {
+ bolusingEvent.status = MainApp.sResources.getString(R.string.overview_bolusprogress_stoped);
+ }
+ MainApp.bus().post(bolusingEvent);
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "BOLUS__SET_STEP_BOLUS_STOP";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java
new file mode 100644
index 0000000000..d30be3abf8
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Keep_Connection.java
@@ -0,0 +1,32 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Etc_Keep_Connection extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Etc_Keep_Connection.class);
+
+ public DanaRS_Packet_Etc_Keep_Connection() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_ETC__KEEP_CONNECTION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "ETC__KEEP_CONNECTION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java
new file mode 100644
index 0000000000..6538b77932
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Etc_Set_History_Save.java
@@ -0,0 +1,71 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Etc_Set_History_Save extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Etc_Set_History_Save.class);
+
+ private int historyType;
+ private int historyYear;
+ private int historyMonth;
+ private int historyDate;
+ private int historyHour;
+ private int historyMinute;
+ private int historySecond;
+ private int historyCode;
+ private int historyValue;
+
+ public DanaRS_Packet_Etc_Set_History_Save() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_ETC__SET_HISTORY_SAVE;
+ }
+
+ public DanaRS_Packet_Etc_Set_History_Save(int historyType, int historyYear, int historyMonth, int historyDate, int historyHour, int historyMinute, int historySecond, int historyCode, int historyValue) {
+ this();
+ this.historyType = historyType;
+ this.historyYear = historyYear;
+ this.historyMonth = historyMonth;
+ this.historyDate = historyDate;
+ this.historyHour = historyHour;
+ this.historyMinute = historyMinute;
+ this.historySecond = historySecond;
+ this.historyCode = historyCode;
+ this.historyValue = historyValue;
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[10];
+ request[0] = (byte) (historyType & 0xff);
+ request[1] = (byte) (historyYear & 0xff);
+ request[2] = (byte) (historyMonth & 0xff);
+ request[3] = (byte) (historyDate & 0xff);
+ request[4] = (byte) (historyHour & 0xff);
+ request[5] = (byte) (historyMinute & 0xff);
+ request[6] = (byte) (historySecond & 0xff);
+ request[7] = (byte) (historyCode & 0xff);
+ request[8] = (byte) (historyValue & 0xff);
+ request[9] = (byte) ((historyValue >>> 8) & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "ETC__SET_HISTORY_SAVE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Delivery_Status.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Delivery_Status.java
new file mode 100644
index 0000000000..d9e2599eb2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Delivery_Status.java
@@ -0,0 +1,32 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_General_Delivery_Status extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Delivery_Status.class);
+
+ public DanaRS_Packet_General_Delivery_Status() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__DELIVERY_STATUS;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Status: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__DELIVERY_STATUS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_More_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_More_Information.java
new file mode 100644
index 0000000000..cd2de4094f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_More_Information.java
@@ -0,0 +1,70 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_General_Get_More_Information extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Get_More_Information.class);
+
+ public DanaRS_Packet_General_Get_More_Information() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__GET_MORE_INFORMATION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 2;
+ pump.iob = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.dailyTotalUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.isExtendedInProgress = byteArrayToInt(getBytes(data, dataIndex, dataSize)) == 0x01;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusRemainingMinutes = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double remainRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ Date lastBolusTime = new Date(); // it doesn't provide day only hour+min, workaround: expecting today
+ dataIndex += dataSize;
+ dataSize = 1;
+ lastBolusTime.setHours(byteArrayToInt(getBytes(data, dataIndex, dataSize)));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ lastBolusTime.setMinutes(byteArrayToInt(getBytes(data, dataIndex, dataSize)));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.lastBolusAmount = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Daily total units: " + pump.dailyTotalUnits + " U");
+ log.debug("Is extended in progress: " + pump.isExtendedInProgress);
+ log.debug("Extended bolus remaining minutes: " + pump.extendedBolusRemainingMinutes);
+ log.debug("Last bolus time: " + lastBolusTime.toLocaleString());
+ log.debug("Last bolus amount: " + pump.lastBolusAmount);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__GET_MORE_INFORMATION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Password.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Password.java
new file mode 100644
index 0000000000..0d250db919
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Password.java
@@ -0,0 +1,36 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_General_Get_Password extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Get_Password.class);
+
+ public DanaRS_Packet_General_Get_Password() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__GET_PASSWORD;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int pass = ((data[DATA_START + 1] & 0x000000FF) << 8) + (data[DATA_START + 0] & 0x000000FF);
+ pass = pass ^ 3463;
+ pump.rs_password = Integer.toHexString(pass);
+ if (Config.logDanaMessageDetail) {
+ log.debug("Pump password: " + pump.rs_password);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__GET_PASSWORD";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java
new file mode 100644
index 0000000000..c38439d7eb
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Pump_Check.java
@@ -0,0 +1,51 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.plugins.Overview.Notification;
+import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
+import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_General_Get_Pump_Check extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Get_Pump_Check.class);
+
+ public DanaRS_Packet_General_Get_Pump_Check() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__GET_PUMP_CHECK;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ pump.model = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.protocol = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.productCode = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ 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));
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__GET_PUMP_CHECK";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java
new file mode 100644
index 0000000000..2cf9b1f124
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Shipping_Information.java
@@ -0,0 +1,46 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_General_Get_Shipping_Information extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Set_Step_Bolus_Stop.class);
+
+ public DanaRS_Packet_General_Get_Shipping_Information() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__GET_SHIPPING_INFORMATION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 10;
+ pump.serialNumber = stringFromBuff(data, dataIndex, dataSize);
+
+ dataIndex += dataSize;
+ dataSize = 3;
+ pump.shippingDate = dateFromBuff(data, dataIndex);
+
+ dataIndex += dataSize;
+ dataSize = 3;
+ pump.shippingCountry = asciiStringFromBuff(data, dataIndex, dataSize);
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Serial number: " + pump.serialNumber);
+ log.debug("Shipping date: " + pump.shippingDate);
+ log.debug("Shipping country: " + pump.shippingCountry);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__GET_SHIPPING_INFORMATION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java
new file mode 100644
index 0000000000..a40d572611
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_Today_Delivery_Total.java
@@ -0,0 +1,47 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_General_Get_Today_Delivery_Total extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Get_Today_Delivery_Total.class);
+
+ public DanaRS_Packet_General_Get_Today_Delivery_Total() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__GET_TODAY_DELIVERY_TOTAL;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 2;
+ pump.dailyTotalUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.dailyTotalBasalUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.dailyTotalBolusUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Daily total: " + pump.dailyTotalUnits + " U");
+ log.debug("Daily total bolus: " + pump.dailyTotalBolusUnits + " U");
+ log.debug("Daily total basal: " + pump.dailyTotalBasalUnits + " U");
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__GET_TODAY_DELIVERY_TOTAL";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java
new file mode 100644
index 0000000000..695e3eace4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Get_User_Time_Change_Flag.java
@@ -0,0 +1,32 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_General_Get_User_Time_Change_Flag extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Get_User_Time_Change_Flag.class);
+
+ public DanaRS_Packet_General_Get_User_Time_Change_Flag() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__GET_USER_TIME_CHANGE_FLAG;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int userTimeChangeFlag = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("UserTimeChangeFlag: " + userTimeChangeFlag);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__GET_USER_TIME_CHANGE_FLAG";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java
new file mode 100644
index 0000000000..d05777d20d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Initial_Screen_Information.java
@@ -0,0 +1,85 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_General_Initial_Screen_Information extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Bolus_Get_Step_Bolus_Information.class);
+
+ public DanaRS_Packet_General_Initial_Screen_Information() {
+ super();
+ type = BleCommandUtil.DANAR_PACKET__TYPE_RESPONSE;
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__INITIAL_SCREEN_INFORMATION;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ pump.pumpSuspended = (status & 0x01) == 0x01;
+ pump.isTempBasalInProgress = (status & 0x10) == 0x10;
+ pump.isExtendedInProgress = (status & 0x04) == 0x04;
+ pump.isDualBolusInProgress = (status & 0x08) == 0x08;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.dailyTotalUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.maxDailyTotalUnits = (int) (byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d);
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.reservoirRemainingUnits = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.currentBasal = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.tempBasalPercent = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.batteryRemaining = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.extendedBolusAbsoluteRate = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.iob = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Pump suspended: " + pump.pumpSuspended);
+ log.debug("Temp basal in progress: " + pump.isTempBasalInProgress);
+ log.debug("Extended in progress: " + pump.isExtendedInProgress);
+ log.debug("Dual in progress: " + pump.isDualBolusInProgress);
+ log.debug("Daily units: " + pump.dailyTotalUnits);
+ log.debug("Max daily units: " + pump.maxDailyTotalUnits);
+ log.debug("Reservoir remaining units: " + pump.reservoirRemainingUnits);
+ log.debug("Battery: " + pump.batteryRemaining);
+ log.debug("Current basal: " + pump.currentBasal);
+ log.debug("Temp basal percent: " + pump.tempBasalPercent);
+ log.debug("Extended absolute rate: " + pump.extendedBolusAbsoluteRate);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__INITIAL_SCREEN_INFORMATION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java
new file mode 100644
index 0000000000..7d9ec07ff1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_History_Upload_Mode.java
@@ -0,0 +1,47 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_General_Set_History_Upload_Mode extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Set_History_Upload_Mode.class);
+
+ private int mode;
+
+ public DanaRS_Packet_General_Set_History_Upload_Mode() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__SET_HISTORY_UPLOAD_MODE;
+ }
+
+ public DanaRS_Packet_General_Set_History_Upload_Mode(int mode) {
+ this();
+ this.mode = mode;
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[1];
+ request[0] = (byte) (mode & 0xff);
+ return request;
+ }
+
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__SET_HISTORY_UPLOAD_MODE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java
new file mode 100644
index 0000000000..9cc6b7b2e0
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.java
@@ -0,0 +1,33 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear.class);
+
+ public DanaRS_Packet_General_Set_User_Time_Change_Flag_Clear() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int status = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + status);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__SET_USER_TIME_CHANGE_FLAG_CLEAR";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_.java
new file mode 100644
index 0000000000..6bae4ab8c1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_.java
@@ -0,0 +1,230 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.db.DanaRHistoryRecord;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
+import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRSyncStatus;
+import info.nightscout.utils.DateUtil;
+
+public abstract class DanaRS_Packet_History_ extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_History_.class);
+
+ private int year = 0;
+ private int month = 0;
+ private int day = 0;
+ private int hour = 0;
+ private int min = 0;
+ private int sec = 0;
+
+ public boolean done;
+ public int totalCount;
+
+ public DanaRS_Packet_History_() {
+ super();
+ done = false;
+ totalCount = 0;
+ }
+
+ public DanaRS_Packet_History_(Date from) {
+ this();
+ GregorianCalendar cal = new GregorianCalendar();
+ if (from.getTime() != 0)
+ cal.setTime(from);
+ else
+ cal.set(2000, 0, 1, 0, 0, 0);
+ year = cal.get(Calendar.YEAR) - 1900 - 100;
+ month = cal.get(Calendar.MONTH) + 1;
+ day = cal.get(Calendar.DAY_OF_MONTH);
+ hour = cal.get(Calendar.HOUR_OF_DAY);
+ min = cal.get(Calendar.MINUTE);
+ sec = cal.get(Calendar.SECOND);
+ log.debug("Loading event history from: " + new Date(cal.getTimeInMillis()).toLocaleString());
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[6];
+ request[0] = (byte) (year & 0xff);
+ request[1] = (byte) (month & 0xff);
+ request[2] = (byte) (day & 0xff);
+ request[3] = (byte) (hour & 0xff);
+ request[4] = (byte) (min & 0xff);
+ request[5] = (byte) (sec & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int error;
+ totalCount = 0;
+ if (data.length == 3) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ done = true;
+ log.debug("History end. Code: " + error + " Success: " + (error == 0x00));
+ } else if (data.length == 5) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ done = true;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ totalCount = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ log.debug("History end. Code: " + error + " Success: " + (error == 0x00) + " Toatal count: " + totalCount);
+ } else {
+ int recordCode = byteArrayToInt(getBytes(data, DATA_START, 1));
+ int historyYear = byteArrayToInt(getBytes(data, DATA_START + 1, 1));
+ int historyMonth = byteArrayToInt(getBytes(data, DATA_START +2 , 1));
+ int historyDay = byteArrayToInt(getBytes(data, DATA_START + 3, 1));
+ int historyHour = byteArrayToInt(getBytes(data, DATA_START + 4, 1));
+ double dailyBasal = (((data[DATA_START + 4] & 0xFF) << 8) + (data[DATA_START + 5] & 0xFF)) * 0.01d;
+ int historyMinute = byteArrayToInt(getBytes(data, DATA_START + 5, 1));
+ int historySecond = byteArrayToInt(getBytes(data, DATA_START + 6, 1));
+ byte paramByte7 = (byte) historySecond;
+ double dailyBolus = (((data[DATA_START + 6] & 0xFF) << 8) + (data[DATA_START + 7] & 0xFF)) * 0.01d;
+
+ Date date = new Date(100 + historyYear, historyMonth - 1, historyDay);
+ Date datetime = new Date(100 + historyYear, historyMonth - 1, historyDay, historyHour, historyMinute);
+ Date datetimewihtsec = new Date(100 + historyYear, historyMonth - 1, historyDay, historyHour, historyMinute, historySecond);
+
+ int historyCode = byteArrayToInt(getBytes(data, DATA_START + 7, 1));
+ byte paramByte8 = (byte) historyCode;
+
+ int value = ((data[DATA_START + 8] & 0xFF) << 8) + (data[DATA_START + 9] & 0xFF);
+
+ log.debug("History packet: " + recordCode + " Date: " + datetimewihtsec.toLocaleString() + " Code: " + historyCode + " Value: " + value);
+
+
+ EventDanaRSyncStatus ev = new EventDanaRSyncStatus();
+ DanaRHistoryRecord danaRHistoryRecord = new DanaRHistoryRecord();
+
+ danaRHistoryRecord.setBytes(data);
+ // danaRHistoryRecord.recordCode is different from DanaR codes
+ // set in switch for every type
+
+ String messageType = "";
+
+ switch (recordCode) {
+ case 0x02:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_BOLUS;
+ danaRHistoryRecord.recordDate = datetime.getTime();
+ switch (0xF0 & paramByte8) {
+ case 0xA0:
+ danaRHistoryRecord.bolusType = "DS";
+ messageType += "DS bolus";
+ break;
+ case 0xC0:
+ danaRHistoryRecord.bolusType = "E";
+ messageType += "E bolus";
+ break;
+ case 0x80:
+ danaRHistoryRecord.bolusType = "S";
+ messageType += "S bolus";
+ break;
+ case 0x90:
+ danaRHistoryRecord.bolusType = "DE";
+ messageType += "DE bolus";
+ break;
+ default:
+ danaRHistoryRecord.bolusType = "None";
+ break;
+ }
+ danaRHistoryRecord.recordDuration = ((int) paramByte8 & 0x0F) * 60 + (int) paramByte7;
+ danaRHistoryRecord.recordValue = value * 0.01;
+ break;
+ case 0x03:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_DAILY;
+ messageType += "dailyinsulin";
+ danaRHistoryRecord.recordDate = date.getTime();
+ danaRHistoryRecord.recordDailyBasal = dailyBasal;
+ danaRHistoryRecord.recordDailyBolus = dailyBolus;
+ break;
+ case 0x04:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_PRIME;
+ messageType += "prime";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ danaRHistoryRecord.recordValue = value * 0.01;
+ break;
+ case 0x05:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_REFILL;
+ messageType += "refill";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ danaRHistoryRecord.recordValue = value * 0.01;
+ break;
+ case 0x0b:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_BASALHOUR;
+ messageType += "basal hour";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ danaRHistoryRecord.recordValue = value * 0.01;
+ break;
+ case 0x99: ///// ????????? don't know the right code
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_TEMP_BASAL;
+ messageType += "tb";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ danaRHistoryRecord.recordValue = value * 0.01;
+ break;
+ case 0x06:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_GLUCOSE;
+ messageType += "glucose";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ danaRHistoryRecord.recordValue = value;
+ break;
+ case 0x07:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_CARBO;
+ messageType += "carbo";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ danaRHistoryRecord.recordValue = value;
+ break;
+ case 0x0a:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_ALARM;
+ messageType += "alarm";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ String strAlarm = "None";
+ switch ((int) paramByte8) {
+ case 67:
+ strAlarm = "Check";
+ break;
+ case 79:
+ strAlarm = "Occlusion";
+ break;
+ case 66:
+ strAlarm = "Low Battery";
+ break;
+ case 83:
+ strAlarm = "Shutdown";
+ break;
+ }
+ danaRHistoryRecord.recordAlarm = strAlarm;
+ danaRHistoryRecord.recordValue = value * 0.01;
+ break;
+ case 0x09:
+ danaRHistoryRecord.recordCode = RecordTypes.RECORD_TYPE_SUSPEND;
+ messageType += "suspend";
+ danaRHistoryRecord.recordDate = datetimewihtsec.getTime();
+ String strRecordValue = "Off";
+ if ((int) paramByte8 == 79)
+ strRecordValue = "On";
+ danaRHistoryRecord.stringRecordValue = strRecordValue;
+ break;
+ }
+
+ MainApp.getDbHelper().createOrUpdate(danaRHistoryRecord);
+
+ ev.message = DateUtil.dateAndTimeString(danaRHistoryRecord.recordDate);
+ ev.message += " " + messageType;
+ MainApp.bus().post(ev);
+
+ }
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Alarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Alarm.java
new file mode 100644
index 0000000000..5fe57fefe4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Alarm.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Alarm extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Alarm() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__ALARM;
+ }
+
+ public DanaRS_Packet_History_Alarm(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__ALARM;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__ALARM";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_All_History.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_All_History.java
new file mode 100644
index 0000000000..a514d4eac7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_All_History.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_All_History extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_All_History() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__ALL_HISTORY;
+ }
+
+ public DanaRS_Packet_History_All_History(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__ALL_HISTORY;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__ALL_HISTORY";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Basal.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Basal.java
new file mode 100644
index 0000000000..4aec1d0352
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Basal.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Basal extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Basal() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BASAL;
+ }
+
+ public DanaRS_Packet_History_Basal(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BASAL;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__BASAL";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Blood_Glucose.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Blood_Glucose.java
new file mode 100644
index 0000000000..22bb3b5c2e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Blood_Glucose.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Blood_Glucose extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Blood_Glucose() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BLOOD_GLUCOSE;
+ }
+
+ public DanaRS_Packet_History_Blood_Glucose(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BLOOD_GLUCOSE;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__BLOOD_GLUCOSE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Bolus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Bolus.java
new file mode 100644
index 0000000000..7451f921be
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Bolus.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Bolus extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Bolus() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BOLUS;
+ }
+
+ public DanaRS_Packet_History_Bolus(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BOLUS;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__BOLUS";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Carbohydrate.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Carbohydrate.java
new file mode 100644
index 0000000000..df2f5c762d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Carbohydrate.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Carbohydrate extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Carbohydrate() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__CARBOHYDRATE;
+ }
+
+ public DanaRS_Packet_History_Carbohydrate(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__CARBOHYDRATE;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__CARBOHYDRATE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Daily.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Daily.java
new file mode 100644
index 0000000000..b55754ba2f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Daily.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Daily extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Daily() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__DAILY;
+ }
+
+ public DanaRS_Packet_History_Daily(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__DAILY;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__DAILY";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Prime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Prime.java
new file mode 100644
index 0000000000..b5dbf7ff93
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Prime.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Prime extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Prime() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__PRIME;
+ }
+
+ public DanaRS_Packet_History_Prime(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__PRIME;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__PRIME";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Refill.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Refill.java
new file mode 100644
index 0000000000..66094e3fb6
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Refill.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Refill extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Refill() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__REFILL;
+ }
+
+ public DanaRS_Packet_History_Refill(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__REFILL;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__REFILL";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Suspend.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Suspend.java
new file mode 100644
index 0000000000..20f1c3d6ff
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Suspend.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Suspend extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Suspend() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__SUSPEND;
+ }
+
+ public DanaRS_Packet_History_Suspend(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__SUSPEND;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__SUSPEND";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Temporary.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Temporary.java
new file mode 100644
index 0000000000..7d63e1bfff
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_History_Temporary.java
@@ -0,0 +1,23 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import java.util.Date;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_History_Temporary extends DanaRS_Packet_History_ {
+
+ public DanaRS_Packet_History_Temporary() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__TEMPORARY;
+ }
+
+ public DanaRS_Packet_History_Temporary(Date from) {
+ super(from);
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__TEMPORARY;
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__TEMPORARY";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Alarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Alarm.java
new file mode 100644
index 0000000000..88edd13a63
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Alarm.java
@@ -0,0 +1,88 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.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 com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.utils.NSUpload;
+
+public class DanaRS_Packet_Notify_Alarm extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Notify_Alarm.class);
+
+ private int alarmCode;
+
+ public DanaRS_Packet_Notify_Alarm() {
+ super();
+ type = BleCommandUtil.DANAR_PACKET__TYPE_NOTIFY;
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_NOTIFY__ALARM;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ alarmCode = byteArrayToInt(getBytes(data, DATA_START, 1));
+ String errorString = "";
+
+ switch (alarmCode) {
+ case 0x01:
+ // Battery 0% Alarm
+ errorString = MainApp.sResources.getString(R.string.batterydischarged);
+ break;
+ case 0x02:
+ // Pump Error
+ errorString = MainApp.sResources.getString(R.string.pumperror) + " " + alarmCode;
+ break;
+ case 0x03:
+ // Occlusion
+ errorString = MainApp.sResources.getString(R.string.occlusion);
+ break;
+ case 0x04:
+ // LOW BATTERY
+ errorString = MainApp.sResources.getString(R.string.lowbattery);
+ break;
+ case 0x05:
+ // Shutdown
+ errorString = MainApp.sResources.getString(R.string.lowbattery);
+ break;
+ case 0x06:
+ // Basal Compare
+ errorString = "BasalCompare ????";
+ break;
+ case 0x09:
+ // Empty Reservoir
+ errorString = MainApp.sResources.getString(R.string.emptyreservoir);
+ break;
+
+ // BT
+ case 0x07:
+ case 0xFF:
+ // Blood sugar measurement alert
+ errorString = MainApp.sResources.getString(R.string.bloodsugarmeasurementalert);
+ break;
+
+ case 0x08:
+ case 0xFE:
+ // Remaining insulin level
+ errorString = MainApp.sResources.getString(R.string.remaininsulinalert);
+ break;
+
+ case 0xFD:
+ // Blood sugar check miss alarm
+ errorString = "Blood sugar check miss alarm ???";
+ break;
+ }
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Error detected: " + errorString);
+ NSUpload.uploadError(errorString);
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "NOTIFY__ALARM";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java
new file mode 100644
index 0000000000..0139b12197
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Complete.java
@@ -0,0 +1,57 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.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 com.cozmo.danar.util.BleCommandUtil;
+
+import info.nightscout.androidaps.db.Treatment;
+import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
+
+public class DanaRS_Packet_Notify_Delivery_Complete extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Notify_Delivery_Complete.class);
+
+ private static Treatment t;
+ private static double amount;
+ public static boolean done;
+
+ public DanaRS_Packet_Notify_Delivery_Complete() {
+ super();
+ type = BleCommandUtil.DANAR_PACKET__TYPE_NOTIFY;
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_COMPLETE;
+ }
+
+ public DanaRS_Packet_Notify_Delivery_Complete(double amount, Treatment t) {
+ this();
+ this.amount = amount;
+ this.t = t;
+ done = false;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ double deliveredInsulin = byteArrayToInt(getBytes(data, DATA_START, 2)) / 100d;
+
+ if (t != null) {
+ t.insulin = deliveredInsulin;
+ EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
+ bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), deliveredInsulin);
+ bolusingEvent.t = t;
+ bolusingEvent.percent = Math.min((int) (deliveredInsulin / amount * 100), 100);
+ done = true;
+ MainApp.bus().post(bolusingEvent);
+ }
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Delivered insulin: " + deliveredInsulin);
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "NOTIFY__DELIVERY_COMPLETE";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java
new file mode 100644
index 0000000000..26c12c27af
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Delivery_Rate_Display.java
@@ -0,0 +1,56 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.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 com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.db.Treatment;
+import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
+
+public class DanaRS_Packet_Notify_Delivery_Rate_Display extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Notify_Delivery_Rate_Display.class);
+
+ private static Treatment t;
+ private static double amount;
+
+ public static long lastReceive = 0;
+
+ public DanaRS_Packet_Notify_Delivery_Rate_Display() {
+ super();
+ type = BleCommandUtil.DANAR_PACKET__TYPE_NOTIFY;
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_NOTIFY__DELIVERY_RATE_DISPLAY;
+ }
+
+ public DanaRS_Packet_Notify_Delivery_Rate_Display(double amount, Treatment t) {
+ this();
+ this.amount = amount;
+ this.t = t;
+ lastReceive = System.currentTimeMillis();
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ double deliveredInsulin = byteArrayToInt(getBytes(data, DATA_START, 2)) / 100d;
+
+ if (t != null) {
+ lastReceive = System.currentTimeMillis();
+ t.insulin = deliveredInsulin;
+ EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
+ bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), deliveredInsulin);
+ bolusingEvent.t = t;
+ bolusingEvent.percent = Math.min((int) (deliveredInsulin / amount * 100), 100);
+ MainApp.bus().post(bolusingEvent);
+ }
+
+ if (Config.logDanaMessageDetail)
+ log.debug("Delivered insulin so far: " + deliveredInsulin);
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "NOTIFY__DELIVERY_RATE_DISPLAY";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java
new file mode 100644
index 0000000000..3af0c209b5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Notify_Missed_Bolus_Alarm.java
@@ -0,0 +1,54 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Notify_Missed_Bolus_Alarm extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Notify_Missed_Bolus_Alarm.class);
+
+ public DanaRS_Packet_Notify_Missed_Bolus_Alarm() {
+ super();
+ type = BleCommandUtil.DANAR_PACKET__TYPE_NOTIFY;
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_NOTIFY__MISSED_BOLUS_ALARM;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int startHour;
+ int startMin;
+ int endHour;
+ int endMin;
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ startHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ startMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ endHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ endMin = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Start hour: " + startHour);
+ log.debug("Start min: " + startMin);
+ log.debug("End hour: " + endHour);
+ log.debug("End min: " + endMin);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "NOTIFY__MISSED_BOLUS_ALARM";
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java
new file mode 100644
index 0000000000..4bfebb5211
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java
@@ -0,0 +1,61 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Option_Get_Pump_Time extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Option_Get_Pump_Time.class);
+
+ public DanaRS_Packet_Option_Get_Pump_Time() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_OPTION__GET_PUMP_TIME;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Requesting pump time");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ int year = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int month = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int day = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int hour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int min = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int sec = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ Date time = new Date(100 + year, month - 1, day, hour, min, sec);
+ DanaRPump.getInstance().pumpTime = time;
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("Pump time " + time.toLocaleString());
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "OPTION__GET_PUMP_TIME";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_User_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_User_Option.java
new file mode 100644
index 0000000000..b4df373f9c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Get_User_Option.java
@@ -0,0 +1,114 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Option_Get_User_Option extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Option_Get_User_Option.class);
+
+
+ public DanaRS_Packet_Option_Get_User_Option() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_OPTION__GET_USER_OPTION;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Requesting user settings");
+ }
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ pump.timeDisplayType = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.buttonScrollOnOff = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.beepAndAlarm = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.lcdOnTimeSec = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.backlightOnTimeSec = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.selectedLanguage = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.units = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.shutdownHour = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ pump.lowReservoirRate = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.cannulaVolume = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ pump.refillAmount = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int selectableLanguage1 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int selectableLanguage2 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int selectableLanguage3 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int selectableLanguage4 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ dataIndex += dataSize;
+ dataSize = 1;
+ int selectableLanguage5 = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+
+ if (Config.logDanaMessageDetail) {
+ log.debug("timeDisplayType: " + pump.timeDisplayType);
+ log.debug("buttonScrollOnOff: " + pump.buttonScrollOnOff);
+ log.debug("beepAndAlarm: " + pump.beepAndAlarm);
+ log.debug("lcdOnTimeSec: " + pump.lcdOnTimeSec);
+ log.debug("backlightOnTimeSec: " + pump.backlightOnTimeSec);
+ log.debug("selectedLanguage: " + pump.selectedLanguage);
+ log.debug("Pump units: " + (pump.units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
+ log.debug("shutdownHour: " + pump.shutdownHour);
+ log.debug("lowReservoirRate: " + pump.lowReservoirRate);
+ log.debug("refillAmount: " + pump.refillAmount);
+ log.debug("selectableLanguage1: " + selectableLanguage1);
+ log.debug("selectableLanguage2: " + selectableLanguage2);
+ log.debug("selectableLanguage3: " + selectableLanguage3);
+ log.debug("selectableLanguage4: " + selectableLanguage4);
+ log.debug("selectableLanguage5: " + selectableLanguage5);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "OPTION__GET_USER_OPTION";
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java
new file mode 100644
index 0000000000..e93e18796d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_Pump_Time.java
@@ -0,0 +1,56 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Option_Set_Pump_Time extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Option_Set_Pump_Time.class);
+ private Date date;
+ public int error;
+
+ public DanaRS_Packet_Option_Set_Pump_Time() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_OPTION__SET_PUMP_TIME;
+ }
+
+ public DanaRS_Packet_Option_Set_Pump_Time(Date date) {
+ this();
+ this.date = date;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting pump time " + date.toLocaleString());
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ byte[] request = new byte[6];
+ request[0] = (byte) ((date.getYear() - 100) & 0xff);
+ request[1] = (byte) ((date.getMonth() + 1) & 0xff);
+ request[2] = (byte) (date.getDate() & 0xff);
+ request[3] = (byte) (date.getHours() & 0xff);
+ request[4] = (byte) (date.getMinutes() & 0xff);
+ request[5] = (byte) (date.getSeconds() & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "OPTION__SET_PUMP_TIME";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java
new file mode 100644
index 0000000000..49c6d35708
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Option_Set_User_Option.java
@@ -0,0 +1,58 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import com.cozmo.danar.util.BleCommandUtil;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+
+public class DanaRS_Packet_Option_Set_User_Option extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Option_Set_User_Option.class);
+
+ private int error;
+
+ public DanaRS_Packet_Option_Set_User_Option() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_OPTION__SET_USER_OPTION;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Setting user settings");
+ }
+ }
+
+ @Override
+ public byte[] getRequestParams() {
+ DanaRPump pump = DanaRPump.getInstance();
+
+ byte[] request = new byte[13];
+ request[0] = (byte) (pump.timeDisplayType & 0xff);
+ request[1] = (byte) (pump.buttonScrollOnOff & 0xff);
+ request[2] = (byte) (pump.beepAndAlarm & 0xff);
+ request[3] = (byte) (pump.lcdOnTimeSec & 0xff);
+ request[4] = (byte) (pump.backlightOnTimeSec & 0xff);
+ request[5] = (byte) (pump.selectedLanguage & 0xff);
+ request[6] = (byte) (pump.units & 0xff);
+ request[7] = (byte) (pump.shutdownHour & 0xff);
+ request[8] = (byte) (pump.lowReservoirRate & 0xff);
+ request[9] = (byte) (pump.cannulaVolume & 0xff);
+ request[10] = (byte) ((pump.cannulaVolume >>> 8) & 0xff);
+ request[11] = (byte) (pump.refillAmount & 0xff);
+ request[12] = (byte) ((pump.refillAmount >>> 8) & 0xff);
+ return request;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 1;
+ error = byteArrayToInt(getBytes(data, dataIndex, dataSize));
+ if (Config.logDanaMessageDetail) {
+ log.debug("Result: " + error);
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "OPTION__SET_USER_OPTION";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java
new file mode 100644
index 0000000000..e8440b12d2
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/comm/DanaRS_Packet_Review_Bolus_Avg.java
@@ -0,0 +1,52 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.comm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+public class DanaRS_Packet_Review_Bolus_Avg extends DanaRS_Packet {
+ private static Logger log = LoggerFactory.getLogger(DanaRS_Packet_Review_Bolus_Avg.class);
+
+ public DanaRS_Packet_Review_Bolus_Avg() {
+ super();
+ opCode = BleCommandUtil.DANAR_PACKET__OPCODE_REVIEW__BOLUS_AVG;
+ }
+
+ @Override
+ public void handleMessage(byte[] data) {
+ int dataIndex = DATA_START;
+ int dataSize = 2;
+ double bolusAvg03 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double bolusAvg07 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double bolusAvg14 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double bolusAvg21 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+
+ dataIndex += dataSize;
+ dataSize = 2;
+ double bolusAvg28 = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100d;
+ if (Config.logDanaMessageDetail) {
+ log.debug("Bolus average 3d: " + bolusAvg03 + " U");
+ log.debug("Bolus average 7d: " + bolusAvg07 + " U");
+ log.debug("Bolus average 14d: " + bolusAvg14 + " U");
+ log.debug("Bolus average 21d: " + bolusAvg21 + " U");
+ log.debug("Bolus average 28d: " + bolusAvg28 + " U");
+ }
+ }
+
+ @Override
+ public String getFriendlyName() {
+ return "REVIEW__BOLUS_AVG";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSDeviceChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSDeviceChange.java
new file mode 100644
index 0000000000..8ae02d47ff
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSDeviceChange.java
@@ -0,0 +1,8 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.events;
+
+/**
+ * Created by mike on 05.09.2017.
+ */
+
+public class EventDanaRSDeviceChange {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPacket.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPacket.java
new file mode 100644
index 0000000000..5815399194
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPacket.java
@@ -0,0 +1,15 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.events;
+
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet;
+
+/**
+ * Created by mike on 01.09.2017.
+ */
+
+public class EventDanaRSPacket {
+ public EventDanaRSPacket(DanaRS_Packet data) {
+ this.data = data;
+ }
+
+ public DanaRS_Packet data;
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPairingSuccess.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPairingSuccess.java
new file mode 100644
index 0000000000..d50091de55
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/events/EventDanaRSPairingSuccess.java
@@ -0,0 +1,8 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.events;
+
+/**
+ * Created by mike on 01.09.2017.
+ */
+
+public class EventDanaRSPairingSuccess {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
new file mode 100644
index 0000000000..dde50a93e1
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java
@@ -0,0 +1,706 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.services;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.SystemClock;
+
+import com.cozmo.danar.util.BleCommandUtil;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventPumpStatusChanged;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingHelperActivity;
+import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingProgressDialog;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRSMessageHashTable;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet;
+import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPacket;
+import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPairingSuccess;
+import info.nightscout.utils.SP;
+
+/**
+ * Created by mike on 23.09.2017.
+ */
+
+public class BLEComm {
+ private static Logger log = LoggerFactory.getLogger(BLEComm.class);
+
+ private static final long WRITE_DELAY_MILLIS = 50;
+
+ public static String UART_READ_UUID = "0000fff1-0000-1000-8000-00805f9b34fb";
+ public static String UART_WRITE_UUID = "0000fff2-0000-1000-8000-00805f9b34fb";
+
+ private byte PACKET_START_BYTE = (byte) 0xA5;
+ private byte PACKET_END_BYTE = (byte) 0x5A;
+ private static BLEComm instance = null;
+
+ public static BLEComm getInstance(DanaRSService service) {
+ if (instance == null)
+ instance = new BLEComm(service);
+ return instance;
+ }
+
+ private Object mConfirmConnect = null;
+
+ private final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
+ private ScheduledFuture> scheduledDisconnection = null;
+
+ private DanaRS_Packet processsedMessage = null;
+ private ArrayList mSendQueue = new ArrayList<>();
+
+ // Variables for connection progress (elapsed time)
+ private Handler sHandler;
+ private HandlerThread sHandlerThread;
+ private long connectionStartTime = 0;
+ private final Runnable updateProgress = new Runnable() {
+ @Override
+ public void run() {
+ long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000;
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed));
+ sHandler.postDelayed(updateProgress, 1000);
+ }
+ };
+
+ private BluetoothManager mBluetoothManager = null;
+ private BluetoothAdapter mBluetoothAdapter = null;
+ private BluetoothDevice mBluetoothDevice = null;
+ private String mBluetoothDeviceAddress = null;
+ private String mBluetoothDeviceName = null;
+ private BluetoothGatt mBluetoothGatt = null;
+
+ protected boolean isConnected = false;
+ protected boolean isConnecting = false;
+
+ private BluetoothGattCharacteristic UART_Read;
+ private BluetoothGattCharacteristic UART_Write;
+
+ private DanaRSService service;
+
+ BLEComm(DanaRSService service) {
+ this.service = service;
+ initialize();
+
+ if (sHandlerThread == null) {
+ sHandlerThread = new HandlerThread(PairingProgressDialog.class.getSimpleName());
+ sHandlerThread.start();
+ sHandler = new Handler(sHandlerThread.getLooper());
+ }
+ }
+
+ private boolean initialize() {
+ log.debug("Initializing BLEComm.");
+
+ if (mBluetoothManager == null) {
+ mBluetoothManager = ((BluetoothManager) MainApp.instance().getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE));
+ if (mBluetoothManager == null) {
+ log.debug("Unable to initialize BluetoothManager.");
+ return false;
+ }
+ }
+
+ mBluetoothAdapter = mBluetoothManager.getAdapter();
+ if (mBluetoothAdapter == null) {
+ log.debug("Unable to obtain a BluetoothAdapter.");
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean isConnected() {
+ return isConnected;
+ }
+
+ public boolean isConnecting() {
+ return isConnecting;
+ }
+
+ public boolean connect(String from, String address, Object confirmConnect) {
+ mConfirmConnect = confirmConnect;
+ BluetoothManager tBluetoothManager = ((BluetoothManager) MainApp.instance().getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE));
+ if (tBluetoothManager == null) {
+ return false;
+ }
+
+ BluetoothAdapter tBluetoothAdapter = tBluetoothManager.getAdapter();
+ if (tBluetoothAdapter == null) {
+ return false;
+ }
+
+ if (mBluetoothAdapter == null) {
+ if (!initialize()) {
+ return false;
+ }
+ }
+
+ if (address == null) {
+ log.debug("unspecified address.");
+ return false;
+ }
+
+ connectionStartTime = System.currentTimeMillis();
+
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING));
+ isConnecting = true;
+
+ // Following should be removed later because we close Gatt on disconnect and this should never happen
+ if ((mBluetoothDeviceAddress != null) && (address.equals(mBluetoothDeviceAddress)) && (mBluetoothGatt != null)) {
+ log.debug("Trying to use an existing mBluetoothGatt for connection.");
+ sHandler.post(updateProgress);
+ if (mBluetoothGatt.connect()) {
+ setCharacteristicNotification(getUARTReadBTGattChar(), true);
+ return true;
+ }
+ sHandler.removeCallbacks(updateProgress);
+ return false;
+ }
+ // end
+
+ BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+ if (device == null) {
+ log.debug("Device not found. Unable to connect.");
+ return false;
+ }
+
+ sHandler.post(updateProgress);
+ mBluetoothGatt = device.connectGatt(service.getApplicationContext(), false, mGattCallback);
+ setCharacteristicNotification(getUARTReadBTGattChar(), true);
+ log.debug("Trying to create a new connection.");
+ mBluetoothDevice = device;
+ mBluetoothDeviceAddress = address;
+ mBluetoothDeviceName = device.getName();
+ return true;
+ }
+
+ public void stopConnecting() {
+ isConnecting = false;
+ sHandler.removeCallbacks(updateProgress); // just to be sure
+ }
+
+ public void disconnect(String from) {
+ log.debug("disconnect from: " + from);
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ return;
+ }
+ setCharacteristicNotification(getUARTReadBTGattChar(), false);
+ mBluetoothGatt.disconnect();
+ isConnected = false;
+ }
+
+ public void close() {
+ log.debug("BluetoothAdapter close");
+ if (mBluetoothGatt == null) {
+ return;
+ }
+ mBluetoothGatt.close();
+ mBluetoothGatt = null;
+ }
+
+ public BluetoothDevice getConnectDevice() {
+ return mBluetoothDevice;
+ }
+
+ public String getConnectDeviceAddress() {
+ return mBluetoothDeviceAddress;
+ }
+
+ public String getConnectDeviceName() {
+ return mBluetoothDeviceName;
+ }
+
+ private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ log.debug("onConnectionStateChange");
+
+ if (newState == BluetoothProfile.STATE_CONNECTED) {
+ mBluetoothGatt.discoverServices();
+ } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
+ close();
+ isConnected = false;
+ sHandler.removeCallbacks(updateProgress); // just to be sure
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED));
+ log.debug("Device was disconnected " + gatt.getDevice().getName());//Device was disconnected
+ }
+ }
+
+ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+ log.debug("onServicesDiscovered");
+
+ isConnecting = false;
+
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ findCharacteristic();
+ }
+ // stop sending connection progress
+ sHandler.removeCallbacks(updateProgress);
+ SendPumpCheck();
+ // 1st message sent to pump after connect
+ }
+
+ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ log.debug("onCharacteristicRead" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
+ addToReadBuffer(characteristic.getValue());
+ readDataParsing();
+ }
+
+ public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
+ log.debug("onCharacteristicChanged" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
+ addToReadBuffer(characteristic.getValue());
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ readDataParsing();
+ }
+ }).start();
+ }
+
+ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ log.debug("onCharacteristicWrite" + (characteristic != null ? ":" + DanaRS_Packet.toHexString(characteristic.getValue()) : ""));
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mSendQueue) {
+ // after message sent, check if there is the rest of the message waiting and send it
+ if (mSendQueue.size() > 0) {
+ byte[] bytes = mSendQueue.get(0);
+ mSendQueue.remove(0);
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
+ }
+ }
+ }
+ }).start();
+ }
+ };
+
+ public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
+ log.debug("setCharacteristicNotification");
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ log.debug("BluetoothAdapter not initialized_ERROR");
+ return;
+ }
+ mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
+ }
+
+ public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
+ log.debug("readCharacteristic");
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ log.debug("BluetoothAdapter not initialized_ERROR");
+ return;
+ }
+ mBluetoothGatt.readCharacteristic(characteristic);
+ }
+
+ public void writeCharacteristic_NO_RESPONSE(final BluetoothGattCharacteristic characteristic, final byte[] data) {
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ log.debug("BluetoothAdapter not initialized_ERROR");
+ return;
+ }
+
+ new Thread(new Runnable() {
+ public void run() {
+ SystemClock.sleep(WRITE_DELAY_MILLIS);
+ characteristic.setValue(data);
+ characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
+ log.debug("writeCharacteristic:" + DanaRS_Packet.toHexString(data));
+ mBluetoothGatt.writeCharacteristic(characteristic);
+ }
+ }).start();
+ }
+
+ public BluetoothGattCharacteristic getUARTReadBTGattChar() {
+ if (UART_Read == null) {
+ UART_Read = new BluetoothGattCharacteristic(UUID.fromString(UART_READ_UUID), BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, 0);
+ }
+ return UART_Read;
+ }
+
+ public BluetoothGattCharacteristic getUARTWriteBTGattChar() {
+ if (UART_Write == null) {
+ UART_Write = new BluetoothGattCharacteristic(UUID.fromString(UART_WRITE_UUID), BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, 0);
+ }
+ return UART_Write;
+ }
+
+ public List getSupportedGattServices() {
+ log.debug("getSupportedGattServices");
+ if ((mBluetoothAdapter == null) || (mBluetoothGatt == null)) {
+ log.debug("BluetoothAdapter not initialized_ERROR");
+ return null;
+ }
+
+ return mBluetoothGatt.getServices();
+ }
+
+ private void findCharacteristic() {
+ List gattServices = getSupportedGattServices();
+
+ if (gattServices == null) {
+ return;
+ }
+ String uuid = null;
+
+ for (BluetoothGattService gattService : gattServices) {
+ List gattCharacteristics = gattService.getCharacteristics();
+ for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
+ uuid = gattCharacteristic.getUuid().toString();
+ if (UART_READ_UUID.equals(uuid)) {
+ UART_Read = gattCharacteristic;
+ setCharacteristicNotification(UART_Read, true);
+ }
+ if (UART_WRITE_UUID.equals(uuid)) {
+ UART_Write = gattCharacteristic;
+ }
+ }
+ }
+ }
+
+ private byte[] readBuffer = new byte[1024];
+ private int bufferLength = 0;
+
+ private void addToReadBuffer(byte[] buffer) {
+ //log.debug("addToReadBuffer " + DanaRS_Packet.toHexString(buffer));
+ if (buffer == null || buffer.length == 0) {
+ return;
+ }
+ synchronized (readBuffer) {
+ // Append incomming data to input buffer
+ System.arraycopy(buffer, 0, readBuffer, bufferLength, buffer.length);
+ bufferLength += buffer.length;
+ }
+ }
+
+ private void readDataParsing() {
+ boolean startSignatureFound = false, packetIsValid = false;
+ boolean isProcessing;
+
+ isProcessing = true;
+
+ while (isProcessing) {
+ int length = 0;
+ byte[] inputBuffer = null;
+ synchronized (readBuffer) {
+ // Find packet start [A5 A5]
+ if (bufferLength >= 6) {
+ for (int idxStartByte = 0; idxStartByte < bufferLength - 2; idxStartByte++) {
+ if ((readBuffer[idxStartByte] == PACKET_START_BYTE) && (readBuffer[idxStartByte + 1] == PACKET_START_BYTE)) {
+ if (idxStartByte > 0) {
+ // if buffer doesn't start with signature remove the leading trash
+ log.debug("Shifting the input buffer by " + idxStartByte + " bytes");
+ System.arraycopy(readBuffer, idxStartByte, readBuffer, 0, bufferLength - idxStartByte);
+ bufferLength -= idxStartByte;
+ }
+ startSignatureFound = true;
+ break;
+ }
+ }
+ }
+ // A5 A5 LEN TYPE CODE PARAMS CHECKSUM1 CHECKSUM2 5A 5A
+ // ^---- LEN -----^
+ // total packet length 2 + 1 + readBuffer[2] + 2 + 2
+ if (startSignatureFound) {
+ length = readBuffer[2];
+ // test if there is enough data loaded
+ if (length + 7 > bufferLength)
+ return;
+ // Verify packed end [5A 5A]
+ if ((readBuffer[length + 5] == PACKET_END_BYTE) && (readBuffer[length + 6] == PACKET_END_BYTE)) {
+ packetIsValid = true;
+ }
+ }
+ if (packetIsValid) {
+ inputBuffer = new byte[length + 7];
+ // copy packet to input buffer
+ System.arraycopy(readBuffer, 0, inputBuffer, 0, length + 7);
+ // Cut off the message from readBuffer
+ try {
+ System.arraycopy(readBuffer, length + 7, readBuffer, 0, bufferLength - (length + 7));
+ } catch (Exception e) {
+ log.debug("length: " + length + "bufferLength: " + bufferLength);
+ throw e;
+ }
+ bufferLength -= (length + 7);
+ // now we have encrypted packet in inputBuffer
+ }
+ }
+ if (packetIsValid) {
+ try {
+ // decrypt the packet
+ inputBuffer = BleCommandUtil.getInstance().getDecryptedPacket(inputBuffer);
+
+ if (inputBuffer == null) {
+ log.debug("Null decryptedInputBuffer");
+ return;
+ }
+
+ switch (inputBuffer[0]) {
+ // initial handshake packet
+ case (byte) BleCommandUtil.DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE:
+ switch (inputBuffer[1]) {
+ // 1st packet
+ case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK:
+ if (inputBuffer.length == 4 && inputBuffer[2] == 'O' && inputBuffer[3] == 'K') {
+ log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (OK)" + " " + DanaRS_Packet.toHexString(inputBuffer));
+ // Grab pairing key from preferences if exists
+ String pairingKey = SP.getString(MainApp.sResources.getString(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, null);
+ log.debug("Using stored pairing key: " + pairingKey);
+ if (pairingKey != null) {
+ byte[] encodedPairingKey = DanaRS_Packet.hexToBytes(pairingKey);
+ byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY, encodedPairingKey, null);
+ log.debug(">>>>> " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(bytes));
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
+ } else {
+ // Stored pairing key does not exists, request pairing
+ SendPairingRequest();
+ }
+
+ } else if (inputBuffer.length == 6 && inputBuffer[2] == 'B' && inputBuffer[3] == 'U' && inputBuffer[4] == 'S' && inputBuffer[5] == 'Y') {
+ log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(inputBuffer));
+ mSendQueue.clear();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.sResources.getString(R.string.pumpbusy)));
+ } else {
+ log.debug("<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(inputBuffer));
+ mSendQueue.clear();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED, MainApp.sResources.getString(R.string.connectionerror)));
+ }
+ break;
+ // 2nd packet, pairing key
+ case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY:
+ log.debug("<<<<< " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(inputBuffer));
+ if (inputBuffer[2] == (byte) 0x00) {
+ // Paring is not requested, sending time info
+ SendTimeInfo();
+ } else {
+ // Pairing on pump is requested
+ SendPairingRequest();
+ }
+ break;
+ case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST:
+ log.debug("<<<<< " + "ENCRYPTION__PASSKEY_REQUEST " + DanaRS_Packet.toHexString(inputBuffer));
+ if (inputBuffer[2] != (byte) 0x00) {
+ disconnect("passkey request failed");
+ }
+ break;
+ // Paring response, OK button on pump pressed
+ case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN:
+ log.debug("<<<<< " + "ENCRYPTION__PASSKEY_RETURN " + DanaRS_Packet.toHexString(inputBuffer));
+ // Paring is successfull, sending time info
+ MainApp.bus().post(new EventDanaRSPairingSuccess());
+ SendTimeInfo();
+ byte[] pairingKey = {inputBuffer[2], inputBuffer[3]};
+ // store pairing key to preferences
+ SP.putString(MainApp.sResources.getString(R.string.key_danars_pairingkey) + DanaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey));
+ log.debug("Got pairing key: " + DanaRS_Packet.bytesToHex(pairingKey));
+ break;
+ // time and user password information. last packet in handshake
+ case (byte) BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION:
+ log.debug("<<<<< " + "ENCRYPTION__TIME_INFORMATION " + /*message.getMessageName() + " " + */ DanaRS_Packet.toHexString(inputBuffer));
+ int size = inputBuffer.length;
+ int pass = ((inputBuffer[size - 1] & 0x000000FF) << 8) + ((inputBuffer[size - 2] & 0x000000FF));
+ pass = pass ^ 3463;
+ DanaRPump.getInstance().rs_password = Integer.toHexString(pass);
+ log.debug("Pump user password: " + Integer.toHexString(pass));
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTED));
+
+ isConnected = true;
+ isConnecting = false;
+ service.getPumpStatus();
+ scheduleDisconnection();
+ if (mConfirmConnect != null) {
+ synchronized (mConfirmConnect) {
+ mConfirmConnect.notify();
+ mConfirmConnect = null;
+ }
+ }
+ break;
+ }
+ break;
+ // common data packet
+ default:
+ DanaRS_Packet message;
+ // Retrieve message code from received buffer and last message sent
+ int originalCommand = processsedMessage != null ? processsedMessage.getCommand() : 0xFFFF;
+ int receivedCommand = DanaRS_Packet.getCommand(inputBuffer);
+ if (originalCommand == receivedCommand) {
+ // it's response to last message
+ message = processsedMessage;
+ } else {
+ // it's not response to last message, create new instance
+ message = DanaRSMessageHashTable.findMessage(receivedCommand);
+ }
+ if (message != null) {
+ log.debug("<<<<< " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(inputBuffer));
+ // process received data
+ message.handleMessage(inputBuffer);
+ message.setReceived();
+ synchronized (message) {
+ // notify to sendMessage
+ message.notify();
+ }
+ MainApp.bus().post(new EventDanaRSPacket(message));
+ } else {
+ log.error("Unknown message received " + DanaRS_Packet.toHexString(inputBuffer));
+ }
+ scheduleDisconnection();
+ break;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ startSignatureFound = false;
+ packetIsValid = false;
+ if (bufferLength < 6) {
+ // stop the loop
+ isProcessing = false;
+ }
+ } else {
+ // stop the loop
+ isProcessing = false;
+ }
+ }
+ }
+
+ public void sendMessage(DanaRS_Packet message) {
+ processsedMessage = message;
+ if (message == null)
+ return;
+
+ byte[] command = {(byte) message.getType(), (byte) message.getOpCode()};
+ byte[] params = message.getRequestParams();
+ log.debug(">>>>> " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(command) + " " + DanaRS_Packet.toHexString(params));
+ byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(message.getOpCode(), params, null);
+ // If there is another message not completely sent, add to queue only
+ if (mSendQueue.size() > 0) {
+ // Split to parts per 20 bytes max
+ for (; ; ) {
+ if (bytes.length > 20) {
+ byte[] addBytes = new byte[20];
+ System.arraycopy(bytes, 0, addBytes, 0, addBytes.length);
+ byte[] reBytes = new byte[bytes.length - addBytes.length];
+ System.arraycopy(bytes, addBytes.length, reBytes, 0, reBytes.length);
+ bytes = reBytes;
+ synchronized (mSendQueue) {
+ mSendQueue.add(addBytes);
+ }
+ } else {
+ synchronized (mSendQueue) {
+ mSendQueue.add(bytes);
+ }
+ break;
+ }
+ }
+
+ } else {
+ if (bytes.length > 20) {
+ // Cut first 20 bytes
+ byte[] sendBytes = new byte[20];
+ System.arraycopy(bytes, 0, sendBytes, 0, sendBytes.length);
+ byte[] reBytes = new byte[bytes.length - sendBytes.length];
+ System.arraycopy(bytes, sendBytes.length, reBytes, 0, reBytes.length);
+ bytes = reBytes;
+ // and send
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), sendBytes);
+ // The rest split to parts per 20 bytes max
+ for (; ; ) {
+ if (bytes.length > 20) {
+ byte[] addBytes = new byte[20];
+ System.arraycopy(bytes, 0, addBytes, 0, addBytes.length);
+ reBytes = new byte[bytes.length - addBytes.length];
+ System.arraycopy(bytes, addBytes.length, reBytes, 0, reBytes.length);
+ bytes = reBytes;
+ synchronized (mSendQueue) {
+ mSendQueue.add(addBytes);
+ }
+ } else {
+ synchronized (mSendQueue) {
+ mSendQueue.add(bytes);
+ }
+ break;
+ }
+ }
+ } else {
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
+ }
+ }
+ // The rest from queue is send from onCharasteristicWrite (after sending 1st part)
+ synchronized (message) {
+ try {
+ message.wait(5000);
+ } catch (InterruptedException e) {
+ log.error("sendMessage InterruptedException", e);
+ e.printStackTrace();
+ }
+ }
+
+ //SystemClock.sleep(200);
+ if (!message.isReceived()) {
+ log.warn("Reply not received " + message.getFriendlyName());
+ }
+ scheduleDisconnection();
+ }
+
+ private void SendPairingRequest() {
+ // Start activity which is waiting 20sec
+ // On pump pairing request is displayed and is waiting for conformation
+ Intent i = new Intent();
+ i.setClass(MainApp.instance(), PairingHelperActivity.class);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ MainApp.instance().startActivity(i);
+
+ byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST, null, null);
+ log.debug(">>>>> " + "ENCRYPTION__PASSKEY_REQUEST" + " " + DanaRS_Packet.toHexString(bytes));
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
+ }
+
+ protected void SendPumpCheck() {
+ // 1st message sent to pump after connect
+ byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, getConnectDeviceName());
+ log.debug(">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes));
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
+ }
+
+ private void SendTimeInfo() {
+ byte[] bytes = BleCommandUtil.getInstance().getEncryptedPacket(BleCommandUtil.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null);
+ log.debug(">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes));
+ writeCharacteristic_NO_RESPONSE(getUARTWriteBTGattChar(), bytes);
+ }
+
+ 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);
+ log.debug("Disconnection scheduled");
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
new file mode 100644
index 0000000000..6b39788342
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java
@@ -0,0 +1,402 @@
+package info.nightscout.androidaps.plugins.PumpDanaRS.services;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+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.db.Treatment;
+import info.nightscout.androidaps.events.EventAppExit;
+import info.nightscout.androidaps.events.EventInitializationChanged;
+import info.nightscout.androidaps.events.EventPumpStatusChanged;
+import info.nightscout.androidaps.plugins.Overview.Notification;
+import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
+import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
+import info.nightscout.androidaps.plugins.PumpDanaR.events.EventDanaRNewStatus;
+import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_APS_Basal_Set_Temporary_Basal;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_APS_History_Events;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_APS_Set_Event_History;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Get_Basal_Rate;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Get_Profile_Number;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Get_Temporary_Basal_State;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Profile_Basal_Rate;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Profile_Number;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Basal_Set_Temporary_Basal;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Bolus_Option;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_CIR_CF_Array;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Calculation_Information;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Extended_Bolus_State;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Get_Step_Bolus_Information;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Stop;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Get_Pump_Check;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Get_Shipping_Information;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Initial_Screen_Information;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_General_Set_History_Upload_Mode;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Alarm;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Basal;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Blood_Glucose;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Bolus;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Carbohydrate;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Daily;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Prime;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Refill;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_History_Suspend;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_Delivery_Complete;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Notify_Delivery_Rate_Display;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Get_Pump_Time;
+import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet_Option_Set_Pump_Time;
+import info.nightscout.utils.NSUpload;
+import info.nightscout.utils.SP;
+
+public class DanaRSService extends Service {
+ private static Logger log = LoggerFactory.getLogger(DanaRSService.class);
+
+ private BLEComm bleComm = BLEComm.getInstance(this);
+
+ private PowerManager.WakeLock mWakeLock;
+ private IBinder mBinder = new LocalBinder();
+
+ private DanaRPump danaRPump = DanaRPump.getInstance();
+ private Treatment bolusingTreatment = null;
+
+ private long lastHistoryFetched = 0;
+
+ public DanaRSService() {
+ try {
+ MainApp.bus().unregister(this);
+ } catch (RuntimeException x) {
+ // Ignore
+ }
+ MainApp.bus().register(this);
+
+ PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DanaRSService.class.getSimpleName());
+
+ }
+
+ public boolean isConnected() {
+ return bleComm.isConnected;
+ }
+
+ public boolean isConnecting() {
+ return bleComm.isConnecting;
+ }
+
+ public boolean connect(String from, String address, Object confirmConnect) {
+ return bleComm.connect(from, address, confirmConnect);
+ }
+
+ public void stopConnecting() {
+ bleComm.stopConnecting();
+ }
+
+ public void disconnect(String from) {
+ bleComm.disconnect(from);
+ }
+
+ public void sendMessage(DanaRS_Packet message) {
+ bleComm.sendMessage(message);
+ }
+
+ protected boolean getPumpStatus() {
+ try {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpstatus)));
+
+ bleComm.sendMessage(new DanaRS_Packet_General_Initial_Screen_Information());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus)));
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // last bolus
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus)));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+
+ Date now = new Date();
+ if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRSPlugin.class).isInitialized()) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
+ bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information()); // serial no
+ bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check()); // firmware
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Profile_Number());
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Bolus_Option()); // isExtendedEnabled
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information()); // bolusStep, maxBolus
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate()); // basal profile, basalStep, maxBasal
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Calculation_Information()); // target
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_CIR_CF_Array());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
+ long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
+ log.debug("Pump time difference: " + timeDiff + " seconds");
+ if (Math.abs(timeDiff) > 10) {
+ bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(new Date()));
+ bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time());
+ 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) {
+ log.error("Unhandled exception", e);
+ }
+ return true;
+ }
+
+ public boolean loadEvents() {
+ DanaRS_Packet_APS_History_Events msg;
+ if (lastHistoryFetched == 0) {
+ msg = new DanaRS_Packet_APS_History_Events(0);
+ log.debug("Loading complete event history");
+ } else {
+ msg = new DanaRS_Packet_APS_History_Events(lastHistoryFetched);
+ log.debug("Loading event history from: " + new Date(lastHistoryFetched).toLocaleString());
+ }
+ bleComm.sendMessage(msg);
+ while (!msg.done && bleComm.isConnected()) {
+ SystemClock.sleep(100);
+ }
+ SystemClock.sleep(200);
+ lastHistoryFetched = DanaRS_Packet_APS_History_Events.lastEventTimeLoaded;
+ return true;
+ }
+
+
+ public boolean bolus(double insulin, int carbs, long carbtime, Treatment t) {
+ bolusingTreatment = t;
+ int speed = SP.getInt(R.string.key_danars_bolusspeed, 0);
+ DanaRS_Packet_Bolus_Set_Step_Bolus_Start start = new DanaRS_Packet_Bolus_Set_Step_Bolus_Start(insulin, speed);
+ DanaRS_Packet_Bolus_Set_Step_Bolus_Stop stop = new DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(insulin, t); // initialize static variables
+ DanaRS_Packet_Notify_Delivery_Complete complete = new DanaRS_Packet_Notify_Delivery_Complete(insulin, t); // initialize static variables
+
+ if (!isConnected()) return false;
+
+ if (carbs > 0) {
+// MsgSetCarbsEntry msg = new MsgSetCarbsEntry(carbtime, carbs); ####
+// bleComm.sendMessage(msg);
+ DanaRS_Packet_APS_Set_Event_History msgSetHistoryEntry_v2 = new DanaRS_Packet_APS_Set_Event_History(DanaRPump.CARBS, carbtime, carbs, 0);
+ bleComm.sendMessage(msgSetHistoryEntry_v2);
+ lastHistoryFetched = carbtime - 60000;
+ }
+ if (insulin > 0) {
+ DanaRS_Packet_Notify_Delivery_Rate_Display progress = new DanaRS_Packet_Notify_Delivery_Rate_Display(insulin, t); // initialize static variables
+
+ if (!stop.stopped) {
+ bleComm.sendMessage(start);
+ } else {
+ t.insulin = 0d;
+ return false;
+ }
+ while (!stop.stopped && !start.failed && !complete.done) {
+ SystemClock.sleep(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");
+ }
+ }
+ }
+ SystemClock.sleep(3000);
+ bolusingTreatment = null;
+ DanaRSPlugin.connectIfNotConnected("ReadHistoryAfterBolus");
+ loadEvents();
+ return true;
+ }
+
+ public void bolusStop() {
+ if (Config.logDanaBTComm)
+ log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
+ DanaRS_Packet_Bolus_Set_Step_Bolus_Stop stop = new DanaRS_Packet_Bolus_Set_Step_Bolus_Stop();
+ stop.forced = true;
+ if (isConnected()) {
+ bleComm.sendMessage(stop);
+ while (!stop.stopped) {
+ bleComm.sendMessage(stop);
+ SystemClock.sleep(200);
+ }
+ } else {
+ stop.stopped = true;
+ }
+ }
+
+ public boolean tempBasal(Integer percent, int durationInHours) {
+ if (!isConnected()) return false;
+ if (danaRPump.isTempBasalInProgress) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal());
+ SystemClock.sleep(500);
+ }
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Temporary_Basal(percent, durationInHours));
+ SystemClock.sleep(200);
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+ loadEvents();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
+ return true;
+ }
+
+ public boolean highTempBasal(Integer percent) {
+ if (danaRPump.isTempBasalInProgress) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal());
+ SystemClock.sleep(500);
+ }
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingtempbasal)));
+ bleComm.sendMessage(new DanaRS_Packet_APS_Basal_Set_Temporary_Basal(percent));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+ loadEvents();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
+ return true;
+ }
+
+ public boolean tempBasalStop() {
+ if (!isConnected()) return false;
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingtempbasal)));
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal());
+ bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State());
+ loadEvents();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
+ return true;
+ }
+
+ public boolean extendedBolus(Double insulin, int durationInHalfHours) {
+ if (!isConnected()) return false;
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.settingextendedbolus)));
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Set_Extended_Bolus(insulin, durationInHalfHours));
+ SystemClock.sleep(200);
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State());
+ loadEvents();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
+ return true;
+ }
+
+ public boolean extendedBolusStop() {
+ if (!isConnected()) return false;
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.stoppingextendedbolus)));
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel());
+ bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State());
+ loadEvents();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
+ return true;
+ }
+
+ public boolean updateBasalsInPump(Profile profile) {
+ if (!isConnected()) return false;
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates)));
+ double[] basal = DanaRPump.buildDanaRProfileRecord(profile);
+ DanaRS_Packet_Basal_Set_Profile_Basal_Rate msgSet = new DanaRS_Packet_Basal_Set_Profile_Basal_Rate(0, basal);
+ bleComm.sendMessage(msgSet);
+ DanaRS_Packet_Basal_Set_Profile_Number msgActivate = new DanaRS_Packet_Basal_Set_Profile_Number(0);
+ bleComm.sendMessage(msgActivate);
+ danaRPump.lastSettingsRead = new Date(0); // force read full settings
+ getPumpStatus();
+ MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING));
+ return true;
+ }
+
+ public boolean loadHistory(byte type) {
+ if (!isConnected()) return false;
+ DanaRS_Packet_History_ msg = null;
+ switch (type) {
+ case RecordTypes.RECORD_TYPE_ALARM:
+ msg = new DanaRS_Packet_History_Alarm();
+ break;
+ case RecordTypes.RECORD_TYPE_PRIME:
+ msg = new DanaRS_Packet_History_Prime();
+ break;
+ case RecordTypes.RECORD_TYPE_BASALHOUR:
+ msg = new DanaRS_Packet_History_Basal();
+ break;
+ case RecordTypes.RECORD_TYPE_BOLUS:
+ msg = new DanaRS_Packet_History_Bolus();
+ break;
+ case RecordTypes.RECORD_TYPE_CARBO:
+ msg = new DanaRS_Packet_History_Carbohydrate();
+ break;
+ case RecordTypes.RECORD_TYPE_DAILY:
+ msg = new DanaRS_Packet_History_Daily();
+ break;
+ case RecordTypes.RECORD_TYPE_GLUCOSE:
+ msg = new DanaRS_Packet_History_Blood_Glucose();
+ break;
+ case RecordTypes.RECORD_TYPE_REFILL:
+ msg = new DanaRS_Packet_History_Refill();
+ break;
+ case RecordTypes.RECORD_TYPE_SUSPEND:
+ msg = new DanaRS_Packet_History_Suspend();
+ break;
+ }
+ if (msg != null) {
+ bleComm.sendMessage(new DanaRS_Packet_General_Set_History_Upload_Mode(1));
+ SystemClock.sleep(200);
+ bleComm.sendMessage(msg);
+ while (!msg.done && isConnected()) {
+ SystemClock.sleep(100);
+ }
+ SystemClock.sleep(200);
+ bleComm.sendMessage(new DanaRS_Packet_General_Set_History_Upload_Mode(0));
+ }
+ return true;
+ }
+
+
+ public class LocalBinder extends Binder {
+ public DanaRSService getServiceInstance() {
+ return DanaRSService.this;
+ }
+
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return START_STICKY;
+ }
+
+ @Subscribe
+ public void onStatusEvent(EventAppExit event) {
+ if (Config.logFunctionCalls)
+ log.debug("EventAppExit received");
+
+ stopSelf();
+ if (Config.logFunctionCalls)
+ log.debug("EventAppExit finished");
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
index 1c69de81f7..ea174e4608 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java
@@ -48,6 +48,7 @@ import info.nightscout.androidaps.plugins.PumpDanaRv2.services.DanaRv2ExecutionS
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.
@@ -210,7 +211,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
@Override
public boolean isInitialized() {
- return pump.lastConnection.getTime() > 0 && pump.isExtendedBolusEnabled;
+ return pump.lastConnection.getTime() > 0;
}
@Override
@@ -294,8 +295,21 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
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;
+ // default delivery speed is 12 U/min
+ int preferencesSpeed = SP.getInt(R.string.key_danars_bolusspeed, 0);
+ int speed = 12;
+ switch (preferencesSpeed) {
+ case 0:
+ speed = 12;
+ break;
+ case 1:
+ speed = 30;
+ break;
+ case 2:
+ speed = 60;
+ break;
+ }
+ detailedBolusInfo.date += detailedBolusInfo.insulin / speed * 60d * 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;
@@ -338,7 +352,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
// This is called from APS
@Override
- public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
// Recheck pump status if older than 30 min
if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
doConnect("setTempBasalAbsolute old data");
@@ -380,7 +394,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
if (MainApp.getConfigBuilder().isTempBasalInProgress()) {
// Correct basal already set ?
if (MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis()).percentRate == percentRate) {
- if (!force) {
+ if (!enforceNew) {
result.success = true;
result.percent = percentRate;
result.absolute = MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory();
@@ -578,7 +592,11 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface,
}
public static void doConnect(String from) {
- if (sExecutionService != null) sExecutionService.connect(from);
+ if (sExecutionService != null) {
+ sExecutionService.connect(from);
+ pumpDescription.basalStep = pump.basalStep;
+ pumpDescription.bolusStep = pump.bolusStep;
+ }
}
public static boolean isConnected() {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java
index 0940efd73f..cafba32239 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MessageHashTable_v2.java
@@ -22,6 +22,7 @@ public class MessageHashTable_v2 {
messages = new HashMap();
put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP
put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA
+ put(new MsgBolusStartWithSpeed()); // 0x0104 CMD_MEALINS_START_DATA_SPEED
put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS
put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
index 0e96987728..fc3df19296 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java
@@ -79,7 +79,7 @@ public class DanaRv2ExecutionService extends Service {
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
+ log.debug("Device was disconnected " + device.getName());//Device was disconnected
if (mBTDevice != null && mBTDevice.getName() != null && mBTDevice.getName().equals(device.getName())) {
if (mSerialIOThread != null) {
mSerialIOThread.disconnect("BT disconnection broadcast");
@@ -261,10 +261,13 @@ public class DanaRv2ExecutionService extends Service {
}
}
- mSerialIOThread.sendMessage(tempStatusMsg); // do this before statusBasic because here is temp duration
- mSerialIOThread.sendMessage(exStatusMsg);
mSerialIOThread.sendMessage(statusMsg);
mSerialIOThread.sendMessage(statusBasicMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingtempbasalstatus)));
+ mSerialIOThread.sendMessage(tempStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingextendedbolusstatus)));
+ mSerialIOThread.sendMessage(exStatusMsg);
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingbolusstatus)));
if (!statusMsg.received) {
mSerialIOThread.sendMessage(statusMsg);
@@ -290,6 +293,7 @@ public class DanaRv2ExecutionService extends Service {
Date now = new Date();
if (danaRPump.lastSettingsRead.getTime() + 60 * 60 * 1000L < now.getTime() || !MainApp.getSpecificPlugin(DanaRv2Plugin.class).isInitialized()) {
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumpsettings)));
mSerialIOThread.sendMessage(new MsgSettingShippingInfo());
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
mSerialIOThread.sendMessage(new MsgSettingMeal());
@@ -300,6 +304,7 @@ public class DanaRv2ExecutionService extends Service {
mSerialIOThread.sendMessage(new MsgSettingActiveProfile());
mSerialIOThread.sendMessage(new MsgSettingProfileRatios());
mSerialIOThread.sendMessage(new MsgSettingProfileRatiosAll());
+ MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.gettingpumptime)));
mSerialIOThread.sendMessage(new MsgSettingPumpTime());
long timeDiff = (danaRPump.pumpTime.getTime() - System.currentTimeMillis()) / 1000L;
log.debug("Pump time difference: " + timeDiff + " seconds");
@@ -318,7 +323,7 @@ public class DanaRv2ExecutionService extends Service {
MainApp.bus().post(new EventDanaRNewStatus());
MainApp.bus().post(new EventInitializationChanged());
NSUpload.uploadDeviceStatus();
- if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning ) {
+ if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
log.debug("Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits);
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, MainApp.sResources.getString(R.string.approachingdailylimit), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(reportFail));
@@ -397,7 +402,12 @@ public class DanaRv2ExecutionService extends Service {
public boolean bolus(double amount, int carbs, long carbtime, Treatment t) {
bolusingTreatment = t;
- MsgBolusStart start = new MsgBolusStart(amount);
+ int speed = SP.getInt(R.string.key_danars_bolusspeed, 0);
+ MessageBase start;
+ if (speed == 0)
+ start = new MsgBolusStart(amount);
+ else
+ start = new MsgBolusStartWithSpeed(amount, speed);
MsgBolusStop stop = new MsgBolusStop(amount, t);
connect("bolus");
@@ -538,7 +548,7 @@ public class DanaRv2ExecutionService extends Service {
connect("updateBasalsInPump");
if (!isConnected()) return false;
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.updatingbasalrates)));
- double[] basal = buildDanaRProfileRecord(profile);
+ double[] basal = DanaRPump.buildDanaRProfileRecord(profile);
MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal);
mSerialIOThread.sendMessage(msgSet);
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
@@ -549,17 +559,6 @@ public class DanaRv2ExecutionService extends Service {
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) {
SystemClock.sleep(msecs);
}
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 f4a37b9914..ca3f7a62a0 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
@@ -166,7 +166,7 @@ public class MDIPlugin implements PluginBase, PumpInterface {
}
@Override
- public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
result.success = false;
result.comment = MainApp.instance().getString(R.string.pumperror);
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 3965ef5326..e7323f48af 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
@@ -251,7 +251,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
}
@Override
- public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) {
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder();
TemporaryBasal tempBasal = new TemporaryBasal();
tempBasal.date = System.currentTimeMillis();
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 209743dee1..9f0e7b7b74 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
@@ -497,7 +497,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
PumpInterface pumpInterface = MainApp.getConfigBuilder();
if (pumpInterface != null) {
danaRPlugin = MainApp.getSpecificPlugin(DanaRPlugin.class);
- PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, false);
+ PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30, true);
if (result.success) {
reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration);
if (danaRPlugin != null)
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
index b4461eabb7..a34146f04a 100644
--- 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
@@ -43,7 +43,7 @@ public class ProfileViewerDialog extends DialogFragment {
private TextView dateTextView;
private Button refreshButton;
- static ProfileViewerDialog newInstance(long time) {
+ public static ProfileViewerDialog newInstance(long time) {
ProfileViewerDialog dialog = new ProfileViewerDialog();
Bundle args = new Bundle();
@@ -63,7 +63,7 @@ public class ProfileViewerDialog extends DialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- View layout = inflater.inflate(R.layout.nsprofileviewer_fragment, container, false);
+ View layout = inflater.inflate(R.layout.profileviewer_fragment, container, false);
noProfile = (TextView) layout.findViewById(R.id.profileview_noprofile);
units = (TextView) layout.findViewById(R.id.profileview_units);
@@ -95,7 +95,7 @@ public class ProfileViewerDialog extends DialogFragment {
noProfile.setVisibility(View.GONE);
units.setText(profile.getUnits());
dia.setText(DecimalFormatter.to2Decimal(profile.getDia()) + " h");
- activeProfile.setText(profileSwitch.profileName);
+ activeProfile.setText(profileSwitch.getCustomizedName());
dateTextView.setText(DateUtil.dateAndTimeString(profileSwitch.date));
ic.setText(profile.getIcList());
isf.setText(profile.getIsfList());
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
index 7fcca51e67..e5655cdb18 100644
--- 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
@@ -74,7 +74,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen
} else {
holder.duration.setText("");
}
- holder.name.setText(profileSwitch.profileName);
+ holder.name.setText(profileSwitch.getCustomizedName());
if (profileSwitch.isInProgress())
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
else
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 07d41a0d8a..9fbcc31685 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
@@ -23,18 +23,20 @@ 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.ProfileSwitch;
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.ProfileInterface;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Actions.dialogs.FillDialog;
+import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Loop.APSResult;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
-import info.nightscout.androidaps.plugins.ProfileCircadianPercentage.CircadianPercentageProfilePlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
@@ -67,8 +69,7 @@ public class ActionStringHandler {
public synchronized static void handleInitiate(String actionstring) {
- if (!BuildConfig.WEAR_CONTROL) return;
-
+ if (!SP.getBoolean("wearcontrol", false)) return;
lastBolusWizard = null;
@@ -242,25 +243,21 @@ public class ActionStringHandler {
lastBolusWizard = bolusWizard;
} 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!");
+ ProfileSwitch activeProfileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
+ if(activeProfileSwitch==null){
+ sendError("No active profile switch!");
return;
} else {
// read CPP values
rTitle = "opencpp";
rMessage = "opencpp";
- rAction = "opencpp" + " " + cpp.getPercentage() + " " + cpp.getTimeshift();
+ rAction = "opencpp" + " " + activeProfileSwitch.percentage + " " + activeProfileSwitch.timeshift;
}
} 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!");
+ ProfileSwitch activeProfileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
+ if(activeProfileSwitch==null){
+ sendError("No active profile switch!");
return;
} else {
// read CPP values
@@ -334,13 +331,16 @@ public class ActionStringHandler {
private static String generateTDDMessage(List historyList, List dummies) {
+ ProfileInterface activeProfile = MainApp.getConfigBuilder().getActiveProfileInterface();
+
+ if(activeProfile == null){
+ return "No profile loaded :(";
+ }
+
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;
+ double refTDD = activeProfile.getProfile().getDefaultProfile().baseBasalSum()*2;
int i = 0;
double sum = 0d;
@@ -364,15 +364,15 @@ public class ActionStringHandler {
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 += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (DecimalFormatter.to0Decimal(100*weighted03/refTDD) + "%") + "\n";
+ message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (DecimalFormatter.to0Decimal(100*weighted05/refTDD) + "%") + "\n";
+ message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (DecimalFormatter.to0Decimal(100*weighted07/refTDD) + "%") + "\n";
message += "\n";
PumpInterface pump = MainApp.getConfigBuilder().getActivePump();
if (pump != null && pump instanceof DanaRPlugin) {
double tdd = DanaRPump.getInstance().dailyTotalUnits;
- message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (isCPP?(DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%"):"") + "\n";
+ message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%") + "\n";
message += "\n";
}
@@ -380,7 +380,7 @@ public class ActionStringHandler {
Collections.reverse(historyList);
for (DanaRHistoryRecord record : historyList) {
double tdd = record.recordDailyBolus + record.recordDailyBasal;
- message += df.format(new Date(record.recordDate)) + " " + DecimalFormatter.to2Decimal(tdd) +"U " + (isCPP?(DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%"):"") + (dummies.contains(record)?"x":"") +"\n";
+ message += df.format(new Date(record.recordDate)) + " " + DecimalFormatter.to2Decimal(tdd) +"U " + (DecimalFormatter.to0Decimal(100*tdd/refTDD) + "%") + (dummies.contains(record)?"x":"") +"\n";
}
return message;
}
@@ -521,7 +521,7 @@ public class ActionStringHandler {
public synchronized static void handleConfirmation(String actionString) {
- if (!BuildConfig.WEAR_CONTROL) return;
+ if (!SP.getBoolean("wearcontrol", false)) return;
//Guard from old or duplicate confirmations
@@ -564,29 +564,47 @@ public class ActionStringHandler {
} else if ("cppset".equals(act[0])) {
int timeshift = SafeParse.stringToInt(act[1]);
int percentage = SafeParse.stringToInt(act[2]);
- setCPP(percentage, timeshift);
+ setCPP(timeshift, percentage);
} 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);
+ private static void setCPP(int timeshift, int percentage) {
- if(cpp == null || activeProfile==null || cpp != activeProfile){
- sendError("CPP not activated!");
- return;
+ String msg = "";
+
+
+ //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";
}
- String msg = cpp.externallySetParameters(timeshift, percentage);
- if(msg != null && !"".equals(msg)){
+ 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);
String rTitle = "STATUS";
String rAction = "statusmessage";
WearFragment.getPlugin(MainApp.instance()).requestActionConfirmation(rTitle, msg, rAction);
lastSentTimestamp = System.currentTimeMillis();
lastConfirmActionString = rAction;
+ return;
}
+
+ //send profile to pumpe
+ new NewNSTreatmentDialog(); //init
+ NewNSTreatmentDialog.doProfileSwitch(0, percentage, timeshift);
}
private static void generateTempTarget(int duration, double low, double high) {
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 a5715ed5a1..e0d8d9210d 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
@@ -29,7 +29,7 @@ import info.nightscout.utils.SP;
public class WearPlugin implements PluginBase {
- private static boolean fragmentEnabled = Config.WEAR;
+ private static boolean fragmentEnabled = true;
private boolean fragmentVisible = true;
private static WatchUpdaterService watchUS;
private final Context ctx;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java
index 93a85686b3..89189e7e12 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
@@ -23,7 +23,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.Constants;
@@ -31,6 +30,7 @@ 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.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.TemporaryBasal;
@@ -38,12 +38,11 @@ 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.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.utils.DecimalFormatter;
+import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
@@ -67,6 +66,7 @@ public class WatchUpdaterService extends WearableListenerService implements
private static final String OPEN_SETTINGS_PATH = "/openwearsettings";
private static final String NEW_STATUS_PATH = "/sendstatustowear";
+ private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
@@ -76,7 +76,7 @@ public class WatchUpdaterService extends WearableListenerService implements
SharedPreferences mPrefs;
private static boolean lastLoopStatus;
- private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfilePlugin.class);
+ private static Logger log = LoggerFactory.getLogger(WatchUpdaterService.class);
@Override
@@ -328,6 +328,7 @@ public class WatchUpdaterService extends WearableListenerService implements
entries.putDataMapArrayList("entries", dataMaps);
new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient).execute(entries);
}
+ sendPreferences();
sendBasals();
sendStatus();
}
@@ -529,6 +530,22 @@ public class WatchUpdaterService extends WearableListenerService implements
}
}
+ private void sendPreferences() {
+ if (googleApiClient.isConnected()) {
+
+ boolean wearcontrol = SP.getBoolean("wearcontrol",false);
+
+ PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH);
+ //unique content
+ dataMapRequest.getDataMap().putDouble("timestamp", System.currentTimeMillis());
+ dataMapRequest.getDataMap().putBoolean("wearcontrol", wearcontrol);
+ PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
+ Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
+ } else {
+ Log.e("SendStatus", "No connection to wearable available!");
+ }
+ }
+
@NonNull
private String generateStatusString() {
String status = "";
@@ -551,8 +568,8 @@ public class WatchUpdaterService extends WearableListenerService implements
//Temp basal
TreatmentsInterface treatmentsInterface = MainApp.getConfigBuilder();
- if (treatmentsInterface.isTempBasalInProgress()) {
- TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis());
+ TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis());
+ if (activeTemp != null) {
status += activeTemp.toStringShort();
}
diff --git a/app/src/main/java/info/nightscout/utils/DateUtil.java b/app/src/main/java/info/nightscout/utils/DateUtil.java
index 2410014808..3e32557adb 100644
--- a/app/src/main/java/info/nightscout/utils/DateUtil.java
+++ b/app/src/main/java/info/nightscout/utils/DateUtil.java
@@ -1,6 +1,8 @@
package info.nightscout.utils;
+import android.support.v4.util.LongSparseArray;
import android.text.format.DateUtils;
+import android.util.SparseIntArray;
import java.text.DateFormat;
import java.text.ParseException;
@@ -8,6 +10,7 @@ import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -24,8 +27,8 @@ 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'";
+ private static String FORMAT_DATE_ISO = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+ private static String FORMAT_DATE_ISO_MSEC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
/**
* Takes in an ISO date string of the following format:
@@ -37,13 +40,13 @@ public class DateUtil {
*/
public static Date fromISODateString(String isoDateString)
throws Exception {
- SimpleDateFormat f = new SimpleDateFormat(FORMAT_DATE_ISO);
+ SimpleDateFormat f = new SimpleDateFormat(FORMAT_DATE_ISO, Locale.getDefault());
Date date;
f.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
date = f.parse(isoDateString);
} catch (ParseException e) {
- f = new SimpleDateFormat(FORMAT_DATE_ISO_MSEC);
+ f = new SimpleDateFormat(FORMAT_DATE_ISO_MSEC, Locale.getDefault());
f.setTimeZone(TimeZone.getTimeZone("UTC"));
date = f.parse(isoDateString);
}
@@ -61,7 +64,7 @@ public class DateUtil {
public static String toISOString(Date date, String format, TimeZone tz) {
if (format == null) format = FORMAT_DATE_ISO;
if (tz == null) tz = TimeZone.getDefault();
- DateFormat f = new SimpleDateFormat(format);
+ DateFormat f = new SimpleDateFormat(format, Locale.getDefault());
f.setTimeZone(tz);
return f.format(date);
}
@@ -85,7 +88,7 @@ public class DateUtil {
}
public static int toSeconds(String hh_colon_mm) {
- Pattern p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM | PM)");
+ Pattern p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM | PM|)");
Matcher m = p.matcher(hh_colon_mm);
int retval = 0;
@@ -131,4 +134,16 @@ public class DateUtil {
return String.format(MainApp.sResources.getString(R.string.minago), mins);
}
+ private static LongSparseArray timeStrings = new LongSparseArray<>();
+
+ public static String timeStringFromSeconds(int seconds) {
+ String cached = timeStrings.get(seconds);
+ if (cached != null)
+ return cached;
+ String t = DateUtils.formatDateTime(MainApp.instance(), toDate(seconds).getTime(), DateUtils.FORMAT_SHOW_TIME);
+ timeStrings.put(seconds, t);
+ return t;
+ }
+
+
}
\ 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
index e6cb358ac1..98ce8632ff 100644
--- a/app/src/main/java/info/nightscout/utils/NSUpload.java
+++ b/app/src/main/java/info/nightscout/utils/NSUpload.java
@@ -274,7 +274,7 @@ public class NSUpload {
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.PROFILESWITCH);
data.put("duration", profileSwitch.durationInMinutes);
- data.put("profile", profileSwitch.profileName);
+ data.put("profile", profileSwitch.getCustomizedName());
data.put("profileJson", profileSwitch.profileJson);
data.put("profilePlugin", profileSwitch.profilePlugin);
if (profileSwitch.isCPP) {
diff --git a/app/src/main/java/info/nightscout/utils/NumberPicker.java b/app/src/main/java/info/nightscout/utils/NumberPicker.java
index 1827009a94..53ffd90f7b 100644
--- a/app/src/main/java/info/nightscout/utils/NumberPicker.java
+++ b/app/src/main/java/info/nightscout/utils/NumberPicker.java
@@ -43,6 +43,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
Double step = 1d;
NumberFormat formater;
boolean allowZero = false;
+ TextWatcher textWatcher = null;
private Handler mHandler;
private ScheduledExecutorService mUpdater;
@@ -95,9 +96,12 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
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);
+ minusButton = (Button) findViewById(R.id.decrement);
+ minusButton.setId(View.generateViewId());
+ plusButton = (Button) findViewById(R.id.increment);
+ plusButton.setId(View.generateViewId());
+ editText = (EditText) findViewById(R.id.display);
+ editText.setId(View.generateViewId());
mHandler = new Handler() {
@Override
@@ -120,7 +124,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
plusButton.setOnTouchListener(this);
plusButton.setOnKeyListener(this);
plusButton.setOnClickListener(this);
- this.addTextChangedListener(new TextWatcher() {
+ setTextWatcher(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -138,16 +142,14 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
});
}
- public void removeTextChangedListener(TextWatcher textWatcher) {
- editText.removeTextChangedListener(textWatcher);
- }
-
- public void addTextChangedListener(TextWatcher textWatcher) {
+ public void setTextWatcher(TextWatcher textWatcher) {
+ this.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);
+ this.textWatcher = textWatcher;
editText.addTextChangedListener(textWatcher);
}
@@ -159,12 +161,20 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
this.formater = formater;
this.allowZero = allowZero;
+ if (textWatcher != null)
+ editText.removeTextChangedListener(textWatcher);
updateEditText();
+ if (textWatcher != null)
+ editText.addTextChangedListener(textWatcher);
}
public void setValue(Double value) {
+ if (textWatcher != null)
+ editText.removeTextChangedListener(textWatcher);
this.value = value;
updateEditText();
+ if (textWatcher != null)
+ editText.addTextChangedListener(textWatcher);
}
public Double getValue() {
diff --git a/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java b/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java
deleted file mode 100644
index c9949252af..0000000000
--- a/app/src/main/java/info/nightscout/utils/PlusMinusEditText.java
+++ /dev/null
@@ -1,210 +0,0 @@
-package info.nightscout.utils;
-
-import android.os.Handler;
-import android.os.Message;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-
-import android.widget.ImageView;
-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 PlusMinusEditText implements View.OnKeyListener,
- View.OnTouchListener, View.OnClickListener {
- private static Logger log = LoggerFactory.getLogger(PlusMinusEditText.class);
-
- Integer editTextID;
- TextView editText;
- ImageView minusImage;
- ImageView plusImage;
-
- 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 PlusMinusEditText(View view, int editTextID, int plusID, int minusID, Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero) {
- editText = (TextView) view.findViewById(editTextID);
- minusImage = (ImageView) view.findViewById(minusID);
- plusImage = (ImageView) view.findViewById(plusID);
-
- this.value = initValue;
- this.minValue = minValue;
- this.maxValue = maxValue;
- this.step = step;
- this.formater = formater;
- this.allowZero = allowZero;
-
- 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);
- }
- };
-
- minusImage.setOnTouchListener(this);
- minusImage.setOnKeyListener(this);
- minusImage.setOnClickListener(this);
- plusImage.setOnTouchListener(this);
- plusImage.setOnKeyListener(this);
- plusImage.setOnClickListener(this);
- 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 == plusImage) {
- 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 == plusImage);
- }
- 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 == plusImage);
- }
- return false;
- }
-
-}
diff --git a/app/src/main/java/info/nightscout/utils/SpinnerHelper.java b/app/src/main/java/info/nightscout/utils/SpinnerHelper.java
new file mode 100644
index 0000000000..84315825f5
--- /dev/null
+++ b/app/src/main/java/info/nightscout/utils/SpinnerHelper.java
@@ -0,0 +1,150 @@
+package info.nightscout.utils;
+
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.Spinner;
+import android.widget.SpinnerAdapter;
+
+/**
+ * Spinner Helper class that works around some common issues
+ * with the stock Android Spinner
+ *
+ * A Spinner will normally call it's OnItemSelectedListener
+ * when you use setSelection(...) in your initialization code.
+ * This is usually unwanted behavior, and a common work-around
+ * is to use spinner.post(...) with a Runnable to assign the
+ * OnItemSelectedListener after layout.
+ *
+ * If you do not call setSelection(...) manually, the callback
+ * may be called with the first item in the adapter you have
+ * set. The common work-around for that is to count callbacks.
+ *
+ * While these workarounds usually *seem* to work, the callback
+ * may still be called repeatedly for other reasons while the
+ * selection hasn't actually changed. This will happen for
+ * example, if the user has accessibility options enabled -
+ * which is more common than you might think as several apps
+ * use this for different purposes, like detecting which
+ * notifications are active.
+ *
+ * Ideally, your OnItemSelectedListener callback should be
+ * coded defensively so that no problem would occur even
+ * if the callback was called repeatedly with the same values
+ * without any user interaction, so no workarounds are needed.
+ *
+ * This class does that for you. It keeps track of the values
+ * you have set with the setSelection(...) methods, and
+ * proxies the OnItemSelectedListener callback so your callback
+ * only gets called if the selected item's position differs
+ * from the one you have set by code, or the first item if you
+ * did not set it.
+ *
+ * This also means that if the user actually clicks the item
+ * that was previously selected by code (or the first item
+ * if you didn't set a selection by code), the callback will
+ * not fire.
+ *
+ * To implement, replace current occurrences of:
+ *
+ * Spinner spinner =
+ * (Spinner)findViewById(R.id.xxx);
+ *
+ * with:
+ *
+ * SpinnerHelper spinner =
+ * new SpinnerHelper(findViewById(R.id.xxx))
+ *
+ * SpinnerHelper proxies the (my) most used calls to Spinner
+ * but not all of them. Should a method not be available, use:
+ *
+ * spinner.getSpinner().someMethod(...)
+ *
+ * Or just add the proxy method yourself :)
+ *
+ * (Quickly) Tested on devices from 2.3.6 through 4.2.2
+ *
+ * @author Jorrit "Chainfire" Jongma
+ * @license WTFPL (do whatever you want with this, nobody cares)
+ */
+public class SpinnerHelper implements OnItemSelectedListener {
+ private final Spinner spinner;
+ private boolean userTouched;
+
+ private int lastPosition = -1;
+ private OnItemSelectedListener proxiedItemSelectedListener = null;
+
+ public SpinnerHelper(Object spinner) {
+ this.spinner = (spinner != null) ? (Spinner)spinner : null;
+ }
+
+ public Spinner getSpinner() {
+ return spinner;
+ }
+
+ public void setSelection(int position) {
+ lastPosition = Math.max(-1, position);
+ spinner.setSelection(position);
+ }
+
+ public void setSelection(int position, boolean animate) {
+ lastPosition = Math.max(-1, position);
+ spinner.setSelection(position, animate);
+ }
+
+ public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+ proxiedItemSelectedListener = listener;
+ setTouchListener();
+ spinner.setOnItemSelectedListener(listener == null ? null : this);
+ }
+
+ public void setTouchListener() {
+ spinner.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ userTouched = true;
+ return false;
+ }
+ });
+ }
+
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ if (position != lastPosition && userTouched) {
+ lastPosition = position;
+ if (proxiedItemSelectedListener != null) {
+ proxiedItemSelectedListener.onItemSelected(
+ parent, view, position, id
+ );
+ }
+ }
+ }
+
+ public void onNothingSelected(AdapterView> parent) {
+ if (-1 != lastPosition) {
+ lastPosition = -1;
+ if (proxiedItemSelectedListener != null) {
+ proxiedItemSelectedListener.onNothingSelected(
+ parent
+ );
+ }
+ }
+ }
+
+ public void setAdapter(SpinnerAdapter adapter) {
+ if (adapter.getCount() > 0) {
+ lastPosition = 0;
+ }
+ spinner.setAdapter(adapter);
+ }
+
+ public SpinnerAdapter getAdapter() { return spinner.getAdapter(); }
+ public int getCount() { return spinner.getCount(); }
+ public Object getItemAtPosition(int position) { return spinner.getItemAtPosition(position); }
+ public long getItemIdAtPosition(int position) { return spinner.getItemIdAtPosition(position); }
+ public Object getSelectedItem() { return spinner.getSelectedItem(); }
+ public long getSelectedItemId() { return spinner.getSelectedItemId(); }
+ public int getSelectedItemPosition() { return spinner.getSelectedItemPosition(); }
+ public void setEnabled(boolean enabled) { spinner.setEnabled(enabled); }
+ public boolean isEnabled() { return spinner.isEnabled(); }
+}
diff --git a/app/src/main/java/info/nightscout/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/utils/TimeListEdit.java
index 8a1fac75a3..af3668310a 100644
--- a/app/src/main/java/info/nightscout/utils/TimeListEdit.java
+++ b/app/src/main/java/info/nightscout/utils/TimeListEdit.java
@@ -1,22 +1,18 @@
package info.nightscout.utils;
import android.content.Context;
-import android.os.Build;
+import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.TextViewCompat;
import android.text.Editable;
-import android.text.Layout;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
-import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.Spinner;
import android.widget.TextView;
import org.json.JSONArray;
@@ -39,40 +35,49 @@ import info.nightscout.androidaps.R;
public class TimeListEdit {
private static Logger log = LoggerFactory.getLogger(TimeListEdit.class);
- final int ONEHOURINSECONDS = 60 * 60;
+ private final int ONEHOURINSECONDS = 60 * 60;
- LinearLayout layout;
+ private View[] intervals = new View[24];
+ private SpinnerHelper[] spinners = new SpinnerHelper[24];
+ private NumberPicker[] numberPickers1 = new NumberPicker[24];
+ private NumberPicker[] numberPickers2 = new NumberPicker[24];
+ private ImageView[] addButtons = new ImageView[24];
+ private ImageView[] removeButtons = new ImageView[24];
+ private ImageView finalAdd;
- Context context;
- View view;
- int resLayoutId;
- String label;
- JSONArray data1;
- JSONArray data2;
- NumberFormat formatter;
- Runnable save;
+ private Context context;
+ private View view;
+ private int resLayoutId;
+ private String label;
+ private JSONArray data1;
+ private JSONArray data2;
+ private double step;
+ private NumberFormat formatter;
+ private Runnable save;
+ private LinearLayout layout;
+ private TextView textlabel;
+ private int inflatedUntil = -1;
- public TimeListEdit(Context context, View view, int resLayoutId, String label, JSONArray data1, JSONArray data2, NumberFormat formatter, Runnable save) {
+
+ public TimeListEdit(Context context, View view, int resLayoutId, String label, JSONArray data1, JSONArray data2, double step, NumberFormat formatter, Runnable save) {
this.context = context;
this.view = view;
this.resLayoutId = resLayoutId;
this.label = label;
this.data1 = data1;
this.data2 = data2;
+ this.step = step;
this.formatter = formatter;
this.save = save;
buildView();
}
private void buildView() {
- LayoutInflater inflater = LayoutInflater.from(context);
layout = (LinearLayout) view.findViewById(resLayoutId);
- layout.removeAllViews();
-
- TextView textlabel = new TextView(context);
+ textlabel = new TextView(context);
textlabel.setText(label);
- textlabel.setGravity(Gravity.LEFT);
+ textlabel.setGravity(Gravity.START);
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
llp.setMargins(10, 0, 0, 0); // llp.setMargins(left, top, right, bottom);
textlabel.setLayoutParams(llp);
@@ -80,177 +85,219 @@ public class TimeListEdit {
TextViewCompat.setTextAppearance(textlabel, android.R.style.TextAppearance_Medium);
layout.addView(textlabel);
- for (int i = 0; i < itemsCount(); i++) {
- View childview = inflater.inflate(R.layout.timelistedit_element, layout, false);
- childview.setId(View.generateViewId());
- final Spinner timeSpinner = (Spinner) childview.findViewById(R.id.timelistedit_time);
- timeSpinner.setId(View.generateViewId());
- int previous = i == 0 ? -1 * ONEHOURINSECONDS : secondFromMidnight(i - 1);
- int next = i == itemsCount() - 1 ? 24 * ONEHOURINSECONDS : secondFromMidnight(i + 1);
- if (i == 0) next = ONEHOURINSECONDS;
- fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
+ for (int i = 0; i < 24 && i < itemsCount(); i++) {
+ inflateRow(i);
+ inflatedUntil = i;
+ }
- final EditText editText1 = (EditText) childview.findViewById(R.id.timelistedit_edit1);
- editText1.setId(View.generateViewId());
- fillNumber(editText1, value1(i));
- final EditText editText2 = ((EditText) childview.findViewById(R.id.timelistedit_edit2));
- fillNumber(editText2, value2(i));
- editText2.setId(View.generateViewId());
- if (data2 == null) {
- editText2.setVisibility(View.GONE);
+ // last "plus" to append new interval
+ finalAdd = new ImageView(context);
+ finalAdd.setImageResource(R.drawable.add);
+ LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
+ illp.gravity = Gravity.CENTER;
+ layout.addView(finalAdd);
+ finalAdd.setLayoutParams(illp);
+ finalAdd.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0);
+ callSave();
+ log();
+ fillView();
}
+ });
+ fillView();
+ }
- ImageView addbutton = (ImageView) childview.findViewById(R.id.timelistedit_add);
- addbutton.setId(View.generateViewId());
- ImageView removebutton = (ImageView) childview.findViewById(R.id.timelistedit_remove);
- removebutton.setId(View.generateViewId());
+ private void inflateRow(int i) {
- if (itemsCount() == 1 && i == 0) {
- removebutton.setVisibility(View.GONE);
- }
+ LayoutInflater inflater = LayoutInflater.from(context);
+ View childview = intervals[i] = inflater.inflate(R.layout.timelistedit_element, layout, false);
+ spinners[i] = new SpinnerHelper(childview.findViewById(R.id.timelistedit_time));
+ numberPickers1[i] = (NumberPicker) childview.findViewById(R.id.timelistedit_edit1);
+ numberPickers2[i] = (NumberPicker) childview.findViewById(R.id.timelistedit_edit2);
+ addButtons[i] = (ImageView) childview.findViewById(R.id.timelistedit_add);
+ removeButtons[i] = (ImageView) childview.findViewById(R.id.timelistedit_remove);
- if (itemsCount() >= 24) {
- addbutton.setVisibility(View.GONE);
- }
-
- final int fixedPos = i;
- addbutton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- int seconds = secondFromMidnight(fixedPos);
- addItem(fixedPos, seconds, 0, 0);
- // for here for the rest of values
- for (int i = fixedPos + 1; i < itemsCount(); i++) {
- if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) {
- editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i));
- }
+ final int fixedPos = i;
+ addButtons[i].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int seconds = secondFromMidnight(fixedPos);
+ addItem(fixedPos, seconds, 0, 0);
+ // for here for the rest of values
+ for (int i = fixedPos + 1; i < itemsCount(); i++) {
+ if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) {
+ editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i));
}
- while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS)
- removeItem(itemsCount() - 1);
- log();
- buildView();
}
- });
+ while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS)
+ removeItem(itemsCount() - 1);
+ callSave();
+ log();
+ fillView();
+ }
+ });
- removebutton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- removeItem(fixedPos);
- log();
- buildView();
+ removeButtons[i].setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ removeItem(fixedPos);
+ callSave();
+ log();
+ fillView();
+ }
+ });
+
+ spinners[i].setOnItemSelectedListener(
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ int seconds = DateUtil.toSeconds(spinners[fixedPos].getSelectedItem().toString());
+ editItem(fixedPos, seconds, value1(fixedPos), value2(fixedPos));
+ log();
+ callSave();
+ fillView();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
}
- });
+ );
- timeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView> parent, View view, int position, long id) {
- int seconds = DateUtil.toSeconds(timeSpinner.getSelectedItem().toString());
- editItem(fixedPos, seconds, value1(fixedPos), value2(fixedPos));
- log();
- buildView();
- }
+ numberPickers1[i].setTextWatcher(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ editItem(fixedPos, secondFromMidnight(fixedPos), SafeParse.stringToDouble(numberPickers1[fixedPos].getText()), value2(fixedPos));
+ callSave();
+ log();
+ }
- @Override
- public void onNothingSelected(AdapterView> parent) {
- editItem(fixedPos, 0, value1(fixedPos), value2(fixedPos));
- log();
- buildView();
- }
- }
- );
+ @Override
+ public void beforeTextChanged(CharSequence s, int start,
+ int count, int after) {
+ }
- editText1.addTextChangedListener(new TextWatcher() {
- @Override
- public void afterTextChanged(Editable s) {
- editItem(fixedPos, secondFromMidnight(fixedPos), SafeParse.stringToDouble(editText1.getText().toString()), value2(fixedPos));
- log();
- }
+ @Override
+ public void onTextChanged(CharSequence s, int start,
+ int before, int count) {
+ }
+ });
- @Override
- public void beforeTextChanged(CharSequence s, int start,
- int count, int after) {
- }
- @Override
- public void onTextChanged(CharSequence s, int start,
- int before, int count) {
- }
- });
+ numberPickers2[i].setTextWatcher(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ editItem(fixedPos, secondFromMidnight(fixedPos), value1(fixedPos), SafeParse.stringToDouble(numberPickers2[fixedPos].getText()));
+ callSave();
+ log();
+ }
- editText2.addTextChangedListener(new TextWatcher() {
- @Override
- public void afterTextChanged(Editable s) {
- editItem(fixedPos, secondFromMidnight(fixedPos), value1(fixedPos), SafeParse.stringToDouble(editText2.getText().toString()));
- log();
- }
+ @Override
+ public void beforeTextChanged(CharSequence s, int start,
+ int count, int after) {
+ }
- @Override
- public void beforeTextChanged(CharSequence s, int start,
- int count, int after) {
- }
+ @Override
+ public void onTextChanged(CharSequence s, int start,
+ int before, int count) {
+ }
+ });
- @Override
- public void onTextChanged(CharSequence s, int start,
- int before, int count) {
- }
- });
+ layout.addView(childview);
+ }
- layout.addView(childview);
+ private void fillView() {
+ for (int i = 0; i < 24; i++) {
+ if (i < itemsCount()) {
+ intervals[i].setVisibility(View.VISIBLE);
+ buildInterval(i);
+ } else if (i <= inflatedUntil){
+ intervals[i].setVisibility(View.GONE);
+ }
}
if (!(itemsCount() > 0 && secondFromMidnight(itemsCount() - 1) == 23 * ONEHOURINSECONDS)) {
- ImageView imageView = new ImageView(context);
- imageView.setImageResource(R.drawable.add);
- LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
- illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
- illp.gravity = Gravity.CENTER;
- layout.addView(imageView);
- imageView.setLayoutParams(illp);
- imageView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0);
- log();
- buildView();
- }
- });
+ finalAdd.setVisibility(View.VISIBLE);
+ } else {
+ finalAdd.setVisibility(View.GONE);
}
-
}
- public void fillSpinner(Spinner spinner, int secondsFromMidnight, int previous, int next) {
+ private View buildInterval(int i) {
+ SpinnerHelper timeSpinner = spinners[i];
+ View childview = intervals[i];
+ final NumberPicker editText1 = numberPickers1[i];
+ final NumberPicker editText2 = numberPickers2[i];
+
+
+ int previous = i == 0 ? -1 * ONEHOURINSECONDS : secondFromMidnight(i - 1);
+ int next = i == itemsCount() - 1 ? 24 * ONEHOURINSECONDS : secondFromMidnight(i + 1);
+ if (i == 0) next = ONEHOURINSECONDS;
+ fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
+
+ editText1.setParams(value1(i), 0.1d, 100d, step, formatter, false);
+ editText2.setParams(value2(i), 0.1d, 100d, step, formatter, false);
+
+ if (data2 == null) {
+ editText2.setVisibility(View.GONE);
+ }
+
+
+ if (itemsCount() == 1 || i == 0) {
+ removeButtons[i].setVisibility(View.INVISIBLE);
+ } else
+ removeButtons[i].setVisibility(View.VISIBLE);
+
+ if (itemsCount() >= 24 || secondFromMidnight(i) >= 82800) {
+ addButtons[i].setVisibility(View.INVISIBLE);
+ } else {
+ addButtons[i].setVisibility(View.VISIBLE);
+ }
+
+ return childview;
+ }
+
+ private void fillSpinner(final SpinnerHelper spinner, int secondsFromMidnight, int previous, int next) {
int posInList = 0;
ArrayList timeList = new ArrayList<>();
int pos = 0;
for (int t = previous + ONEHOURINSECONDS; t < next; t += ONEHOURINSECONDS) {
- timeList.add(DateUtil.timeString(DateUtil.toDate(t)));
+ timeList.add(DateUtil.timeStringFromSeconds(t));
if (secondsFromMidnight == t) posInList = pos;
pos++;
}
- ArrayAdapter adapter = new ArrayAdapter(context,
+ final ArrayAdapter adapter = new ArrayAdapter<>(context,
R.layout.spinner_centered, timeList);
spinner.setAdapter(adapter);
- spinner.setSelection(posInList, false);
+ final int finalPosInList = posInList;
+ new Handler().postDelayed(new Runnable() {
+ public void run() {
+ spinner.setSelection(finalPosInList, false);
+ adapter.notifyDataSetChanged();
+ }
+ }, 100);
}
- public void fillNumber(EditText edit, Double value) {
- if (value.equals(0d))
- edit.setText("");
- else
- edit.setText(formatter.format(value));
- }
-
- public int itemsCount() {
+ private int itemsCount() {
return data1.length();
}
- public int secondFromMidnight(int index) {
+ private int secondFromMidnight(int index) {
try {
JSONObject item = (JSONObject) data1.get(index);
if (item.has("timeAsSeconds")) {
- return item.getInt("timeAsSeconds");
+ int time = item.getInt("timeAsSeconds");
+ if (index == 0 && time != 0) {
+ // fix the bug, every array must start with 0
+ item.put("timeAsSeconds", 0);
+ time = 0;
+ }
+ return time;
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
@@ -258,7 +305,7 @@ public class TimeListEdit {
return 0;
}
- public double value1(int index) {
+ private double value1(int index) {
try {
JSONObject item = (JSONObject) data1.get(index);
if (item.has("value")) {
@@ -270,7 +317,7 @@ public class TimeListEdit {
return 0d;
}
- public double value2(int index) {
+ private double value2(int index) {
if (data2 != null) {
try {
JSONObject item = (JSONObject) data2.get(index);
@@ -284,7 +331,7 @@ public class TimeListEdit {
return 0d;
}
- public void editItem(int index, int timeAsSeconds, double value1, double value2) {
+ private void editItem(int index, int timeAsSeconds, double value1, double value2) {
try {
String time;
int hour = timeAsSeconds / 60 / 60;
@@ -303,14 +350,18 @@ public class TimeListEdit {
newObject2.put("value", value2);
data2.put(index, newObject2);
}
- if (save != null) save.run();
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
- public void addItem(int index, int timeAsSeconds, double value1, double value2) {
+ private void addItem(int index, int timeAsSeconds, double value1, double value2) {
+ if(itemsCount()>inflatedUntil) {
+ layout.removeView(finalAdd);
+ inflateRow(++inflatedUntil);
+ layout.addView(finalAdd);
+ }
try {
// shift data
for (int i = data1.length(); i > index; i--) {
@@ -320,24 +371,33 @@ public class TimeListEdit {
}
// add new object
editItem(index, timeAsSeconds, value1, value2);
- if (save != null) save.run();
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
- public void removeItem(int index) {
+ private void removeItem(int index) {
data1.remove(index);
if (data2 != null)
data2.remove(index);
+ }
+
+ private void log() {
+ if (log.isDebugEnabled()) {
+ for (int i = 0; i < data1.length(); i++) {
+ log.debug(i + ": @" + DateUtil.timeStringFromSeconds(secondFromMidnight(i)) + " " + value1(i) + (data2 != null ? " " + value2(i) : ""));
+ }
+ }
+ }
+
+ private void callSave() {
if (save != null) save.run();
}
- void log() {
- for (int i = 0; i < data1.length(); i++) {
- int pos = 0;
- log.debug(i + ": @" + DateUtil.timeString(DateUtil.toDate(secondFromMidnight(i))) + " " + value1(i) + (data2 != null ? " " + value2(i) : ""));
- }
+ public void updateLabel(String txt){
+ this.label = txt;
+ if(textlabel!=null)
+ textlabel.setText(txt);
}
}
diff --git a/app/src/main/jniLibs/arm64-v8a/libBleCommandUtil.so b/app/src/main/jniLibs/arm64-v8a/libBleCommandUtil.so
new file mode 100644
index 0000000000..69e283b5fe
Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libBleCommandUtil.so differ
diff --git a/app/src/main/jniLibs/armeabi-v7a/libBleCommandUtil.so b/app/src/main/jniLibs/armeabi-v7a/libBleCommandUtil.so
new file mode 100644
index 0000000000..0c717bc3e8
Binary files /dev/null and b/app/src/main/jniLibs/armeabi-v7a/libBleCommandUtil.so differ
diff --git a/app/src/main/jniLibs/armeabi/libBleCommandUtil.so b/app/src/main/jniLibs/armeabi/libBleCommandUtil.so
new file mode 100644
index 0000000000..a51a8c7d9a
Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libBleCommandUtil.so differ
diff --git a/app/src/main/jniLibs/mips/libBleCommandUtil.so b/app/src/main/jniLibs/mips/libBleCommandUtil.so
new file mode 100644
index 0000000000..fcff5eb6b2
Binary files /dev/null and b/app/src/main/jniLibs/mips/libBleCommandUtil.so differ
diff --git a/app/src/main/jniLibs/mips64/libBleCommandUtil.so b/app/src/main/jniLibs/mips64/libBleCommandUtil.so
new file mode 100644
index 0000000000..a8a292ea13
Binary files /dev/null and b/app/src/main/jniLibs/mips64/libBleCommandUtil.so differ
diff --git a/app/src/main/jniLibs/x86/libBleCommandUtil.so b/app/src/main/jniLibs/x86/libBleCommandUtil.so
new file mode 100644
index 0000000000..638a9def95
Binary files /dev/null and b/app/src/main/jniLibs/x86/libBleCommandUtil.so differ
diff --git a/app/src/main/jniLibs/x86_64/libBleCommandUtil.so b/app/src/main/jniLibs/x86_64/libBleCommandUtil.so
new file mode 100644
index 0000000000..94873d3732
Binary files /dev/null and b/app/src/main/jniLibs/x86_64/libBleCommandUtil.so differ
diff --git a/app/src/main/res/layout/actions_fill_dialog.xml b/app/src/main/res/layout/actions_fill_dialog.xml
index e6fb0b05ee..55e44f4bc7 100644
--- a/app/src/main/res/layout/actions_fill_dialog.xml
+++ b/app/src/main/res/layout/actions_fill_dialog.xml
@@ -6,51 +6,37 @@
android:orientation="vertical"
android:padding="10dp">
-
-
-
-
-
-
+ android:text="@string/treatments_newtreatment_insulinamount_label"
+ android:textAppearance="@android:style/TextAppearance.Material.Small"
+ android:textStyle="bold" />
-
+
+
+ android:layout_gravity="center_vertical"
+ android:gravity="left"
+ android:minWidth="45dp"
+ android:paddingLeft="5dp"
+ android:text="U"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/danar_fragment.xml b/app/src/main/res/layout/danar_fragment.xml
index 6456a1cbe2..29c9398a04 100644
--- a/app/src/main/res/layout/danar_fragment.xml
+++ b/app/src/main/res/layout/danar_fragment.xml
@@ -5,643 +5,729 @@
tools:context="info.nightscout.androidaps.plugins.PumpDanaR.DanaRFragment">
-
+ android:layout_height="match_parent">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:text="@string/danar_viewprofile" />
+
-
+
+
-
+
+
diff --git a/app/src/main/res/layout/danars_blescanner_activity.xml b/app/src/main/res/layout/danars_blescanner_activity.xml
new file mode 100644
index 0000000000..3a3eb78f5c
--- /dev/null
+++ b/app/src/main/res/layout/danars_blescanner_activity.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/danars_blescanner_item.xml b/app/src/main/res/layout/danars_blescanner_item.xml
new file mode 100644
index 0000000000..2c620b532f
--- /dev/null
+++ b/app/src/main/res/layout/danars_blescanner_item.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/danars_pairingprogressdialog.xml b/app/src/main/res/layout/danars_pairingprogressdialog.xml
new file mode 100644
index 0000000000..fc8c97836f
--- /dev/null
+++ b/app/src/main/res/layout/danars_pairingprogressdialog.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml
index 3773b43fbc..e64f7a14a1 100644
--- a/app/src/main/res/layout/localprofile_fragment.xml
+++ b/app/src/main/res/layout/localprofile_fragment.xml
@@ -17,12 +17,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/linearBlockBackground"
+ android:layout_marginLeft="10px"
android:text="@string/units"
android:textAppearance="?android:attr/textAppearanceMedium" />
-
+ android:gravity="center_horizontal"
+ android:orientation="horizontal"
+ android:paddingTop="5dp"
+ android:textAppearance="?android:attr/textAppearanceSmall">
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -93,7 +140,7 @@
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
- android:text="@string/send_to_pump"
+ android:text="@string/activate_profile"
android:textColor="@color/colorProfileSwitchButton" />
diff --git a/app/src/main/res/layout/nsprofile_fragment.xml b/app/src/main/res/layout/nsprofile_fragment.xml
new file mode 100644
index 0000000000..b1c88c41c1
--- /dev/null
+++ b/app/src/main/res/layout/nsprofile_fragment.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml
index a22d46906d..a07af9664d 100644
--- a/app/src/main/res/layout/overview_fragment.xml
+++ b/app/src/main/res/layout/overview_fragment.xml
@@ -17,7 +17,7 @@
-
+ android:minWidth="300dp"
+ android:orientation="vertical"
+ android:padding="10dp">
-
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/nsprofileviewer_fragment.xml b/app/src/main/res/layout/profileviewer_fragment.xml
similarity index 100%
rename from app/src/main/res/layout/nsprofileviewer_fragment.xml
rename to app/src/main/res/layout/profileviewer_fragment.xml
diff --git a/app/src/main/res/layout/simpleprofile_fragment.xml b/app/src/main/res/layout/simpleprofile_fragment.xml
index b7c3c3cac8..174f38f8bc 100644
--- a/app/src/main/res/layout/simpleprofile_fragment.xml
+++ b/app/src/main/res/layout/simpleprofile_fragment.xml
@@ -125,7 +125,7 @@
android:layout_weight="1"
android:paddingLeft="10dp"
android:paddingRight="10dp"
- android:text="@string/send_to_pump"
+ android:text="@string/activate_profile"
android:textColor="@color/colorProfileSwitchButton" />
diff --git a/app/src/main/res/layout/timelistedit_element.xml b/app/src/main/res/layout/timelistedit_element.xml
index b0588aea45..97fad65d38 100644
--- a/app/src/main/res/layout/timelistedit_element.xml
+++ b/app/src/main/res/layout/timelistedit_element.xml
@@ -8,28 +8,29 @@
android:textAppearance="?android:attr/textAppearanceSmall">
+ android:layout_gravity="center"
+ android:layout_marginRight="10dp"
+ android:minWidth="80dp" />
-
+ android:orientation="vertical">
-
+
+
+
+
@@ -23,56 +23,59 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:gravity="center_vertical|right"
- android:paddingLeft="10dp"
- android:paddingRight="5dp"
+ android:gravity="center_vertical|end"
+ android:paddingEnd="5dp"
+ android:paddingStart="10dp"
android:text="{fa-clock-o}" />
+
+
+
+
-
-
@@ -80,18 +83,16 @@
android:id="@+id/profileswitch_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingLeft="10dp"
- android:paddingRight="5dp"
+ android:paddingEnd="5dp"
+ android:paddingStart="10dp"
android:text="@string/overview_quickwizard_item_remove_button"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_orange_light" />
-
Бутон 3
% с който базовият профил ще бъде променен.
Точен брой часове, с които ще бъде изместен профила!
- ИЗПРАТИ КЪМ ПОМПАТА
- Единици:
+ Единици:
мг/дл
ммол/л
DIA:
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index 20a54298c2..beb7c370e4 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -340,7 +340,6 @@
Pumpa vypnuta
Znovu poslat všechny data
Opravdu resetovat všechny databáze
- POSLAT DO PUMPY
Cílový rozsah:
Čas v hodinách, o který bude bazál posunutý.
Jednotky:
@@ -448,7 +447,7 @@
Odpojuji
Nezobrazovat znovu
Provádím
- Načítám stav pumpy
+ Nahrávám stav pumpy
Pumpa pozastavena
Pumpa pozastavena. Klik pro obnovení stavu
Nastavuji extended bolus
@@ -629,4 +628,35 @@
NEPLATNÝ
Nizozemština
Švédština
+ trvání aktivity
+ cíl při aktivitě
+ % změna
+ Posun času
+ Nastavte bazální krok 0.01U/h
+ Prozatím žádné zařízení nenalezeno
+ Doplňování
+ Rychlost bolusu
+ DanaRS
+ Dana
+ Výchozí nastavení dočasných cílů
+ Trvání \"blížícího se jídla\"
+ Cíl pro \"blížící se jídlo\"
+ Prázdný zásobník
+ Nahrávám bolusy
+ Nahrávám prodloužené bolusy
+ Nahrávám nastavení pumpy
+ Nahrávám čas v pumpě
+ Nahrávám dočasné bazály
+ PÁROVÁNÍ
+ Spárováno
+ Vypršel časový limit pro párování
+ Párování pumpy
+ Zbývající inzulín
+ znovu použít
+ Vybraná pumpa
+ Sériové číslo
+ Čekání na spárování na pumpě
+ Nastavování dočasných cílů a vkládání ošetření na hodinkách Wear
+ Řízení z hodinek Wear
+ Model: %02X Protokol: %02X Kód: %02X
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index c8317565ee..c01c25b549 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -288,7 +288,6 @@
Niedrige Batterie
Pumpe ist beschäftigt
Pumpenfehler
- an Pumpe senden
Zielbereich:
Einheiten:
Falscher Pumpentreiber ausgewählt
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 18cfbe75a4..71e911402b 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -377,7 +377,6 @@
Apagando Bomba
Eliminar registro:
Enviar todos los datos
- ENVIAR A BOMBA
Media corta delta
Bolo:
Último BG:
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index d57e7d5876..e4ed325e18 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -330,7 +330,6 @@
Salva
Esci
Accettare il nuovo basale temp
- INVIARE ALLA POMPA
Impostare il nuovo bollo esteso
Impostazioni importate
Impostazioni aggiuntive bolus
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 5dce573231..a591ac5c27 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -351,7 +351,6 @@
버튼3
Percentage factor by which the base profile will be multiplied.
Time in hours by which the profile will be shifted round robin.
- SEND TO PUMP
Units:
mg/dl
mmol/l
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index e46d349236..eb6b45b33a 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -185,7 +185,6 @@
Veiligheid
VERZEND
Verzend calibratie %.1f naar xDrip?
- VERZEND NAAR POMP
Vergeet niet alle gegeten koolhydraten in te geven bij het activeren van de Autosens functie. Anders zullen BG wijzigingen door maaltijden foutief geïnterpreteerd worden!!
Gevoeligheid AAPS
Gevoeligheid Oref0
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 2964a144c1..1492740232 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -427,7 +427,6 @@
сохранить
ОТПРАВИТЬ
отправить калибровку %.1f на xdrip?
- ОТПРАВИТЬ НА ПОМПУ
принять новый врем базал:
установить новый расширенн болюс:
настройки импортированы
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index a4ef3e7b2e..03ac2aee36 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -413,7 +413,6 @@
inställningar importerade
Ställ in ny förlängd bolus:
Acceptera ny temp basal:
- SKICKA TILL PUMP
Skicka kalibrering %.1f till xDrip?
SKICKA
Spara
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index a564b68e80..efa2d31c4d 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -47,4 +47,16 @@
- @string/key_teenage
- @string/key_adult
+
+
+ - 12s 1U
+ - 30s 1U
+ - 60s 1U
+
+
+ - 0
+ - 1
+ - 2
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d92828ed99..b5f3037145 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -362,7 +362,6 @@
Button 3
Percentage factor by which the base profile will be multiplied.
Time in hours by which the profile will be shifted round robin.
- SEND TO PUMP
Units:
mg/dl
mmol/l
@@ -702,19 +701,50 @@
ACTIVATE PROFILE
Date
INVALID
- wizard_include_bg
- wizard_include_cob
- wizard_include_trend_bg
- wizard_include_bolus_iob
- wizard_include_basal_iob
+ Waiting for pairing on pump
+ Paring OK
+ Paring timed out
+ PAIRING
+ danars_paring_key_
+ danars_address
+ danars_name
+ No device found so far
+ Empty reservoir
+ Blood sugar measurement alert
+ Remaining insulin level
+ DanaRS
+ Dana
+ Selected pump
+ Pair new pump
+ Bolus speed
+ danars_bolusspeed
+ Set basal step to 0.01 U/h
+ Serial number
+ wizard_include_bg
+ wizard_include_cob
+ wizard_include_trend_bg
+ wizard_include_bolus_iob
+ wizard_include_basal_iob
+ Percentage
+ Time shift
Default Temp-Targets
eatingsoon duration
eatingsoon target
activity duration
activity target
- eatingsoon_duration
- eatingsoon_target
- activity_duration
- activity_target
+ eatingsoon_duration
+ eatingsoon_target
+ activity_duration
+ activity_target
+ Prime
+ Getting extended bolus status
+ Getting bolus status
+ Getting temporary basal status
+ Gettings pump settings
+ Getting pump time
+ reuse
+ Controls from Watch
+ Set Temp-Targets and enter Treatments from the watch.
+ Connection timed out
diff --git a/app/src/main/res/xml/pref_danar.xml b/app/src/main/res/xml/pref_danar.xml
index e57a211a16..51c5003ec9 100644
--- a/app/src/main/res/xml/pref_danar.xml
+++ b/app/src/main/res/xml/pref_danar.xml
@@ -8,20 +8,31 @@
android:dialogTitle="@string/danar_bt_name_title"
android:key="@string/key_danar_bt_name"
android:title="@string/danar_bt_name_title" />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_danarkorean.xml b/app/src/main/res/xml/pref_danarkorean.xml
new file mode 100644
index 0000000000..e57a211a16
--- /dev/null
+++ b/app/src/main/res/xml/pref_danarkorean.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_danars.xml b/app/src/main/res/xml/pref_danars.xml
new file mode 100644
index 0000000000..6513ba4290
--- /dev/null
+++ b/app/src/main/res/xml/pref_danars.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_danarv2.xml b/app/src/main/res/xml/pref_danarv2.xml
index 1029c43fb4..45906e8615 100644
--- a/app/src/main/res/xml/pref_danarv2.xml
+++ b/app/src/main/res/xml/pref_danarv2.xml
@@ -8,11 +8,19 @@
android:dialogTitle="@string/danar_bt_name_title"
android:key="@string/key_danar_bt_name"
android:title="@string/danar_bt_name_title" />
+
-
+ android:title="@string/danar_password_title">
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/pref_wear.xml b/app/src/main/res/xml/pref_wear.xml
index 4b80c0446d..3ccde55678 100644
--- a/app/src/main/res/xml/pref_wear.xml
+++ b/app/src/main/res/xml/pref_wear.xml
@@ -4,6 +4,12 @@
android:key="wearplugin"
android:title="@string/wear_settings">
+
+
-
+ AAPS
+ AAPS(Large)
+ AAPS(BigChart)
+ AAPS(NoChart)
+ AAPS(Circle)
+ AAPS
+ AAPS Settings
BolusActivity
Hello Round World!