Merge branch 'smb-rhino' into 'smb'

SMB Rhino

See merge request MilosKozak/AndroidAPS!365
This commit is contained in:
AdrianLxM 2017-10-23 22:34:30 +00:00
commit 337f31382f
197 changed files with 10473 additions and 2658 deletions

View file

@ -43,10 +43,16 @@ android {
applicationId "info.nightscout.androidaps"
minSdkVersion 21
targetSdkVersion 23
multiDexEnabled true
versionCode 1500
version "1.54-smb"
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') {

BIN
app/libs/rhino-1.7.7.2.jar Normal file

Binary file not shown.

View file

@ -17,6 +17,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -50,6 +51,13 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".plugins.PumpDanaRS.activities.BLEScanActivity">
<intent-filter>
<action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
<receiver
android:name=".receivers.DataReceiver"
@ -113,6 +121,10 @@
android:name=".plugins.PumpDanaRv2.services.DanaRv2ExecutionService"
android:enabled="true"
android:exported="false" />
<service
android:name=".plugins.PumpDanaRS.services.DanaRSService"
android:enabled="true"
android:exported="true"></service>
<service
android:name=".plugins.Wear.wearintegration.WatchUpdaterService"
android:exported="true">

View file

@ -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]);
}
};

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -53,6 +53,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;
@ -124,7 +126,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());
@ -149,7 +152,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());
@ -209,6 +212,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);
}

View file

@ -22,6 +22,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;
@ -71,6 +72,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());
@ -133,12 +136,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);
}
@ -163,12 +173,10 @@ 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);
}
}
StatuslinePlugin statuslinePlugin = MainApp.getSpecificPlugin(StatuslinePlugin.class);
if (statuslinePlugin != null && statuslinePlugin.isEnabled(PluginBase.GENERAL)) {

View file

@ -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<Double> basal_v = null; // oldest at index 0
JSONArray targetLow;
private LongSparseArray<Double> targetLow_v = null; // oldest at index 0
JSONArray targetHigh;
private LongSparseArray<Double> 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<Double> convertToSparseArray(JSONArray array) {
double multiplier = getMultiplier(array);
LongSparseArray<Double> 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<Double> 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<Double> 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<Double> 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) / 60;
DecimalFormat df = new DecimalFormat("00");
time = df.format(hour) + ":" + df.format(minutes);
return time;
}
private String getValuesList(LongSparseArray<Double> array, LongSparseArray<Double> 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");
for (Integer index = 0; index < array.size(); index++) {
retValue += format_HH_MM((int) array.keyAt(index));
retValue += " ";
retValue += format.format(o.getDouble("value"));
retValue += format.format(array.valueAt(index));
if (array2 != null) {
JSONObject o2 = array2.getJSONObject(index);
retValue += " - ";
retValue += format.format(o2.getDouble("value"));
retValue += format.format(array2.valueAt(index));
}
retValue += " " + units;
if (index + 1 < array.length())
if (index + 1 < array.size())
retValue += "\n";
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
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");
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 ret;
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
return new BasalValue[0];
}
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;
}
}

View file

@ -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;

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -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");

View file

@ -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);
@ -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:

View file

@ -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);

View file

@ -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 {
@ -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) {

View file

@ -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;

View file

@ -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,7 +712,7 @@ 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() {
@ -689,17 +723,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
if (ConfigBuilderPlugin.getActiveProfileInterface() instanceof CircadianPercentageProfilePlugin) {
CircadianPercentageProfilePlugin cpp = (CircadianPercentageProfilePlugin) ConfigBuilderPlugin.getActiveProfileInterface();
profileSwitch.isCPP = true;
profileSwitch.timeshift = cpp.timeshift;
profileSwitch.percentage = cpp.percentage;
}
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");
@ -709,4 +740,37 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
});
}
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
sHandler.post(new Runnable() {
@Override
public void run() {
ProfileSwitch profileSwitch = MainApp.getConfigBuilder().getProfileSwitchFromHistory(System.currentTimeMillis());
if (profileSwitch != null) {
profileSwitch = new ProfileSwitch();
profileSwitch.date = System.currentTimeMillis();
profileSwitch.source = Source.USER;
profileSwitch.profileName = MainApp.getConfigBuilder().getProfileName(System.currentTimeMillis(), false);
profileSwitch.profileJson = MainApp.getConfigBuilder().getProfile().getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.percentage = percentage;
MainApp.getConfigBuilder().addToHistoryProfileSwitch(profileSwitch);
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"));
} else {
log.error("No profile switch existing");
}
}
});
}
}

View file

@ -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;
}
}

View file

@ -578,7 +578,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();
@ -961,10 +961,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)
@ -984,7 +988,7 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain
}
public String getProfileUnits() {
return activeProfile.getUnits();
return getProfile().getUnits();
}
public Profile getProfile(long time) {
@ -1020,7 +1024,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);
}

View file

@ -46,23 +46,29 @@ public class BroadcastSgvs {
}
public static void handleNewSgv(JSONArray sgvs, Context context, boolean isDelta) {
List<JSONArray> splitted = BroadcastTreatment.splitArray(sgvs);
for (JSONArray part : splitted) {
Bundle bundle = new Bundle();
bundle.putString("sgvs", sgvs.toString());
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);
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
}
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) {
bundle = new Bundle();
bundle.putString("sgvs", sgvs.toString());
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);
}
}
}
}

View file

@ -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());
}

View file

@ -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));
//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();
}
storedGlucoseStatus = mGlucoseStatus.toString();
storedIobData = mIobData.toString();
storedCurrentTemp = mCurrentTemp.toString();
storedProfile = mProfile.toString();
storedMeal_data = mMealData.toString();
return determineBasalResultAMA;
return result;
}
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();
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];
}
mV8rt.release();
});
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 {

View file

@ -4,6 +4,7 @@ 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;
@ -17,36 +18,35 @@ public class DetermineBasalResultAMA extends APSResult {
public double eventualBG;
public double snoozeBG;
public DetermineBasalResultAMA(V8Object result, JSONObject j) {
public DetermineBasalResultAMA(NativeObject result, JSONObject j) {
this();
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() {

View file

@ -55,7 +55,7 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
AutosensResult lastAutosensResult = null;
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
private boolean fragmentVisible = false;
@Override
public String getName() {
@ -222,11 +222,16 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
Profiler.log(log, "AMA data gathering", start);
start = new Date();
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 {

View file

@ -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));
//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;
}
}

View file

@ -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;
@ -21,38 +17,37 @@ public class DetermineBasalResultMA extends APSResult {
public double snoozeBG;
public String mealAssist;
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() {

View file

@ -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;
}
}

View file

@ -53,7 +53,7 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
DetermineBasalResultMA lastAPSResult = null;
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
private boolean fragmentVisible = false;
@Override
public String getName() {
@ -211,12 +211,16 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, 5)) return;
start = new Date();
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;
}

View file

@ -5,12 +5,23 @@ 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 +35,8 @@ 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.OpenAPSAMA.DetermineBasalResultAMA;
import info.nightscout.androidaps.plugins.OpenAPSMA.LoggerCallback;
import info.nightscout.utils.SP;
public class DetermineBasalAdapterSMBJS {
@ -31,26 +44,17 @@ public class DetermineBasalAdapterSMBJS {
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 final String PARAM_reservoirData = "reservoirData";
private final String PARAM_microBolusAllowed = "microBolusAllowed";
private JSONObject mProfile;
private JSONObject mGlucoseStatus;
private JSONArray mIobData;
private JSONObject mMealData;
private JSONObject mCurrentTemp;
private JSONObject mAutosensData = null;
private boolean mMicrobolusAllowed;
private String storedCurrentTemp = null;
private String storedIobData = null;
private String storedGlucoseStatus = null;
private String storedProfile = null;
private String storedMeal_data = null;
@ -64,55 +68,108 @@ public class DetermineBasalAdapterSMBJS {
*/
public DetermineBasalAdapterSMBJS(ScriptReader scriptReader) throws IOException {
mV8rt = V8.createV8Runtime();
mScriptReader = scriptReader;
initLogCallback();
initProcessExitCallback();
initModuleParent();
loadScript();
}
public DetermineBasalResultSMB invoke() {
log.debug(">>> Invoking detemine_basal_oref1 <<<");
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(">>> Invoking detemine_basal <<<");
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"));
log.debug("Reservoir data: " + "undefined");
log.debug("MicroBolusAllowed: " + (storedMicroBolusAllowed = mV8rt.executeStringScript("JSON.stringify(" + PARAM_microBolusAllowed + ");")));
log.debug("MicroBolusAllowed: " + (storedMicroBolusAllowed = "" + mMicrobolusAllowed));
mV8rt.executeVoidScript(
"var rT = determine_basal(" +
PARAM_glucoseStatus + ", " +
PARAM_currentTemp + ", " +
PARAM_iobData + ", " +
PARAM_profile + ", " +
PARAM_autosens_data + ", " +
PARAM_meal_data + ", " +
"tempBasalFunctions" + ", " +
PARAM_microBolusAllowed + ", " +
PARAM_reservoirData +
");");
DetermineBasalResultSMB determineBasalResultSMB = 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);
DetermineBasalResultSMB result = null;
try {
result = new DetermineBasalResultSMB(new JSONObject(ret));
//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("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null);
rhino.evaluateString(scope, readFile("OpenAPSSMB/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,
new Boolean(mMicrobolusAllowed),
makeParam(null,rhino,scope) // reservoir data as undefined
};
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 {
determineBasalResultSMB = new DetermineBasalResultSMB(new JSONObject(result));
} catch (JSONException e) {
e.printStackTrace();
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 determineBasalResultSMB;
}
String getGlucoseStatusParam() {
@ -147,60 +204,6 @@ public class DetermineBasalAdapterSMBJS {
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("OpenAPSSMB/basal-set-temp.js"), "OpenAPSSMB/basal-set-temp.js ", 0);
mV8rt.executeVoidScript("var tempBasalFunctions = module.exports;");
mV8rt.executeVoidScript(
readFile("OpenAPSSMB/determine-basal.js"),
"OpenAPSSMB/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,
@ -214,102 +217,104 @@ public class DetermineBasalAdapterSMBJS {
double autosensDataRatio,
boolean tempTargetSet,
boolean microBolusAllowed
) {
) throws JSONException {
String units = profile.getUnits();
mProfile = new V8Object(mV8rt);
mProfile.add("max_iob", maxIob);
mProfile.add("dia", profile.getDia());
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.add("enableSMB_with_bolus", SP.getBoolean(R.string.key_use_smb, false));
mProfile.add("enableSMB_with_COB", SP.getBoolean(R.string.key_use_smb, false));
mProfile.add("enableSMB_with_temptarget", SP.getBoolean(R.string.key_use_smb, false));
mProfile.add("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
mProfile.add("adv_target_adjustments", true); // lower target automatically when BG and eventualBG are high
mProfile = new JSONObject();;
mProfile.put("max_iob", maxIob);
mProfile.put("dia", profile.getDia());
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));
mProfile.put("enableSMB_with_bolus", SP.getBoolean(R.string.key_use_smb, false));
mProfile.put("enableSMB_with_COB", SP.getBoolean(R.string.key_use_smb, false));
mProfile.put("enableSMB_with_temptarget", SP.getBoolean(R.string.key_use_smb, false));
mProfile.put("enableUAM", SP.getBoolean(R.string.key_use_uam, false));
mProfile.put("adv_target_adjustments", true); // lower target automatically when BG and eventualBG are high
// create maxCOB and default it to 120 because that's the most a typical body can absorb over 4 hours.
// (If someone enters more carbs or stacks more; OpenAPS will just truncate dosing based on 120.
// Essentially, this just limits AMA as a safety cap against weird COB calculations)
mProfile.add("maxCOB", 120);
mProfile.add("autotune_isf_adjustmentFraction", 0.5); // keep autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 1.0 allows full adjustment, 0 is no adjustment from pump ISF.
mProfile.add("remainingCarbsFraction", 1.0d); // fraction of carbs we'll assume will absorb over 4h if we don't yet see carb absorption
mProfile.add("remainingCarbsCap", 90); // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption
mV8rt.add(PARAM_profile, mProfile);
mProfile.put("maxCOB", 120);
mProfile.put("autotune_isf_adjustmentFraction", 0.5); // keep autotune ISF closer to pump ISF via a weighted average of fullNewISF and pumpISF. 1.0 allows full adjustment, 0 is no adjustment from pump ISF.
mProfile.put("remainingCarbsFraction", 1.0d); // fraction of carbs we'll assume will absorb over 4h if we don't yet see carb absorption
mProfile.put("remainingCarbsCap", 90); // max carbs we'll assume will absorb over 4h if we don't yet see carb absorption
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);
mMealData.add("minDeviationSlope", mealData.minDeviationSlope);
mMealData.add("lastBolusTime", mealData.lastBolusTime);
mV8rt.add(PARAM_meal_data, mMealData);
mMealData = new JSONObject();;
mMealData.put("carbs", mealData.carbs);
mMealData.put("boluses", mealData.boluses);
mMealData.put("mealCOB", mealData.mealCOB);
mMealData.put("minDeviationSlope", mealData.minDeviationSlope);
mMealData.put("lastBolusTime", mealData.lastBolusTime);
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;
}
mV8rt.addUndefined(PARAM_reservoirData);
mV8rt.add(PARAM_microBolusAllowed, microBolusAllowed);
mMicrobolusAllowed = microBolusAllowed;
}
public Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) {
public void release() {
mProfile.release();
mCurrentTemp.release();
mIobData.release();
mMealData.release();
mGlucoseStatus.release();
if (mAutosensData != null) {
mAutosensData.release();
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];
}
mV8rt.release();
});
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 {

View file

@ -224,11 +224,16 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
Profiler.log(log, "AMA data gathering", start);
start = new Date();
try {
determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, pump, iobArray, glucoseStatus, mealData,
lastAutosensResult.ratio, //autosensDataRatio
isTempTarget,
true //microBolusAllowed
);
} catch (JSONException e) {
log.error(e.getMessage());
return;
}
DetermineBasalResultSMB determineBasalResultSMB = determineBasalAdapterSMBJS.invoke();
@ -245,9 +250,6 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
}
determineBasalResultSMB.iob = iobArray[0];
determineBasalAdapterSMBJS.release();
Date now = new Date();
try {

View file

@ -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;
}

View file

@ -32,6 +32,7 @@ import com.squareup.otto.Subscribe;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.javascript.tools.debugger.Main;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -344,7 +345,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);
}
@ -401,15 +402,11 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
ArrayList<CharSequence> profileList;
profileList = profileStore.getProfileList();
profileList.add(0, MainApp.sResources.getString(R.string.active));
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(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);
}
String units = profile.getUnits();
bgUnits.setText(units);
@ -420,15 +417,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);
@ -457,7 +448,11 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
if (profileSpinner == null || profileSpinner.getSelectedItem() == null)
return; // not initialized yet
String selectedAlternativeProfile = profileSpinner.getSelectedItem().toString();
Profile specificProfile = profile.getSpecificProfile(selectedAlternativeProfile);
Profile specificProfile;
if (selectedAlternativeProfile.equals(MainApp.sResources.getString(R.string.active)))
specificProfile = MainApp.getConfigBuilder().getProfile();
else
specificProfile = profile.getSpecificProfile(selectedAlternativeProfile);
// Entered values
Double c_bg = SafeParse.stringToDouble(editBg.getText());
@ -465,19 +460,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;
}

View file

@ -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;

View file

@ -119,6 +119,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;
@ -349,6 +350,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v == apsModeView) {
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
if (activeloop == null)
return;
@ -370,6 +372,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
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));
}
}
@Override
@ -553,6 +560,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);
@ -737,6 +754,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
MainApp.bus().unregister(this);
sLoopHandler.removeCallbacksAndMessages(null);
unregisterForContextMenu(apsModeView);
unregisterForContextMenu(activeProfileView);
}
@Override
@ -752,6 +770,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
};
sLoopHandler.postDelayed(sRefreshLoop, 60 * 1000L);
registerForContextMenu(apsModeView);
registerForContextMenu(activeProfileView);
updateGUI("onResume");
}
@ -1087,27 +1106,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");

View file

@ -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);
}
}

View file

@ -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;
@ -36,7 +38,7 @@ public class CircadianPercentageProfilePlugin implements PluginBase, ProfileInte
private static Logger log = LoggerFactory.getLogger(CircadianPercentageProfilePlugin.class);
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
private boolean fragmentVisible = false;
private static ProfileStore convertedProfile = null;
private static String convertedProfileName = null;
@ -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();

View file

@ -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,21 +54,45 @@ public class LocalProfileFragment extends SubscriberFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
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 = (EditText) layout.findViewById(R.id.localprofile_dia);
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, 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);
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();
@ -78,7 +104,6 @@ public class LocalProfileFragment extends SubscriberFragment {
mgdlView.setChecked(localProfilePlugin.mgdl);
mmolView.setChecked(localProfilePlugin.mmol);
diaView.setText(localProfilePlugin.dia.toString());
mgdlView.setOnClickListener(new View.OnClickListener() {
@Override
@ -103,37 +128,27 @@ public class LocalProfileFragment 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");
}
});
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;
} catch (Exception e) {
log.error("Unhandled exception: ", e);
Crashlytics.logException(e);
}
return null;
}
@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);
}
}

View file

@ -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 boolean fragmentVisible = false;
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 ";
}
}

View file

@ -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<CharSequence> profileList = profileStore.getProfileList();
ArrayAdapter<CharSequence> 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("");
}
}

View file

@ -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);
}
}

View file

@ -33,7 +33,7 @@ public class SimpleProfilePlugin implements PluginBase, ProfileInterface {
}
private boolean fragmentEnabled = false;
private boolean fragmentVisible = true;
private boolean fragmentVisible = false;
private static ProfileStore convertedProfile = null;

View file

@ -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);
}
});

View file

@ -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() {

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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)));
}

View file

@ -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;

View file

@ -18,6 +18,7 @@ public class MessageHashTable {
messages = new HashMap<Integer, MessageBase>();
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

View file

@ -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);
}
}
}

View file

@ -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));

View file

@ -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);
}
}
}

View file

@ -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);
}

View file

@ -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() {

View file

@ -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);
}

View file

@ -0,0 +1,840 @@
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.DecimalFormatter;
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 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 synchronized 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 synchronized 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 synchronized 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 synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) {
// Recheck pump status if older than 30 min
if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
connect("setTempBasalAbsolute old data");
}
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 synchronized 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 synchronized PumpEnactResult setHighTempBasalPercent(Integer percent) {
PumpEnactResult result = new PumpEnactResult();
connectIfNotConnected("hightempbasal");
boolean connectionOK = danaRSService.highTempBasal(percent);
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
result.enacted = true;
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 synchronized 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 synchronized 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 synchronized 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) {
String ret = "";
if (pump.lastConnection.getTime() != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection.getTime();
int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " minago\n";
}
if (pump.lastBolusTime.getTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.lastBolusAmount) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.lastBolusTime) + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryRealTempBasalInProgress()) {
ret += "Temp: " + MainApp.getConfigBuilder().getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull() + "\n";
}
if (MainApp.getConfigBuilder().isInHistoryExtendedBoluslInProgress()) {
ret += "Extended: " + MainApp.getConfigBuilder().getExtendedBolusFromHistory(System.currentTimeMillis()).toString() + "\n";
}
if (!veryShort) {
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n";
}
ret += "IOB: " + pump.iob + "U\n";
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n";
ret += "Batt: " + pump.batteryRemaining + "\n";
return ret;
}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return false;
}
}

View file

@ -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<BluetoothDeviceItem> 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();
}
}

View file

@ -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");
}
}

View file

@ -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();
}
}

View file

@ -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<Integer, DanaRS_Packet> 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();
}
}
}

View file

@ -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;
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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);
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

View file

@ -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";
}
}

Some files were not shown because too many files have changed in this diff Show more