Merge pull request #15 from MilosKozak/startupwizard

Startupwizard
This commit is contained in:
Roumen Georgiev 2018-04-23 11:56:45 +03:00 committed by GitHub
commit daafe9c548
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
84 changed files with 2285 additions and 929 deletions

View file

@ -49,8 +49,8 @@ def generateGitBuild = { ->
return stringBuilder.toString() return stringBuilder.toString()
} }
tasks.matching {it instanceof Test}.all { tasks.matching { it instanceof Test }.all {
testLogging.events = ["failed", "skipped"] testLogging.events = ["failed", "skipped", "started"]
testLogging.exceptionFormat = "full" testLogging.exceptionFormat = "full"
} }
@ -89,7 +89,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
debug { debug {
testCoverageEnabled (project.hasProperty('coverage') ? true : false) testCoverageEnabled(project.hasProperty('coverage') ? true : false)
} }
} }
productFlavors { productFlavors {
@ -156,7 +156,7 @@ android {
unitTests.returnDefaultValues = true unitTests.returnDefaultValues = true
unitTests.includeAndroidResources = true unitTests.includeAndroidResources = true
} }
} }
allprojects { allprojects {
repositories { repositories {
@ -172,6 +172,7 @@ configurations {
} }
dependencies { dependencies {
implementation 'com.android.support:support-v4:27.1.1'
wearApp project(':wear') wearApp project(':wear')
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
@ -242,7 +243,7 @@ dependencies {
} }
task unzip(type: Copy) { task unzip(type: Copy) {
def zipPath = configurations.libs.find {it.name.startsWith("danars") } def zipPath = configurations.libs.find { it.name.startsWith("danars") }
def zipFile = file(zipPath) def zipFile = file(zipPath)
def outputDir = file("${buildDir}/unpacked/dist") def outputDir = file("${buildDir}/unpacked/dist")
@ -263,4 +264,4 @@ task full_clean(type: Delete) {
} }
clean.dependsOn full_clean clean.dependsOn full_clean
preBuild.dependsOn copyLibs preBuild.dependsOn copyLibs

View file

@ -51,12 +51,14 @@
<activity android:name=".plugins.Overview.activities.QuickWizardListActivity"> <activity android:name=".plugins.Overview.activities.QuickWizardListActivity">
<intent-filter> <intent-filter>
<action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" /> <action android:name="info.nightscout.androidaps.plugins.Overview.activities.QuickWizardListActivity" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".plugins.PumpDanaRS.activities.BLEScanActivity"> <activity android:name=".plugins.PumpDanaRS.activities.BLEScanActivity">
<intent-filter> <intent-filter>
<action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" /> <action android:name="info.nightscout.androidaps.plugins.PumpDanaRS.activities.BLEScanActivity" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
</activity> </activity>
@ -68,6 +70,7 @@
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<!-- Receive new SMS messages --> <!-- Receive new SMS messages -->
<action android:name="android.provider.Telephony.SMS_RECEIVED" /> <action android:name="android.provider.Telephony.SMS_RECEIVED" />
<!-- Receiver from xDrip --> <!-- Receiver from xDrip -->
@ -130,7 +133,7 @@
<service <service
android:name=".plugins.PumpDanaRS.services.DanaRSService" android:name=".plugins.PumpDanaRS.services.DanaRSService"
android:enabled="true" android:enabled="true"
android:exported="true"></service> android:exported="true" />
<service <service
android:name=".plugins.Wear.wearintegration.WatchUpdaterService" android:name=".plugins.Wear.wearintegration.WatchUpdaterService"
android:exported="true"> android:exported="true">
@ -148,12 +151,17 @@
android:exported="true" /> android:exported="true" />
<service <service
android:name=".plugins.Overview.notifications.DismissNotificationService" android:name=".plugins.Overview.notifications.DismissNotificationService"
android:exported="false"></service> android:exported="false" />
<meta-data <meta-data
android:name="io.fabric.ApiKey" android:name="io.fabric.ApiKey"
android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" /> android:value="59d462666c664c57b29e1d79ea123e01f8057cfa" />
<activity
android:name=".startupwizard.SetupWizardActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/title_activity_setup_wizard"
android:theme="@style/FullscreenTheme"></activity>
</application> </application>
</manifest> </manifest>

View file

@ -37,6 +37,7 @@ public class Config {
public static final boolean logCongigBuilderActions = true; public static final boolean logCongigBuilderActions = true;
public static final boolean logAutosensData = false; public static final boolean logAutosensData = false;
public static final boolean logEvents = false; public static final boolean logEvents = false;
public static final boolean logProfile = false;
// DanaR specific // DanaR specific
public static final boolean logDanaBTComm = true; public static final boolean logDanaBTComm = true;

View file

@ -49,6 +49,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Food.FoodPlugin; import info.nightscout.androidaps.plugins.Food.FoodPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock; import info.nightscout.androidaps.plugins.Overview.events.EventSetWakeLock;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.startupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.SlidingTabLayout; import info.nightscout.androidaps.tabs.SlidingTabLayout;
import info.nightscout.androidaps.tabs.TabPageAdapter; import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.utils.ImportExportPrefs; import info.nightscout.utils.ImportExportPrefs;
@ -368,6 +369,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.nav_historybrowser: case R.id.nav_historybrowser:
startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class)); startActivity(new Intent(v.getContext(), HistoryBrowseActivity.class));
break; break;
case R.id.nav_setupwizard:
startActivity(new Intent(v.getContext(), SetupWizardActivity.class));
break;
case R.id.nav_resetdb: case R.id.nav_resetdb:
new AlertDialog.Builder(v.getContext()) new AlertDialog.Builder(v.getContext())
.setTitle(R.string.nav_resetdb) .setTitle(R.string.nav_resetdb)

View file

@ -197,7 +197,8 @@ public class DataService extends IntentService {
bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME); bgReading.direction = bundle.getString(Intents.EXTRA_BG_SLOPE_NAME);
bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP); bgReading.date = bundle.getLong(Intents.EXTRA_TIMESTAMP);
bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW); bgReading.raw = bundle.getDouble(Intents.EXTRA_RAW);
String source = bundle.getString(Intents.XDRIP_DATA_SOURCE_DESCRIPTION, "no Source specified");
SourceXdripPlugin.getPlugin().setSource(source);
MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP"); MainApp.getDbHelper().createIfNotExists(bgReading, "XDRIP");
} }

View file

@ -37,6 +37,8 @@ public interface Intents {
String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery"; String EXTRA_SENSOR_BATTERY = "com.eveningoutpost.dexdrip.Extras.SensorBattery";
String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time"; String EXTRA_TIMESTAMP = "com.eveningoutpost.dexdrip.Extras.Time";
String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw"; String EXTRA_RAW = "com.eveningoutpost.dexdrip.Extras.Raw";
String XDRIP_DATA_SOURCE_DESCRIPTION = "com.eveningoutpost.dexdrip.Extras.SourceDesc";
String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData"; String ACTION_NEW_BG_ESTIMATE_NO_DATA = "com.eveningoutpost.dexdrip.BgEstimateNoData";

View file

@ -30,6 +30,7 @@ public class DetailedBolusInfo {
public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment) public long pumpId = 0; // id of record if comming from pump history (not a newly created treatment)
public boolean isSMB = false; // is a Super-MicroBolus public boolean isSMB = false; // is a Super-MicroBolus
public long deliverAt = 0; // SMB should be delivered within 1 min from this time public long deliverAt = 0; // SMB should be delivered within 1 min from this time
public String notes = null;
public DetailedBolusInfo copy() { public DetailedBolusInfo copy() {
DetailedBolusInfo n = new DetailedBolusInfo(); DetailedBolusInfo n = new DetailedBolusInfo();
@ -47,6 +48,7 @@ public class DetailedBolusInfo {
n.pumpId = pumpId; n.pumpId = pumpId;
n.isSMB = isSMB; n.isSMB = isSMB;
n.deliverAt = deliverAt; n.deliverAt = deliverAt;
n.notes = notes;
return n; return n;
} }

View file

@ -12,6 +12,7 @@ import java.text.DecimalFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.TimeZone; import java.util.TimeZone;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
@ -275,7 +276,7 @@ public class Profile {
Integer getShitfTimeSecs(Integer originalTime) { Integer getShitfTimeSecs(Integer originalTime) {
Integer shiftedTime = originalTime + timeshift * 60 * 60; Integer shiftedTime = originalTime + timeshift * 60 * 60;
shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 60 * 60); shiftedTime = (shiftedTime + 24 * 60 * 60) % (24 * 60 * 60);
if (timeshift != 0) if (timeshift != 0 && Config.logProfile)
log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime); log.debug("(Sec) Original time: " + originalTime + " ShiftedTime: " + shiftedTime);
return shiftedTime; return shiftedTime;
} }

View file

@ -11,7 +11,6 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
@ -119,8 +118,8 @@ public class QuickWizardEntry {
if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) { if (useSuperBolus() == YES && SP.getBoolean(R.string.key_usesuperbolus, false)) {
superBolus = true; superBolus = true;
} }
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) if (loopPlugin.isEnabled(loopPlugin.getType()) && loopPlugin.isSuperBolus())
superBolus = false; superBolus = false;
// Trend // Trend

View file

@ -28,6 +28,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
@ -45,6 +46,7 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistor
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes; import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.PercentageSplitter; import info.nightscout.utils.PercentageSplitter;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
@ -662,7 +664,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
public void createTemptargetFromJsonIfNotExists(JSONObject trJson) { public void createTemptargetFromJsonIfNotExists(JSONObject trJson) {
try { try {
String units = MainApp.getConfigBuilder().getProfileUnits(); String units = JsonHelper.safeGetString(trJson, "units", MainApp.getConfigBuilder().getProfileUnits());
TempTarget tempTarget = new TempTarget() TempTarget tempTarget = new TempTarget()
.date(trJson.getLong("mills")) .date(trJson.getLong("mills"))
.duration(trJson.getInt("duration")) .duration(trJson.getInt("duration"))

View file

@ -55,6 +55,7 @@ public interface TreatmentsInterface {
TempTarget getTempTargetFromHistory(); TempTarget getTempTargetFromHistory();
TempTarget getTempTargetFromHistory(long time); TempTarget getTempTargetFromHistory(long time);
Intervals<TempTarget> getTempTargetsFromHistory(); Intervals<TempTarget> getTempTargetsFromHistory();
void addToHistoryTempTarget(TempTarget tempTarget);
ProfileSwitch getProfileSwitchFromHistory(long time); ProfileSwitch getProfileSwitchFromHistory(long time);
ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory(); ProfileIntervals<ProfileSwitch> getProfileSwitchesFromHistory();

View file

@ -5,7 +5,9 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.Html; import android.text.Html;
import android.text.TextWatcher;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -14,6 +16,8 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
@ -21,8 +25,6 @@ import com.google.common.base.Joiner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Constants;
import java.text.DecimalFormat;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -41,19 +43,45 @@ import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils;
import static info.nightscout.utils.DateUtil.now;
public class FillDialog extends DialogFragment implements OnClickListener { public class FillDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(FillDialog.class); private static Logger log = LoggerFactory.getLogger(FillDialog.class);
private CheckBox pumpSiteChangeCheckbox;
private CheckBox insulinCartridgeChangeCheckbox;
private NumberPicker editInsulin;
double amount1 = 0d; double amount1 = 0d;
double amount2 = 0d; double amount2 = 0d;
double amount3 = 0d; double amount3 = 0d;
NumberPicker editInsulin; private EditText notesEdit;
CheckBox pumpSiteChangeCheckbox;
CheckBox insulinCartridgeChangeCheckbox;
public FillDialog() { final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
validateInputs();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private void validateInputs() {
int time = editInsulin.getValue().intValue();
if (Math.abs(time) > 12 * 60) {
editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
} }
@Override @Override
@ -67,45 +95,47 @@ public class FillDialog extends DialogFragment implements OnClickListener {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
pumpSiteChangeCheckbox = view.findViewById(R.id.catheter_change); pumpSiteChangeCheckbox = view.findViewById(R.id.fill_catheter_change);
insulinCartridgeChangeCheckbox = view.findViewById(R.id.cartridge_change); insulinCartridgeChangeCheckbox = view.findViewById(R.id.fill_cartridge_change);
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep; double bolusstep = ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep;
editInsulin = view.findViewById(R.id.treatments_newtreatment_insulinamount); editInsulin = view.findViewById(R.id.fill_insulinamount);
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false); editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
//setup preset buttons
Button button1 = (Button) view.findViewById(R.id.fill_preset_button1);
Button button2 = (Button) view.findViewById(R.id.fill_preset_button2);
Button button3 = (Button) view.findViewById(R.id.fill_preset_button3);
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
amount1 = SP.getDouble("fill_button1", 0.3); amount1 = SP.getDouble("fill_button1", 0.3);
amount2 = SP.getDouble("fill_button2", 0d);
amount3 = SP.getDouble("fill_button3", 0d);
if (amount1 > 0) { if (amount1 > 0) {
button1.setVisibility(View.VISIBLE); preset1Button.setVisibility(View.VISIBLE);
button1.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U"); preset1Button.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U");
button1.setOnClickListener(this); preset1Button.setOnClickListener(this);
} else { } else {
button1.setVisibility(View.GONE); preset1Button.setVisibility(View.GONE);
} }
Button preset2Button = view.findViewById(R.id.fill_preset_button2);
amount2 = SP.getDouble("fill_button2", 0d);
if (amount2 > 0) { if (amount2 > 0) {
button2.setVisibility(View.VISIBLE); preset2Button.setVisibility(View.VISIBLE);
button2.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U"); preset2Button.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U");
button2.setOnClickListener(this); preset2Button.setOnClickListener(this);
} else { } else {
button2.setVisibility(View.GONE); preset2Button.setVisibility(View.GONE);
} }
Button preset3Button = view.findViewById(R.id.fill_preset_button3);
amount3 = SP.getDouble("fill_button3", 0d);
if (amount3 > 0) { if (amount3 > 0) {
button3.setVisibility(View.VISIBLE); preset3Button.setVisibility(View.VISIBLE);
button3.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U"); preset3Button.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U");
button3.setOnClickListener(this); preset3Button.setOnClickListener(this);
} else { } else {
button3.setVisibility(View.GONE); preset3Button.setVisibility(View.GONE);
} }
LinearLayout notesLayout = view.findViewById(R.id.fill_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = view.findViewById(R.id.fill_notes);
setCancelable(true); setCancelable(true);
getDialog().setCanceledOnTouchOutside(false); getDialog().setCanceledOnTouchOutside(false);
return view; return view;
@ -154,42 +184,50 @@ public class FillDialog extends DialogFragment implements OnClickListener {
if (insulinCartridgeChangeCheckbox.isChecked()) if (insulinCartridgeChangeCheckbox.isChecked())
confirmMessage.add("" + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + getString(R.string.record_insulin_cartridge_change) + "</font>"); confirmMessage.add("" + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + getString(R.string.record_insulin_cartridge_change) + "</font>");
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
confirmMessage.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
}
final Double finalInsulinAfterConstraints = insulinAfterConstraints; final Double finalInsulinAfterConstraints = insulinAfterConstraints;
final Context context = getContext(); final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
if (confirmMessage.isEmpty())
confirmMessage.add(MainApp.gs(R.string.no_action_selected));
builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(confirmMessage))); if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) {
builder.setPositiveButton(getString(R.string.primefill), (dialog, id) -> { builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(confirmMessage)));
if (finalInsulinAfterConstraints > 0) { builder.setPositiveButton(getString(R.string.primefill), (dialog, id) -> {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); if (finalInsulinAfterConstraints > 0) {
detailedBolusInfo.insulin = finalInsulinAfterConstraints; DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.context = context; detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.context = context;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) detailedBolusInfo.source = Source.USER;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
@Override detailedBolusInfo.notes = notes;
public void run() { ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
if (!result.success) { @Override
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); public void run() {
i.putExtra("soundid", R.raw.boluserror); if (!result.success) {
i.putExtra("status", result.comment); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror)); i.putExtra("soundid", R.raw.boluserror);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra("status", result.comment);
MainApp.instance().startActivity(i); i.putExtra("title", MainApp.sResources.getString(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
} }
} });
}); FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill"));
FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill")); }
} if (pumpSiteChangeCheckbox.isChecked())
long now = System.currentTimeMillis(); NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes);
if (pumpSiteChangeCheckbox.isChecked()) NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now); if (insulinCartridgeChangeCheckbox.isChecked())
if (insulinCartridgeChangeCheckbox.isChecked()) NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now + 1000); NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes);
}); });
} else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
}
builder.setNegativeButton(getString(R.string.cancel), null); builder.setNegativeButton(getString(R.string.cancel), null);
builder.show(); builder.show();
dismiss(); dismiss();

View file

@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.Careportal.Dialogs;
import android.app.Activity; import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -15,7 +14,6 @@ import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioButton; import android.widget.RadioButton;
@ -23,6 +21,7 @@ import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.google.common.collect.Lists;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog; import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout; import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
@ -52,8 +51,10 @@ import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow; import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DefaultValueHelper;
import info.nightscout.utils.FabricPrivacy; import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.HardLimits; import info.nightscout.utils.HardLimits;
import info.nightscout.utils.JsonHelper;
import info.nightscout.utils.NSUpload; import info.nightscout.utils.NSUpload;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -69,7 +70,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
private static String event; private static String event;
Profile profile; Profile profile;
ProfileStore profileStore; public ProfileStore profileStore;
String units = Constants.MGDL; String units = Constants.MGDL;
TextView eventTypeText; TextView eventTypeText;
@ -108,14 +109,14 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public void setOptions(OptionsToShow options, int event) { public void setOptions(OptionsToShow options, int event) {
this.options = options; this.options = options;
this.event = MainApp.sResources.getString(event); this.event = MainApp.gs(event);
} }
public NewNSTreatmentDialog() { public NewNSTreatmentDialog() {
super(); super();
if (seconds == null) { if (seconds == null) {
seconds = new Double(Math.random() * 59).intValue(); seconds = Double.valueOf(Math.random() * 59).intValue();
} }
} }
@ -135,7 +136,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
if (options == null) return null; if (options == null) return null;
getDialog().setTitle(getString(options.eventName)); getDialog().setTitle(MainApp.gs(options.eventName));
setStyle(DialogFragment.STYLE_NORMAL, getTheme()); setStyle(DialogFragment.STYLE_NORMAL, getTheme());
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false); View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
@ -192,36 +193,40 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units); final Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units);
// temp target // temp target
final ArrayList<CharSequence> reasonList = new ArrayList<CharSequence>(); final List<String> reasonList = Lists.newArrayList(
reasonList.add(MainApp.sResources.getString(R.string.manual)); MainApp.gs(R.string.manual),
reasonList.add(MainApp.sResources.getString(R.string.eatingsoon)); MainApp.gs(R.string.eatingsoon),
reasonList.add(MainApp.sResources.getString(R.string.activity)); MainApp.gs(R.string.activity),
ArrayAdapter<CharSequence> adapterReason = new ArrayAdapter<CharSequence>(getContext(), MainApp.gs(R.string.hypo));
ArrayAdapter<String> adapterReason = new ArrayAdapter<>(getContext(),
R.layout.spinner_centered, reasonList); R.layout.spinner_centered, reasonList);
reasonSpinner.setAdapter(adapterReason); reasonSpinner.setAdapter(adapterReason);
reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { reasonSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
double defaultDuration = 0; double defaultDuration;
double defaultTarget = 0; double defaultTarget = 0;
if (profile != null) { if (profile != null) {
defaultTarget = bg.doubleValue(); defaultTarget = bg;
} }
boolean erase = false; boolean erase = false;
if (MainApp.sResources.getString(R.string.eatingsoon).equals(reasonList.get(position))) { String units = MainApp.getConfigBuilder().getProfileUnits();
defaultDuration = SP.getDouble(R.string.key_eatingsoon_duration, 0d); DefaultValueHelper helper = new DefaultValueHelper();
defaultTarget = SP.getDouble(R.string.key_eatingsoon_target, 0d); if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) {
; defaultDuration = helper.determineEatingSoonTTDuration();
} else if (MainApp.sResources.getString(R.string.activity).equals(reasonList.get(position))) { defaultTarget = helper.determineEatingSoonTT(units);
defaultDuration = SP.getDouble(R.string.key_activity_duration, 0d); } else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) {
; defaultDuration = helper.determineActivityTTDuration();
defaultTarget = SP.getDouble(R.string.key_activity_target, 0d); defaultTarget = helper.determineActivityTT(units);
; } else if (MainApp.gs(R.string.hypo).equals(reasonList.get(position))) {
defaultDuration = helper.determineHypoTTDuration();
defaultTarget = helper.determineHypoTT(units);
} else { } else {
defaultDuration = 0; defaultDuration = 0;
erase = true; erase = true;
} }
if (defaultTarget != 0 || erase) { if (defaultTarget != 0 || erase) {
editTemptarget.setValue(defaultTarget); editTemptarget.setValue(defaultTarget);
} }
@ -266,12 +271,9 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher); editBg.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, bgTextWatcher);
editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false); editTemptarget.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false);
} }
sensorRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { sensorRadioButton.setOnCheckedChangeListener((buttonView, isChecked) -> {
@Override Double bg1 = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { editBg.setValue(bg1);
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, profile.getUnits());
editBg.setValue(bg);
}
}); });
Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value(); Integer maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
@ -407,7 +409,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
tpd.show(context.getFragmentManager(), "Timepickerdialog"); tpd.show(context.getFragmentManager(), "Timepickerdialog");
break; break;
case R.id.ok: case R.id.ok:
createNSTreatment(); confirmNSTreatmentCreation();
dismiss(); dismiss();
break; break;
case R.id.cancel: case R.id.cancel:
@ -571,158 +573,151 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
String buildConfirmText(JSONObject data) { String buildConfirmText(JSONObject data) {
String ret = ""; String ret = "";
try { if (data.has("eventType")) {
if (data.has("eventType")) { ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
ret += getString(R.string.careportal_newnstreatment_eventtype); ret += ": ";
ret += ": "; ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
ret += Translator.translate(data.getString("eventType")); ret += "\n";
ret += "\n"; }
} if (data.has("glucose")) {
if (data.has("glucose")) { ret += MainApp.gs(R.string.treatments_wizard_bg_label);
ret += getString(R.string.treatments_wizard_bg_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "glucose", "");
ret += data.get("glucose"); ret += " " + units + "\n";
ret += " " + units + "\n"; }
} if (data.has("glucoseType")) {
if (data.has("glucoseType")) { ret += MainApp.gs(R.string.careportal_newnstreatment_glucosetype);
ret += getString(R.string.careportal_newnstreatment_glucosetype); ret += ": ";
ret += ": "; ret += Translator.translate(JsonHelper.safeGetString(data, "glucoseType", ""));
ret += Translator.translate(data.getString("glucoseType")); ret += "\n";
ret += "\n"; }
} if (data.has("carbs")) {
if (data.has("carbs")) { ret += MainApp.gs(R.string.careportal_newnstreatment_carbs_label);
ret += getString(R.string.careportal_newnstreatment_carbs_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "carbs", "");
ret += data.get("carbs"); ret += " g\n";
ret += " g\n"; }
} if (data.has("insulin")) {
if (data.has("insulin")) { ret += MainApp.gs(R.string.careportal_newnstreatment_insulin_label);
ret += getString(R.string.careportal_newnstreatment_insulin_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "insulin", "");
ret += data.get("insulin"); ret += " U\n";
ret += " U\n"; }
} if (data.has("duration")) {
if (data.has("duration")) { ret += MainApp.gs(R.string.careportal_newnstreatment_duration_label);
ret += getString(R.string.careportal_newnstreatment_duration_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "duration", "");
ret += data.get("duration"); ret += " min\n";
ret += " min\n"; }
} if (data.has("percent")) {
if (data.has("percent")) { ret += MainApp.gs(R.string.careportal_newnstreatment_percent_label);
ret += getString(R.string.careportal_newnstreatment_percent_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "percent", "");
ret += data.get("percent"); ret += " %\n";
ret += " %\n"; }
} if (data.has("absolute")) {
if (data.has("absolute")) { ret += MainApp.gs(R.string.careportal_newnstreatment_absolute_label);
ret += getString(R.string.careportal_newnstreatment_absolute_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "absolute", "");
ret += data.get("absolute"); ret += " U/h\n";
ret += " U/h\n"; }
} if (data.has("preBolus")) {
if (data.has("preBolus")) { ret += MainApp.gs(R.string.careportal_newnstreatment_carbtime_label);
ret += getString(R.string.careportal_newnstreatment_carbtime_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "preBolus", "");
ret += data.get("preBolus"); ret += " min\n";
ret += " min\n"; }
} if (data.has("notes")) {
if (data.has("notes")) { ret += MainApp.gs(R.string.careportal_newnstreatment_notes_label);
ret += getString(R.string.careportal_newnstreatment_notes_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "notes", "");
ret += data.get("notes"); ret += "\n";
ret += "\n"; }
} if (data.has("profile")) {
if (data.has("profile")) { ret += MainApp.gs(R.string.careportal_newnstreatment_profile_label);
ret += getString(R.string.careportal_newnstreatment_profile_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "profile", "");
ret += data.get("profile"); ret += "\n";
ret += "\n"; }
} if (data.has("percentage")) {
if (data.has("percentage")) { ret += MainApp.gs(R.string.careportal_newnstreatment_percentage_label);
ret += getString(R.string.careportal_newnstreatment_percentage_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "percentage", "");
ret += data.get("percentage"); ret += " %\n";
ret += " %\n"; }
} if (data.has("timeshift")) {
if (data.has("timeshift")) { ret += MainApp.gs(R.string.careportal_newnstreatment_timeshift_label);
ret += getString(R.string.careportal_newnstreatment_timeshift_label); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "timeshift", "");
ret += data.get("timeshift"); ret += " h\n";
ret += " h\n"; }
} if (data.has("targetBottom") && data.has("targetTop")) {
if (data.has("targetBottom") && data.has("targetTop")) { ret += MainApp.gs(R.string.target_range);
ret += getString(R.string.target_range); ret += " ";
ret += " "; ret += JsonHelper.safeGetObject(data, "targetBottom", "");
ret += data.get("targetBottom"); ret += " - ";
ret += " - "; ret += JsonHelper.safeGetObject(data, "targetTop", "");
ret += data.get("targetTop"); ret += "\n";
ret += "\n"; }
} if (data.has("created_at")) {
if (data.has("created_at")) { ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label);
ret += getString(R.string.careportal_newnstreatment_eventtime_label); ret += ": ";
ret += ": "; ret += eventTime.toLocaleString();
ret += eventTime.toLocaleString(); ret += "\n";
ret += "\n"; }
} if (data.has("enteredBy")) {
if (data.has("enteredBy")) { ret += MainApp.gs(R.string.careportal_newnstreatment_enteredby_title);
ret += getString(R.string.careportal_newnstreatment_enteredby_title); ret += ": ";
ret += ": "; ret += JsonHelper.safeGetObject(data, "enteredBy", "");
ret += data.get("enteredBy"); ret += "\n";
ret += "\n";
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
} }
return ret; return ret;
} }
void createNSTreatment() { void confirmNSTreatmentCreation() {
final JSONObject data = gatherData(); if (context != null) {
String confirmText = buildConfirmText(data); final JSONObject data = gatherData();
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); final String confirmText = buildConfirmText(data);
builder.setTitle(getContext().getString(R.string.confirmation)); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(confirmText); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setMessage(confirmText);
public void onClick(DialogInterface dialog, int id) { builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data));
if (options.executeProfileSwitch) { builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
if (data.has("profile")) { builder.show();
try { }
doProfileSwitch(profileStore, data.getString("profile"), data.getInt("duration"), data.getInt("percentage"), data.getInt("timeshift")); }
} catch (JSONException e) {
log.error("Unhandled exception", e);
} public void createNSTreatment(JSONObject data) {
} if (options.executeProfileSwitch) {
} else if (options.executeTempTarget) { if (data.has("profile")) {
try { doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
if ((data.has("targetBottom") && data.has("targetTop")) || (data.has("duration") && data.getInt("duration") == 0)) {
TempTarget tempTarget = new TempTarget()
.date(eventTime.getTime())
.duration(data.getInt("duration"))
.reason(data.getString("reason"))
.source(Source.USER);
if (tempTarget.durationInMinutes != 0) {
tempTarget.low(Profile.toMgdl(data.getDouble("targetBottom"), profile.getUnits()))
.high(Profile.toMgdl(data.getDouble("targetTop"), profile.getUnits()));
} else {
tempTarget.low(0).high(0);
}
log.debug("Creating new TempTarget db record: " + tempTarget.toString());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadCareportalEntryToNS(data);
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget"));
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
} else {
NSUpload.uploadCareportalEntryToNS(data);
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment"));
}
} }
}); } else if (options.executeTempTarget) {
builder.setNegativeButton(getContext().getString(R.string.cancel), null); final int duration = JsonHelper.safeGetInt(data, "duration");
builder.show(); final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom");
final double targetTop = JsonHelper.safeGetDouble(data, "targetTop");
final String reason = JsonHelper.safeGetString(data, "reason", "");
if ((targetBottom != 0d && targetTop != 0d) || duration == 0) {
TempTarget tempTarget = new TempTarget()
.date(eventTime.getTime())
.duration(duration)
.reason(reason)
.source(Source.USER);
if (tempTarget.durationInMinutes != 0) {
tempTarget.low(Profile.toMgdl(targetBottom, profile.getUnits()))
.high(Profile.toMgdl(targetTop, profile.getUnits()));
} else {
tempTarget.low(0).high(0);
}
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
FabricPrivacy.getInstance().logCustom(new CustomEvent("TempTarget"));
}
} else {
NSUpload.uploadCareportalEntryToNS(data);
FabricPrivacy.getInstance().logCustom(new CustomEvent("NSTreatment"));
}
} }
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {

View file

@ -264,10 +264,6 @@ public class ConfigBuilderPlugin extends PluginBase {
return activeAPS; return activeAPS;
} }
public static LoopPlugin getActiveLoop() {
return activeLoop;
}
public static PumpInterface getActivePump() { public static PumpInterface getActivePump() {
return activePump; return activePump;
} }
@ -621,7 +617,7 @@ public class ConfigBuilderPlugin extends PluginBase {
} }
public void disconnectPump(int durationInMinutes, Profile profile) { public void disconnectPump(int durationInMinutes, Profile profile) {
getActiveLoop().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L); LoopPlugin.getPlugin().disconnectTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000L);
getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() { getCommandQueue().tempBasalPercent(0, durationInMinutes, true, profile, new Callback() {
@Override @Override
public void run() { public void run() {
@ -644,7 +640,7 @@ public class ConfigBuilderPlugin extends PluginBase {
} }
public void suspendLoop(int durationInMinutes) { public void suspendLoop(int durationInMinutes) {
getActiveLoop().suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000); LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + durationInMinutes * 60 * 1000);
getCommandQueue().cancelTempBasal(true, new Callback() { getCommandQueue().cancelTempBasal(true, new Callback() {
@Override @Override
public void run() { public void run() {

View file

@ -85,37 +85,52 @@ public class ObjectivesFragment extends SubscriberFragment {
} }
}); });
Long now = System.currentTimeMillis(); long prevObjectiveAccomplishedTime = position > 0 ?
if (position > 0 && objectives.get(position - 1).accomplished.getTime() == 0) { objectives.get(position - 1).accomplished.getTime() : -1;
// Phase 0: previous not completed
holder.startedLayout.setVisibility(View.GONE); int phase = modifyVisibility(position, prevObjectiveAccomplishedTime,
holder.durationLayout.setVisibility(View.GONE); o.started.getTime(), o.durationInDays,
holder.progressLayout.setVisibility(View.GONE); o.accomplished.getTime(), requirementsMet.done, enableFake.isChecked());
holder.verifyLayout.setVisibility(View.GONE);
} else if (o.started.getTime() == 0) { switch (phase) {
// Phase 1: not started case 0:
holder.durationLayout.setVisibility(View.GONE); // Phase 0: previous not completed
holder.progressLayout.setVisibility(View.GONE); holder.startedLayout.setVisibility(View.GONE);
holder.verifyLayout.setVisibility(View.GONE); holder.durationLayout.setVisibility(View.GONE);
holder.started.setVisibility(View.GONE); holder.progressLayout.setVisibility(View.GONE);
} else if (o.started.getTime() > 0 && !enableFake.isChecked() && o.accomplished.getTime() == 0 && !(o.started.getTime() + o.durationInDays * 24 * 60 * 60 * 1000 < now && requirementsMet.done)) { holder.verifyLayout.setVisibility(View.GONE);
// Phase 2: started, waiting for duration and met requirements break;
holder.startButton.setEnabled(false); case 1:
holder.verifyLayout.setVisibility(View.GONE); // Phase 1: not started
} else if (o.accomplished.getTime() == 0) { holder.durationLayout.setVisibility(View.GONE);
// Phase 3: started, after duration, requirements met holder.progressLayout.setVisibility(View.GONE);
holder.startButton.setEnabled(false); holder.verifyLayout.setVisibility(View.GONE);
holder.accomplished.setVisibility(View.INVISIBLE); holder.started.setVisibility(View.GONE);
} else { break;
// Phase 4: verified case 2:
holder.gateLayout.setVisibility(View.GONE); // Phase 2: started, waiting for duration and met requirements
holder.startedLayout.setVisibility(View.GONE); holder.startButton.setEnabled(false);
holder.durationLayout.setVisibility(View.GONE); holder.verifyLayout.setVisibility(View.GONE);
holder.progressLayout.setVisibility(View.GONE); break;
holder.verifyButton.setVisibility(View.INVISIBLE); case 3:
// Phase 3: started, after duration, requirements met
holder.startButton.setEnabled(false);
holder.accomplished.setVisibility(View.INVISIBLE);
break;
case 4:
// Phase 4: verified
holder.gateLayout.setVisibility(View.GONE);
holder.startedLayout.setVisibility(View.GONE);
holder.durationLayout.setVisibility(View.GONE);
holder.progressLayout.setVisibility(View.GONE);
holder.verifyButton.setVisibility(View.INVISIBLE);
break;
default:
// should not happen
} }
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return objectives.size(); return objectives.size();
@ -164,6 +179,40 @@ public class ObjectivesFragment extends SubscriberFragment {
} }
} }
/**
* returns an int, which represents the phase the current objective is at.
*
* this is mainly used for unit-testing the conditions
*
* @param currentPosition
* @param prevObjectiveAccomplishedTime
* @param objectiveStartedTime
* @param durationInDays
* @param objectiveAccomplishedTime
* @param requirementsMet
* @return
*/
public int modifyVisibility(int currentPosition,
long prevObjectiveAccomplishedTime,
long objectiveStartedTime, int durationInDays,
long objectiveAccomplishedTime, boolean requirementsMet,
boolean enableFakeValue) {
Long now = System.currentTimeMillis();
if (currentPosition > 0 && prevObjectiveAccomplishedTime == 0) {
return 0;
} else if (objectiveStartedTime == 0) {
return 1;
} else if (objectiveStartedTime > 0 && !enableFakeValue
&& objectiveAccomplishedTime == 0
&& !(objectiveStartedTime + durationInDays * 24 * 60 * 60 * 1000 >= now && requirementsMet)) {
return 2;
} else if (objectiveAccomplishedTime == 0) {
return 3;
} else {
return 4;
}
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
@ -205,6 +254,7 @@ public class ObjectivesFragment extends SubscriberFragment {
ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate); ObjectivesPlugin.objectives.get(3).gate = MainApp.sResources.getString(R.string.objectives_3_gate);
ObjectivesPlugin.objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate); ObjectivesPlugin.objectives.get(4).gate = MainApp.sResources.getString(R.string.objectives_4_gate);
ObjectivesPlugin.objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate); ObjectivesPlugin.objectives.get(5).gate = MainApp.sResources.getString(R.string.objectives_5_gate);
updateGUI(); updateGUI();
return view; return view;
@ -225,4 +275,4 @@ public class ObjectivesFragment extends SubscriberFragment {
}); });
} }
} }

View file

@ -9,6 +9,7 @@ import android.app.TaskStackBuilder;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
@ -56,6 +57,7 @@ public class LoopPlugin extends PluginBase {
protected static LoopPlugin loopPlugin; protected static LoopPlugin loopPlugin;
@NonNull
public static LoopPlugin getPlugin() { public static LoopPlugin getPlugin() {
if (loopPlugin == null) { if (loopPlugin == null) {
loopPlugin = new LoopPlugin(); loopPlugin = new LoopPlugin();

View file

@ -1,15 +1,14 @@
package info.nightscout.androidaps.plugins.Overview.Dialogs; package info.nightscout.androidaps.plugins.Overview.Dialogs;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
import android.text.Html; import android.text.Html;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -18,20 +17,16 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton; import android.widget.RadioButton;
import android.widget.TextView;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -49,36 +44,32 @@ import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.queue.Callback;
import info.nightscout.utils.DateUtil; import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.DefaultValueHelper;
import info.nightscout.utils.NumberPicker; import info.nightscout.utils.NumberPicker;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
public class NewCarbsDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener, CompoundButton.OnCheckedChangeListener { import static info.nightscout.utils.DateUtil.now;
public class NewCarbsDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class); private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class);
private NumberPicker editCarbs;
private TextView dateButton;
private TextView timeButton;
private Date initialEventTime;
private Date eventTime;
private Button fav1Button;
private Button fav2Button;
private Button fav3Button;
private static final int FAV1_DEFAULT = 5; private static final int FAV1_DEFAULT = 5;
private static final int FAV2_DEFAULT = 10; private static final int FAV2_DEFAULT = 10;
private static final int FAV3_DEFAULT = 20; private static final int FAV3_DEFAULT = 20;
private RadioButton startActivityTTCheckbox; private RadioButton startActivityTTCheckbox;
private RadioButton startEatingSoonTTCheckbox; private RadioButton startEatingSoonTTCheckbox;
private RadioButton startHypoTTCheckbox; private RadioButton startHypoTTCheckbox;
private boolean togglingTT; private boolean togglingTT;
private NumberPicker editTime;
private NumberPicker editDuration;
private NumberPicker editCarbs;
private Integer maxCarbs; private Integer maxCarbs;
private EditText notesEdit;
//one shot guards //one shot guards
private boolean accepted; private boolean accepted;
private boolean okClicked; private boolean okClicked;
@ -91,6 +82,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
final private TextWatcher textWatcher = new TextWatcher() { final private TextWatcher textWatcher = new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
validateInputs();
} }
@Override @Override
@ -99,12 +91,21 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
validateInputs();
} }
}; };
private void validateInputs() { private void validateInputs() {
Integer carbs = SafeParse.stringToInt(editCarbs.getText()); int time = editTime.getValue().intValue();
if (time > 12 * 60 || time < -12 * 60) {
editTime.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
Double duration = editDuration.getValue();
if (duration > 10) {
editDuration.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
int carbs = editCarbs.getValue().intValue();
if (carbs > maxCarbs) { if (carbs > maxCarbs) {
editCarbs.setValue(0d); editCarbs.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied)); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied));
@ -122,12 +123,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = view.findViewById(R.id.newcarb_carbsamount);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt); startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt);
startActivityTTCheckbox.setOnCheckedChangeListener(this); startActivityTTCheckbox.setOnCheckedChangeListener(this);
startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt); startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt);
@ -135,28 +130,36 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt); startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt);
startHypoTTCheckbox.setOnCheckedChangeListener(this); startHypoTTCheckbox.setOnCheckedChangeListener(this);
dateButton = view.findViewById(R.id.newcarbs_eventdate); editTime = view.findViewById(R.id.newcarbs_time);
timeButton = view.findViewById(R.id.newcarb_eventtime); editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
initialEventTime = new Date(); LinearLayout durationLayout = view.findViewById(R.id.newcarbs_duration_layout);
eventTime = new Date(initialEventTime.getTime()); durationLayout.setVisibility(MainApp.engineeringMode ? View.VISIBLE : View.GONE);
dateButton.setText(DateUtil.dateString(eventTime));
timeButton.setText(DateUtil.timeString(eventTime));
dateButton.setOnClickListener(this);
timeButton.setOnClickListener(this);
fav1Button = view.findViewById(R.id.newcarbs_plus1); editDuration = view.findViewById(R.id.new_carbs_duration);
editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, textWatcher);
maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = view.findViewById(R.id.newcarb_carbsamount);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, textWatcher);
Button fav1Button = view.findViewById(R.id.newcarbs_plus1);
fav1Button.setOnClickListener(this); fav1Button.setOnClickListener(this);
fav1Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))); fav1Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)));
fav2Button = view.findViewById(R.id.newcarbs_plus2); Button fav2Button = view.findViewById(R.id.newcarbs_plus2);
fav2Button.setOnClickListener(this); fav2Button.setOnClickListener(this);
fav2Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))); fav2Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)));
fav3Button = view.findViewById(R.id.newcarbs_plus3); Button fav3Button = view.findViewById(R.id.newcarbs_plus3);
fav3Button.setOnClickListener(this); fav3Button.setOnClickListener(this);
fav3Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))); fav3Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)));
LinearLayout notesLayout = view.findViewById(R.id.newcarbs_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = view.findViewById(R.id.newcarbs_notes);
setCancelable(true); setCancelable(true);
getDialog().setCanceledOnTouchOutside(false); getDialog().setCanceledOnTouchOutside(false);
return view; return view;
@ -168,8 +171,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
@Override @Override
public synchronized void onClick(View view) { public synchronized void onClick(View view) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(eventTime);
switch (view.getId()) { switch (view.getId()) {
case R.id.ok: case R.id.ok:
submit(); submit();
@ -177,28 +178,6 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
case R.id.cancel: case R.id.cancel:
dismiss(); dismiss();
break; break;
case R.id.newcarbs_eventdate:
DatePickerDialog dpd = DatePickerDialog.newInstance(
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
dpd.setThemeDark(true);
dpd.dismissOnPause(true);
dpd.show(getActivity().getFragmentManager(), "Datepickerdialog");
break;
case R.id.newcarb_eventtime:
TimePickerDialog tpd = TimePickerDialog.newInstance(
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(getActivity())
);
tpd.setThemeDark(true);
tpd.dismissOnPause(true);
tpd.show(getActivity().getFragmentManager(), "Timepickerdialog");
break;
case R.id.newcarbs_plus1: case R.id.newcarbs_plus1:
editCarbs.setValue(Math.max(0, editCarbs.getValue() editCarbs.setValue(Math.max(0, editCarbs.getValue()
+ SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))); + SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)));
@ -304,39 +283,35 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
} }
okClicked = true; okClicked = true;
try { try {
final Integer carbs = SafeParse.stringToInt(editCarbs.getText()); final Profile currentProfile = MainApp.getConfigBuilder().getProfile();
if (currentProfile == null) {
return;
}
int carbs = editCarbs.getValue().intValue();
Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value(); Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value();
final String units = currentProfile.getUnits();
DefaultValueHelper helper = new DefaultValueHelper();
int activityTTDuration = helper.determineActivityTTDuration();
double activityTT = helper.determineActivityTT(units);
int eatingSoonTTDuration = helper.determineEatingSoonTTDuration();
double eatingSoonTT = helper.determineEatingSoonTT(units);
int hypoTTDuration = helper.determineHypoTTDuration();
double hypoTT = helper.determineHypoTT(units);
List<String> actions = new LinkedList<>(); List<String> actions = new LinkedList<>();
if (carbs > 0)
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + carbsAfterConstraints + "g" + "</font>");
if (!carbsAfterConstraints.equals(carbs))
actions.add("<font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>");
final Profile currentProfile = MainApp.getConfigBuilder().getProfile();
if (currentProfile == null)
return;
int activityTTDuration = SP.getInt(R.string.key_activity_duration, Constants.defaultActivityTTDuration);
activityTTDuration = activityTTDuration > 0 ? activityTTDuration : Constants.defaultActivityTTDuration;
double activityTT = SP.getDouble(R.string.key_activity_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultActivityTTmmol : Constants.defaultActivityTTmgdl);
activityTT = activityTT > 0 ? activityTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultActivityTTmmol : Constants.defaultActivityTTmgdl;
int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration);
eatingSoonTTDuration = eatingSoonTTDuration > 0 ? eatingSoonTTDuration : Constants.defaultEatingSoonTTDuration;
double eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl);
eatingSoonTT = eatingSoonTT > 0 ? eatingSoonTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl;
int hypoTTDuration = SP.getInt(R.string.key_hypo_duration, Constants.defaultHypoTTDuration);
hypoTTDuration = hypoTTDuration > 0 ? hypoTTDuration : Constants.defaultHypoTTDuration;
double hypoTT = SP.getDouble(R.string.key_hypo_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultHypoTTmmol : Constants.defaultHypoTTmgdl);
hypoTT = hypoTT > 0 ? hypoTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultHypoTTmmol : Constants.defaultHypoTTmgdl;
if (startActivityTTCheckbox.isChecked()) { if (startActivityTTCheckbox.isChecked()) {
String unitLabel = "mg/dl";
if (currentProfile.getUnits().equals(Constants.MMOL)) { if (currentProfile.getUnits().equals(Constants.MMOL)) {
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " mmol/l (" + activityTTDuration + " min)</font>"); unitLabel = "mmol/l";
} else }
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to0Decimal(activityTT) + " mg/dl (" + activityTTDuration + " min)</font>");
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " min)</font>");
} }
if (startEatingSoonTTCheckbox.isChecked()) { if (startEatingSoonTTCheckbox.isChecked()) {
@ -352,6 +327,26 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)</font>"); actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)</font>");
} }
int timeOffset = editTime.getValue().intValue();
final long time = now() + timeOffset * 1000 * 60;
if (timeOffset != 0) {
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time));
}
int duration = editDuration.getValue().intValue();
if (duration > 0) {
actions.add(MainApp.gs(R.string.duration) + ": " + duration + MainApp.gs(R.string.shorthour));
}
if (carbs > 0) {
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + carbsAfterConstraints + "g" + "</font>");
}
if (!carbsAfterConstraints.equals(carbs)) {
actions.add("<font color='" + MainApp.gc(R.color.low) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>");
}
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
}
final double finalActivityTT = activityTT; final double finalActivityTT = activityTT;
final int finalActivityTTDuration = activityTTDuration; final int finalActivityTTDuration = activityTTDuration;
final double finalEatigSoonTT = eatingSoonTT; final double finalEatigSoonTT = eatingSoonTT;
@ -359,26 +354,18 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
final double finalHypoTT = hypoTT; final double finalHypoTT = hypoTT;
final int finalHypoTTDuration = hypoTTDuration; final int finalHypoTTDuration = hypoTTDuration;
if (!initialEventTime.equals(eventTime)) { final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
actions.add("Time: " + DateUtil.dateAndTimeString(eventTime));
}
final int finalCarbsAfterConstraints = carbsAfterConstraints;
final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(actions.isEmpty() if (carbsAfterConstraints > 0 || startActivityTTCheckbox.isChecked()
? MainApp.gs(R.string.no_action_selected) || startEatingSoonTTCheckbox.isChecked() || startHypoTTCheckbox.isChecked()) {
: Html.fromHtml(Joiner.on("<br/>").join(actions))); builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(actions)));
builder.setPositiveButton(MainApp.gs(R.string.ok), actions.isEmpty() ? null : (dialog, id) -> { builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
synchronized (builder) { synchronized (builder) {
if (accepted) { if (accepted) {
log.debug("guarding: already accepted"); log.debug("guarding: already accepted");
return; return;
} }
accepted = true; accepted = true;
if (startActivityTTCheckbox.isChecked()) { if (startActivityTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget() TempTarget tempTarget = new TempTarget()
@ -388,7 +375,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())) .low(Profile.toMgdl(finalActivityTT, currentProfile.getUnits()))
.high(Profile.toMgdl(finalActivityTT, currentProfile.getUnits())); .high(Profile.toMgdl(finalActivityTT, currentProfile.getUnits()));
MainApp.getDbHelper().createOrUpdate(tempTarget); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (startEatingSoonTTCheckbox.isChecked()) { } else if (startEatingSoonTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget() TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis()) .date(System.currentTimeMillis())
@ -397,7 +384,7 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())) .low(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits()))
.high(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits())); .high(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits()));
MainApp.getDbHelper().createOrUpdate(tempTarget); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (startHypoTTCheckbox.isChecked()) { } else if (startHypoTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget() TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis()) .date(System.currentTimeMillis())
@ -406,36 +393,28 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
.source(Source.USER) .source(Source.USER)
.low(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())) .low(Profile.toMgdl(finalHypoTT, currentProfile.getUnits()))
.high(Profile.toMgdl(finalHypoTT, currentProfile.getUnits())); .high(Profile.toMgdl(finalHypoTT, currentProfile.getUnits()));
MainApp.getDbHelper().createOrUpdate(tempTarget); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} }
if (finalCarbsAfterConstraints > 0) { if (carbsAfterConstraints > 0) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); if (duration == 0) {
detailedBolusInfo.date = eventTime.getTime(); createCarb(carbsAfterConstraints, time, notes);
detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION; } else {
detailedBolusInfo.carbs = finalCarbsAfterConstraints; long remainingCarbs = carbsAfterConstraints;
detailedBolusInfo.context = context; int ticks = (duration * 4); //duration guaranteed to be integer greater zero
detailedBolusInfo.source = Source.USER; for (int i = 0; i < ticks; i++){
if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { long carbTime = time + i * 15 * 60 * 1000;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { long smallCarbAmount = Math.round((1d * remainingCarbs) / (ticks-i)); //on last iteration (ticks-i) is 1 -> smallCarbAmount == remainingCarbs
@Override remainingCarbs -= smallCarbAmount;
public void run() { createCarb(smallCarbAmount, carbTime, notes);
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
} }
}); }
} else {
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
} }
} }
} });
}); } else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
}
builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show(); builder.show();
dismiss(); dismiss();
@ -444,19 +423,30 @@ public class NewCarbsDialog extends DialogFragment implements OnClickListener, D
} }
} }
@Override private void createCarb(long carbs, long time, @Nullable String notes) {
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) { DetailedBolusInfo carbInfo = new DetailedBolusInfo();
eventTime.setYear(year - 1900); carbInfo.date = time;
eventTime.setMonth(monthOfYear); carbInfo.eventType = CareportalEvent.CARBCORRECTION;
eventTime.setDate(dayOfMonth); carbInfo.carbs = carbs;
dateButton.setText(DateUtil.dateString(eventTime)); carbInfo.context = getContext();
} carbInfo.source = Source.USER;
carbInfo.notes = notes;
@Override if (ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) { ConfigBuilderPlugin.getCommandQueue().bolus(carbInfo, new Callback() {
eventTime.setHours(hourOfDay); @Override
eventTime.setMinutes(minute); public void run() {
eventTime.setSeconds(second); if (!result.success) {
timeButton.setText(DateUtil.timeString(eventTime)); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
} else {
TreatmentsPlugin.getPlugin().addToHistoryTreatment(carbInfo);
}
} }
} }

View file

@ -9,7 +9,6 @@ import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
import android.text.Html; import android.text.Html;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -18,19 +17,16 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.TextView; import android.widget.EditText;
import android.widget.LinearLayout;
import com.crashlytics.android.answers.CustomEvent; import com.crashlytics.android.answers.CustomEvent;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import com.wdullaer.materialdatetimepicker.time.RadialPickerLayout;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Calendar; import java.text.DecimalFormat;
import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -54,30 +50,25 @@ import info.nightscout.utils.SP;
import info.nightscout.utils.SafeParse; import info.nightscout.utils.SafeParse;
import info.nightscout.utils.ToastUtils; import info.nightscout.utils.ToastUtils;
public class NewInsulinDialog extends DialogFragment implements OnClickListener, DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener { import static info.nightscout.utils.DateUtil.now;
public class NewInsulinDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewInsulinDialog.class); private static Logger log = LoggerFactory.getLogger(NewInsulinDialog.class);
private NumberPicker editInsulin;
private TextView dateButton;
private TextView timeButton;
private Date initialEventTime;
private Date eventTime;
private Button plus1Button;
private Button plus2Button;
private Button plus3Button;
public static final double PLUS1_DEFAULT = 0.5d; public static final double PLUS1_DEFAULT = 0.5d;
public static final double PLUS2_DEFAULT = 1d; public static final double PLUS2_DEFAULT = 1d;
public static final double PLUS3_DEFAULT = 2d; public static final double PLUS3_DEFAULT = 2d;
private CheckBox startESMCheckbox; private CheckBox startEatingSoonTTCheckbox;
private CheckBox recordOnlyCheckbox; private CheckBox recordOnlyCheckbox;
private LinearLayout editLayout;
private NumberPicker editTime;
private NumberPicker editInsulin;
private Double maxInsulin; private Double maxInsulin;
private EditText notesEdit;
//one shot guards //one shot guards
private boolean accepted; private boolean accepted;
private boolean okClicked; private boolean okClicked;
@ -90,6 +81,7 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
final private TextWatcher textWatcher = new TextWatcher() { final private TextWatcher textWatcher = new TextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
validateInputs();
} }
@Override @Override
@ -98,12 +90,16 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) { public void onTextChanged(CharSequence s, int start, int before, int count) {
validateInputs();
} }
}; };
private void validateInputs() { private void validateInputs() {
Double insulin = SafeParse.stringToDouble(editInsulin.getText()); int time = editTime.getValue().intValue();
if (Math.abs(time) > 12 * 60) {
editTime.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
Double insulin = editInsulin.getValue();
if (insulin > maxInsulin) { if (insulin > maxInsulin) {
editInsulin.setValue(0d); editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied)); ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied));
@ -121,39 +117,34 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
startEatingSoonTTCheckbox = view.findViewById(R.id.newinsulin_start_eating_soon_tt);
recordOnlyCheckbox = view.findViewById(R.id.newinsulin_record_only);
recordOnlyCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> editLayout.setVisibility(isChecked ? View.VISIBLE : View.GONE));
editLayout = view.findViewById(R.id.newinsulin_time_layout);
editLayout.setVisibility(View.GONE);
editTime = view.findViewById(R.id.newinsulin_time);
editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, textWatcher);
maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value(); maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newinsulin_amount); editInsulin = view.findViewById(R.id.newinsulin_amount);
editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher); editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, textWatcher);
dateButton = (TextView) view.findViewById(R.id.newinsulin_eventdate); Button plus1Button = view.findViewById(R.id.newinsulin_plus05);
timeButton = (TextView) view.findViewById(R.id.newinsulin_eventtime);
initialEventTime = new Date();
eventTime = new Date(initialEventTime.getTime());
dateButton.setText(DateUtil.dateString(eventTime));
timeButton.setText(DateUtil.timeString(eventTime));
dateButton.setOnClickListener(this);
timeButton.setOnClickListener(this);
plus1Button = (Button) view.findViewById(R.id.newinsulin_plus05);
plus1Button.setOnClickListener(this); plus1Button.setOnClickListener(this);
plus1Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))); plus1Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)));
plus2Button = (Button) view.findViewById(R.id.newinsulin_plus10); Button plus2Button = view.findViewById(R.id.newinsulin_plus10);
plus2Button.setOnClickListener(this); plus2Button.setOnClickListener(this);
plus2Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))); plus2Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT)));
plus3Button = (Button) view.findViewById(R.id.newinsulin_plus20); Button plus3Button = view.findViewById(R.id.newinsulin_plus20);
plus3Button.setOnClickListener(this); plus3Button.setOnClickListener(this);
plus3Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))); plus3Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT)));
startESMCheckbox = (CheckBox) view.findViewById(R.id.newinsulin_start_eating_soon_tt); LinearLayout notesLayout = view.findViewById(R.id.newinsulin_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
recordOnlyCheckbox = (CheckBox) view.findViewById(R.id.newinsulin_record_only); notesEdit = view.findViewById(R.id.newinsulin_notes);
recordOnlyCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (dateButton != null) dateButton.setEnabled(isChecked);
if (timeButton != null) timeButton.setEnabled(isChecked);
});
setCancelable(true); setCancelable(true);
getDialog().setCanceledOnTouchOutside(false); getDialog().setCanceledOnTouchOutside(false);
@ -167,8 +158,6 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
@Override @Override
public synchronized void onClick(View view) { public synchronized void onClick(View view) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(eventTime);
switch (view.getId()) { switch (view.getId()) {
case R.id.ok: case R.id.ok:
submit(); submit();
@ -176,28 +165,6 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
case R.id.cancel: case R.id.cancel:
dismiss(); dismiss();
break; break;
case R.id.newinsulin_eventdate:
DatePickerDialog dpd = DatePickerDialog.newInstance(
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
);
dpd.setThemeDark(true);
dpd.dismissOnPause(true);
dpd.show(getActivity().getFragmentManager(), "Datepickerdialog");
break;
case R.id.newinsulin_eventtime:
TimePickerDialog tpd = TimePickerDialog.newInstance(
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(getActivity())
);
tpd.setThemeDark(true);
tpd.dismissOnPause(true);
tpd.show(getActivity().getFragmentManager(), "Timepickerdialog");
break;
case R.id.newinsulin_plus05: case R.id.newinsulin_plus05:
editInsulin.setValue(Math.max(0, editInsulin.getValue() editInsulin.setValue(Math.max(0, editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))); + SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)));
@ -225,6 +192,10 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
okClicked = true; okClicked = true;
try { try {
Profile currentProfile = MainApp.getConfigBuilder().getProfile();
if (currentProfile == null)
return;
Double insulin = SafeParse.stringToDouble(editInsulin.getText()); Double insulin = SafeParse.stringToDouble(editInsulin.getText());
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value(); Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
@ -239,92 +210,90 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
if (!insulinAfterConstraints.equals(insulin)) if (!insulinAfterConstraints.equals(insulin))
actions.add("<font color='" + MainApp.sResources.getColor(R.color.low) + "'>" + MainApp.gs(R.string.bolusconstraintapplied) + "</font>"); actions.add("<font color='" + MainApp.sResources.getColor(R.color.low) + "'>" + MainApp.gs(R.string.bolusconstraintapplied) + "</font>");
double prefTTDuration = SP.getDouble(R.string.key_eatingsoon_duration, 45d); int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration);
double ttDuration = prefTTDuration > 0 ? prefTTDuration : 45d; eatingSoonTTDuration = eatingSoonTTDuration > 0 ? eatingSoonTTDuration : Constants.defaultEatingSoonTTDuration;
double prefTT = SP.getDouble(R.string.key_eatingsoon_target, 80d); double eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl);
Profile currentProfile = MainApp.getConfigBuilder().getProfile(); eatingSoonTT = eatingSoonTT > 0 ? eatingSoonTT : currentProfile.getUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl;
if (currentProfile == null)
return;
double tt;
if (currentProfile.getUnits().equals(Constants.MMOL))
tt = prefTT > 0 ? Profile.toMgdl(prefTT, Constants.MMOL) : 80d;
else
tt = prefTT > 0 ? prefTT : 80d;
final double finalTT = tt;
if (startESMCheckbox.isChecked()) { if (startEatingSoonTTCheckbox.isChecked()) {
if (currentProfile.getUnits().equals("mmol")) { if (currentProfile.getUnits().equals(Constants.MMOL)) {
actions.add("TT: " + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + Profile.toMmol(tt, Constants.MGDL) + " mmol for " + ((int) ttDuration) + " min </font>"); actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)</font>");
} else } else
actions.add("TT: " + "<font color='" + MainApp.sResources.getColor(R.color.high) + "'>" + ((int) tt) + "mg/dl for " + ((int) ttDuration) + " min </font>"); actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.high) + "'>" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)</font>");
} }
if (!initialEventTime.equals(eventTime)) { int timeOffset = editTime.getValue().intValue();
actions.add("Time: " + DateUtil.dateAndTimeString(eventTime)); final long time = now() + timeOffset * 1000 * 60;
if (timeOffset != 0) {
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time));
}
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
} }
final double finalInsulinAfterConstraints = insulinAfterConstraints; final double finalInsulinAfterConstraints = insulinAfterConstraints;
final double finalEatigSoonTT = eatingSoonTT;
final int finalEatingSoonTTDuration = eatingSoonTTDuration;
final Context context = getContext(); final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context); final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(actions.isEmpty() if (finalInsulinAfterConstraints > 0 || startEatingSoonTTCheckbox.isChecked()) {
? MainApp.gs(R.string.no_action_selected) builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(actions)));
: Html.fromHtml(Joiner.on("<br/>").join(actions))); builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
builder.setPositiveButton(MainApp.gs(R.string.ok), actions.isEmpty() ? null : (dialog, id) -> { synchronized (builder) {
synchronized (builder) { if (accepted) {
if (accepted) { log.debug("guarding: already accepted");
log.debug("guarding: already accepted"); return;
return; }
} accepted = true;
accepted = true;
if (startESMCheckbox.isChecked()) { if (startEatingSoonTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget() TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis()) .date(System.currentTimeMillis())
.duration((int) ttDuration) .duration(finalEatingSoonTTDuration)
.reason("Eating soon") .reason(MainApp.gs(R.string.eatingsoon))
.source(Source.USER) .source(Source.USER)
.low((int) finalTT) .low(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits()))
.high((int) finalTT); .high(Profile.toMgdl(finalEatigSoonTT, currentProfile.getUnits()));
MainApp.getDbHelper().createOrUpdate(tempTarget); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} }
if (finalInsulinAfterConstraints <= 0.01) { if (finalInsulinAfterConstraints > 0) {
return; DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
} detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
if (recordOnlyCheckbox.isChecked()) { detailedBolusInfo.context = context;
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); detailedBolusInfo.source = Source.USER;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.notes = notes;
detailedBolusInfo.date = eventTime.getTime(); if (recordOnlyCheckbox.isChecked()) {
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; detailedBolusInfo.date = time;
detailedBolusInfo.insulin = finalInsulinAfterConstraints; TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo); } else {
} else { detailedBolusInfo.date = now();
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS; @Override
detailedBolusInfo.insulin = finalInsulinAfterConstraints; public void run() {
detailedBolusInfo.context = context; if (!result.success) {
detailedBolusInfo.source = Source.USER; Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { i.putExtra("soundid", R.raw.boluserror);
@Override i.putExtra("status", result.comment);
public void run() { i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
if (!result.success) { i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); MainApp.instance().startActivity(i);
i.putExtra("soundid", R.raw.boluserror); }
i.putExtra("status", result.comment); }
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); });
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); FabricPrivacy.getInstance().logCustom(new CustomEvent("Bolus"));
MainApp.instance().startActivity(i);
}
} }
}); }
FabricPrivacy.getInstance().logCustom(new CustomEvent("Bolus"));
} }
} });
}); } else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
}
builder.setNegativeButton(MainApp.gs(R.string.cancel), null); builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show(); builder.show();
dismiss(); dismiss();
@ -332,20 +301,4 @@ public class NewInsulinDialog extends DialogFragment implements OnClickListener,
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
} }
@Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
eventTime.setYear(year - 1900);
eventTime.setMonth(monthOfYear);
eventTime.setDate(dayOfMonth);
dateButton.setText(DateUtil.dateString(eventTime));
}
@Override
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute, int second) {
eventTime.setHours(hourOfDay);
eventTime.setMinutes(minute);
eventTime.setSeconds(second);
timeButton.setText(DateUtil.timeString(eventTime));
}
} }

View file

@ -21,6 +21,7 @@ import android.widget.ArrayAdapter;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
@ -53,6 +54,7 @@ import info.nightscout.androidaps.events.EventFeatureRunning;
import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventNewBG;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData;
import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin;
@ -103,6 +105,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
NumberPicker editCorr; NumberPicker editCorr;
NumberPicker editCarbTime; NumberPicker editCarbTime;
LinearLayout notesLayout;
EditText notesEdit;
Integer calculatedCarbs = 0; Integer calculatedCarbs = 0;
Double calculatedTotalInsulin = 0d; Double calculatedTotalInsulin = 0d;
JSONObject boluscalcJSON; JSONObject boluscalcJSON;
@ -205,6 +210,10 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb); superbolus = (TextView) view.findViewById(R.id.treatments_wizard_sb);
superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin); superbolusInsulin = (TextView) view.findViewById(R.id.treatments_wizard_sbinsulin);
notesLayout = view.findViewById(R.id.treatments_wizard_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = (EditText) view.findViewById(R.id.treatment_wizard_notes);
bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend); bgTrend = (TextView) view.findViewById(R.id.treatments_wizard_bgtrend);
bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin); bgTrendInsulin = (TextView) view.findViewById(R.id.treatments_wizard_bgtrendinsulin);
cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout); cobLayout = (LinearLayout) view.findViewById(R.id.treatments_wizard_cob_layout);
@ -320,6 +329,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
final Double bg = SafeParse.stringToDouble(editBg.getText()); final Double bg = SafeParse.stringToDouble(editBg.getText());
final int carbTime = SafeParse.stringToInt(editCarbTime.getText()); final int carbTime = SafeParse.stringToInt(editCarbTime.getText());
final boolean useSuperBolus = superbolusCheckbox.isChecked(); final boolean useSuperBolus = superbolusCheckbox.isChecked();
final String finalNotes = notesEdit.getText().toString();
final AlertDialog.Builder builder = new AlertDialog.Builder(context); final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); builder.setTitle(MainApp.sResources.getString(R.string.confirmation));
@ -334,9 +344,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
accepted = true; accepted = true;
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
if (useSuperBolus) { if (useSuperBolus) {
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (activeloop != null) { if (loopPlugin.isEnabled(PluginType.LOOP)) {
activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
MainApp.bus().post(new EventRefreshOverview("WizardDialog")); MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
} }
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() { ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
@ -363,6 +373,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com
detailedBolusInfo.carbTime = carbTime; detailedBolusInfo.carbTime = carbTime;
detailedBolusInfo.boluscalc = boluscalcJSON; detailedBolusInfo.boluscalc = boluscalcJSON;
detailedBolusInfo.source = Source.USER; detailedBolusInfo.source = Source.USER;
detailedBolusInfo.notes = finalNotes;
if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) { if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getActivePump().getPumpDescription().storesCarbInfo) {
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override @Override

View file

@ -79,6 +79,7 @@ import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventInitializationChanged; import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventPreferenceChange; import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventProfileSwitchChange;
import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
@ -457,14 +458,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
if (v == apsModeView) { if (v == apsModeView) {
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription(); final PumpDescription pumpDescription = ConfigBuilderPlugin.getActivePump().getPumpDescription();
if (activeloop == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation")) if (loopPlugin == null || !MainApp.getConfigBuilder().isProfileValid("ContexMenuCreation"))
return; return;
menu.setHeaderTitle(MainApp.gs(R.string.loop)); menu.setHeaderTitle(MainApp.gs(R.string.loop));
if (activeloop.isEnabled(PluginType.LOOP)) { if (loopPlugin.isEnabled(PluginType.LOOP)) {
menu.add(MainApp.gs(R.string.disableloop)); menu.add(MainApp.gs(R.string.disableloop));
if (!activeloop.isSuspended()) { if (!loopPlugin.isSuspended()) {
menu.add(MainApp.gs(R.string.suspendloopfor1h)); menu.add(MainApp.gs(R.string.suspendloopfor1h));
menu.add(MainApp.gs(R.string.suspendloopfor2h)); menu.add(MainApp.gs(R.string.suspendloopfor2h));
menu.add(MainApp.gs(R.string.suspendloopfor3h)); menu.add(MainApp.gs(R.string.suspendloopfor3h));
@ -480,7 +481,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
menu.add(MainApp.gs(R.string.resume)); menu.add(MainApp.gs(R.string.resume));
} }
} }
if (!activeloop.isEnabled(PluginType.LOOP)) if (!loopPlugin.isEnabled(PluginType.LOOP))
menu.add(MainApp.gs(R.string.enableloop)); menu.add(MainApp.gs(R.string.enableloop));
} else if (v == activeProfileView) { } else if (v == activeProfileView) {
menu.setHeaderTitle(MainApp.gs(R.string.profile)); menu.setHeaderTitle(MainApp.gs(R.string.profile));
@ -496,13 +497,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
final Profile profile = MainApp.getConfigBuilder().getProfile(); final Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) if (profile == null)
return true; return true;
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (item.getTitle().equals(MainApp.gs(R.string.disableloop))) { if (item.getTitle().equals(MainApp.gs(R.string.disableloop))) {
activeloop.setPluginEnabled(PluginType.LOOP, false); loopPlugin.setPluginEnabled(PluginType.LOOP, false);
activeloop.setFragmentVisible(PluginType.LOOP, false); loopPlugin.setFragmentVisible(PluginType.LOOP, false);
MainApp.getConfigBuilder().storeSettings("DisablingLoop"); MainApp.getConfigBuilder().storeSettings("DisablingLoop");
updateGUI("suspendmenu"); updateGUI("suspendmenu");
MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() { ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
@ -513,16 +514,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration NSUpload.uploadOpenAPSOffline(24 * 60); // upload 24h, we don't know real duration
return true; return true;
} else if (item.getTitle().equals(MainApp.gs(R.string.enableloop))) { } else if (item.getTitle().equals(MainApp.gs(R.string.enableloop))) {
activeloop.setPluginEnabled(PluginType.LOOP, true); loopPlugin.setPluginEnabled(PluginType.LOOP, true);
activeloop.setFragmentVisible(PluginType.LOOP, true); loopPlugin.setFragmentVisible(PluginType.LOOP, true);
MainApp.getConfigBuilder().storeSettings("EnablingLoop"); MainApp.getConfigBuilder().storeSettings("EnablingLoop");
updateGUI("suspendmenu"); updateGUI("suspendmenu");
NSUpload.uploadOpenAPSOffline(0); NSUpload.uploadOpenAPSOffline(0);
return true; return true;
} else if (item.getTitle().equals(MainApp.gs(R.string.resume))) { } else if (item.getTitle().equals(MainApp.gs(R.string.resume))) {
activeloop.suspendTo(0L); loopPlugin.suspendTo(0L);
updateGUI("suspendmenu"); updateGUI("suspendmenu");
MainApp.getConfigBuilder().getCommandQueue().cancelTempBasal(true, new Callback() { ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
@ -673,36 +674,34 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
private void onClickAcceptTemp() { private void onClickAcceptTemp() {
Profile profile = MainApp.getConfigBuilder().getProfile(); Profile profile = MainApp.getConfigBuilder().getProfile();
if (ConfigBuilderPlugin.getActiveLoop() != null && profile != null) { if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && profile != null) {
ConfigBuilderPlugin.getActiveLoop().invoke("Accept temp button", false); LoopPlugin.getPlugin().invoke("Accept temp button", false);
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) { if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(getContext().getString(R.string.confirmation)); builder.setTitle(getContext().getString(R.string.confirmation));
builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); builder.setMessage(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
builder.setPositiveButton(getContext().getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(getContext().getString(R.string.ok), (dialog, id) -> {
public void onClick(DialogInterface dialog, int id) { hideTempRecommendation();
hideTempRecommendation(); clearNotification();
clearNotification(); MainApp.getConfigBuilder().applyTBRRequest(finalLastRun.constraintsProcessed, profile, new Callback() {
MainApp.getConfigBuilder().applyTBRRequest(finalLastRun.constraintsProcessed, profile, new Callback() { @Override
@Override public void run() {
public void run() { if (result.enacted) {
if (result.enacted) { finalLastRun.tbrSetByPump = result;
finalLastRun.tbrSetByPump = result; finalLastRun.lastEnact = new Date();
finalLastRun.lastEnact = new Date(); finalLastRun.lastOpenModeAccept = new Date();
finalLastRun.lastOpenModeAccept = new Date(); NSUpload.uploadDeviceStatus();
NSUpload.uploadDeviceStatus(); ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class);
ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); if (objectivesPlugin != null) {
if (objectivesPlugin != null) { ObjectivesPlugin.manualEnacts++;
ObjectivesPlugin.manualEnacts++; ObjectivesPlugin.saveProgress();
ObjectivesPlugin.saveProgress();
}
} }
scheduleUpdateGUI("onClickAcceptTemp");
} }
}); scheduleUpdateGUI("onClickAcceptTemp");
FabricPrivacy.getInstance().logCustom(new CustomEvent("AcceptTemp")); }
} });
FabricPrivacy.getInstance().logCustom(new CustomEvent("AcceptTemp"));
}); });
builder.setNegativeButton(getContext().getString(R.string.cancel), null); builder.setNegativeButton(getContext().getString(R.string.cancel), null);
builder.show(); builder.show();
@ -768,57 +767,55 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
accepted = false; accepted = false;
builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmMessage); builder.setMessage(confirmMessage);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { builder.setPositiveButton(getString(R.string.ok), (dialog, id) -> {
public void onClick(DialogInterface dialog, int id) { synchronized (builder) {
synchronized (builder) { if (accepted) {
if (accepted) { log.debug("guarding: already accepted");
log.debug("guarding: already accepted"); return;
return; }
} accepted = true;
accepted = true; if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) { if (wizard.superBolus) {
if (wizard.superBolus) { final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); if (loopPlugin.isEnabled(PluginType.LOOP)) {
if (activeloop != null) { loopPlugin.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000);
activeloop.superBolusTo(System.currentTimeMillis() + 2 * 60L * 60 * 1000); MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
MainApp.bus().post(new EventRefreshOverview("WizardDialog"));
}
ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
} }
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); ConfigBuilderPlugin.getCommandQueue().tempBasalPercent(0, 120, true, profile, new Callback() {
detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.boluscalc = boluscalcJSON;
detailedBolusInfo.source = Source.USER;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override @Override
public void run() { public void run() {
if (!result.success) { if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror); i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment); i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i); MainApp.instance().startActivity(i);
} }
} }
}); });
FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard"));
} }
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.eventType = CareportalEvent.BOLUSWIZARD;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.boluscalc = boluscalcJSON;
detailedBolusInfo.source = Source.USER;
ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
FabricPrivacy.getInstance().logCustom(new CustomEvent("QuickWizard"));
} }
} }
}); });
@ -902,6 +899,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
scheduleUpdateGUI("EventTempTargetChange"); scheduleUpdateGUI("EventTempTargetChange");
} }
@Subscribe
public void onStatusEvent(final EventProfileSwitchChange ev) {
scheduleUpdateGUI("EventProfileSwitchChange");
}
@Subscribe @Subscribe
public void onStatusEvent(final EventPumpStatusChanged s) { public void onStatusEvent(final EventPumpStatusChanged s) {
Activity activity = getActivity(); Activity activity = getActivity();
@ -1024,24 +1026,24 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
apsModeView.setVisibility(View.VISIBLE); apsModeView.setVisibility(View.VISIBLE);
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopenabled)); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.loopenabled));
apsModeView.setTextColor(Color.BLACK); apsModeView.setTextColor(Color.BLACK);
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuperBolus()) { if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuperBolus()) {
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended));
apsModeView.setText(String.format(MainApp.gs(R.string.loopsuperbolusfor), activeloop.minutesToEndOfSuspend())); apsModeView.setText(String.format(MainApp.gs(R.string.loopsuperbolusfor), loopPlugin.minutesToEndOfSuspend()));
apsModeView.setTextColor(Color.WHITE); apsModeView.setTextColor(Color.WHITE);
} else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isDisconnected()) { } else if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isDisconnected()) {
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended));
apsModeView.setText(String.format(MainApp.gs(R.string.loopdisconnectedfor), activeloop.minutesToEndOfSuspend())); apsModeView.setText(String.format(MainApp.gs(R.string.loopdisconnectedfor), loopPlugin.minutesToEndOfSuspend()));
apsModeView.setTextColor(Color.WHITE); apsModeView.setTextColor(Color.WHITE);
} else if (activeloop != null && activeloop.isEnabled(activeloop.getType()) && activeloop.isSuspended()) { } else if (loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuspended()) {
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended));
apsModeView.setText(String.format(MainApp.gs(R.string.loopsuspendedfor), activeloop.minutesToEndOfSuspend())); apsModeView.setText(String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()));
apsModeView.setTextColor(Color.WHITE); apsModeView.setTextColor(Color.WHITE);
} else if (pump.isSuspended()) { } else if (pump.isSuspended()) {
apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended)); apsModeView.setBackgroundColor(MainApp.sResources.getColor(R.color.looppumpsuspended));
apsModeView.setText(MainApp.gs(R.string.pumpsuspended)); apsModeView.setText(MainApp.gs(R.string.pumpsuspended));
apsModeView.setTextColor(Color.WHITE); apsModeView.setTextColor(Color.WHITE);
} else if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { } else if (loopPlugin.isEnabled(PluginType.LOOP)) {
if (closedLoopEnabled.value()) { if (closedLoopEnabled.value()) {
apsModeView.setText(MainApp.gs(R.string.closedloop)); apsModeView.setText(MainApp.gs(R.string.closedloop));
} else { } else {
@ -1077,7 +1079,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result showAcceptButton = showAcceptButton && (finalLastRun.lastOpenModeAccept == null || finalLastRun.lastOpenModeAccept.getTime() < finalLastRun.lastAPSRun.getTime()); // never accepted or before last result
showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested showAcceptButton = showAcceptButton && finalLastRun.constraintsProcessed.isChangeRequested(); // change is requested
if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && ConfigBuilderPlugin.getActiveLoop() != null) { if (showAcceptButton && pump.isInitialized() && !pump.isSuspended() && LoopPlugin.getPlugin().isEnabled(PluginType.LOOP)) {
acceptTempLayout.setVisibility(View.VISIBLE); acceptTempLayout.setVisibility(View.VISIBLE);
acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); acceptTempButton.setText(getContext().getString(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
} else { } else {

View file

@ -172,7 +172,7 @@ public class GraphData {
lastAbsoluteLineBasal = absoluteLineValue; lastAbsoluteLineBasal = absoluteLineValue;
lastLineBasal = baseBasalValue; lastLineBasal = baseBasalValue;
lastTempBasal = tempBasalValue; lastTempBasal = tempBasalValue;
maxBasalValueFound = Math.max(maxBasalValueFound, basal); maxBasalValueFound = Math.max(maxBasalValueFound, Math.max(tempBasalValue, baseBasalValue));
} }
basalLineArray.add(new ScaledDataPoint(toTime, lastLineBasal, basalScale)); basalLineArray.add(new ScaledDataPoint(toTime, lastLineBasal, basalScale));

View file

@ -1,7 +1,5 @@
package info.nightscout.androidaps.plugins.ProfileLocal; package info.nightscout.androidaps.plugins.ProfileLocal;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import org.json.JSONArray; import org.json.JSONArray;
@ -70,18 +68,15 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface {
} }
public synchronized void storeSettings() { public synchronized void storeSettings() {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext()); SP.putBoolean(LOCAL_PROFILE + "mmol", mmol);
SharedPreferences.Editor editor = settings.edit(); SP.putBoolean(LOCAL_PROFILE + "mgdl", mgdl);
editor.putBoolean(LOCAL_PROFILE + "mmol", mmol); SP.putString(LOCAL_PROFILE + "dia", dia.toString());
editor.putBoolean(LOCAL_PROFILE + "mgdl", mgdl); SP.putString(LOCAL_PROFILE + "ic", ic.toString());
editor.putString(LOCAL_PROFILE + "dia", dia.toString()); SP.putString(LOCAL_PROFILE + "isf", isf.toString());
editor.putString(LOCAL_PROFILE + "ic", ic.toString()); SP.putString(LOCAL_PROFILE + "basal", basal.toString());
editor.putString(LOCAL_PROFILE + "isf", isf.toString()); SP.putString(LOCAL_PROFILE + "targetlow", targetLow.toString());
editor.putString(LOCAL_PROFILE + "basal", basal.toString()); SP.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString());
editor.putString(LOCAL_PROFILE + "targetlow", targetLow.toString());
editor.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString());
editor.apply();
createAndStoreConvertedProfile(); createAndStoreConvertedProfile();
edited = false; edited = false;
if (Config.logPrefsChange) if (Config.logPrefsChange)

View file

@ -279,8 +279,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Status")); FabricPrivacy.getInstance().logCustom(new CustomEvent("SMS_Loop_Status"));
break; break;
case "RESUME": case "RESUME":
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); LoopPlugin.getPlugin().suspendTo(0);
activeloop.suspendTo(0);
MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_RESUME")); MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_RESUME"));
NSUpload.uploadOpenAPSOffline(0); NSUpload.uploadOpenAPSOffline(0);
reply = MainApp.sResources.getString(R.string.smscommunicator_loopresumed); reply = MainApp.sResources.getString(R.string.smscommunicator_loopresumed);
@ -517,8 +516,7 @@ public class SmsCommunicatorPlugin extends PluginBase {
@Override @Override
public void run() { public void run() {
if (result.success) { if (result.success) {
final LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000);
activeloop.suspendTo(System.currentTimeMillis() + suspendWaitingForConfirmation.duration * 60L * 1000);
NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60); NSUpload.uploadOpenAPSOffline(suspendWaitingForConfirmation.duration * 60);
MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); MainApp.bus().post(new EventRefreshOverview("SMS_LOOP_SUSPENDED"));
String reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " + String reply = MainApp.sResources.getString(R.string.smscommunicator_loopsuspended) + " " +

View file

@ -12,6 +12,8 @@ import info.nightscout.androidaps.interfaces.PluginType;
public class SourceXdripPlugin extends PluginBase implements BgSourceInterface { public class SourceXdripPlugin extends PluginBase implements BgSourceInterface {
private static SourceXdripPlugin plugin = null; private static SourceXdripPlugin plugin = null;
boolean advancedFiltering;
public static SourceXdripPlugin getPlugin() { public static SourceXdripPlugin getPlugin() {
if (plugin == null) if (plugin == null)
@ -29,6 +31,10 @@ public class SourceXdripPlugin extends PluginBase implements BgSourceInterface {
@Override @Override
public boolean advancedFilteringSupported() { public boolean advancedFilteringSupported() {
return false; return advancedFiltering;
}
public void setSource(String source) {
this.advancedFiltering = "G5 Native".equals(source);
} }
} }

View file

@ -452,7 +452,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
//log.debug("Adding new Treatment record" + carbsTreatment); //log.debug("Adding new Treatment record" + carbsTreatment);
} }
if (newRecordCreated && detailedBolusInfo.isValid) if (newRecordCreated && detailedBolusInfo.isValid)
NSUpload.uploadBolusWizardRecord(detailedBolusInfo); NSUpload.uploadTreatmentRecord(detailedBolusInfo);
return newRecordCreated; return newRecordCreated;
} }
@ -505,6 +505,13 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
} }
} }
@Override
public void addToHistoryTempTarget(TempTarget tempTarget) {
//log.debug("Adding new TemporaryBasal record" + profileSwitch.log());
MainApp.getDbHelper().createOrUpdate(tempTarget);
NSUpload.uploadTempTarget(tempTarget);
}
// Profile Switch // Profile Switch
@Subscribe @Subscribe
@SuppressWarnings("unused") @SuppressWarnings("unused")

View file

@ -89,6 +89,10 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View.
holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
else else
holder.iob.setTextColor(holder.carbs.getCurrentTextColor()); holder.iob.setTextColor(holder.carbs.getCurrentTextColor());
if (t.date > DateUtil.now())
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorScheduled));
else
holder.date.setTextColor(holder.carbs.getCurrentTextColor());
holder.remove.setTag(t); holder.remove.setTag(t);
} }

View file

@ -84,14 +84,10 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements
holder.reasonLabel.setText(""); holder.reasonLabel.setText("");
holder.reasonColon.setText(""); holder.reasonColon.setText("");
} }
if (tempTarget.isInProgress()) { if (tempTarget.isInProgress() && tempTarget == currentlyActiveTarget) {
if (tempTarget == currentlyActiveTarget) { holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
// active as newest } else if (tempTarget.date > DateUtil.now()) {
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorInProgress)); holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorScheduled));
} else {
// other's that might become active again after the latest (overlapping) is over
holder.date.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive));
}
} else { } else {
holder.date.setTextColor(holder.reasonColon.getCurrentTextColor()); holder.date.setTextColor(holder.reasonColon.getCurrentTextColor());
} }

View file

@ -441,21 +441,21 @@ public class ActionStringHandler {
private static String getLoopStatus() { private static String getLoopStatus() {
String ret = ""; String ret = "";
// decide if enabled/disabled closed/open; what Plugin as APS? // decide if enabled/disabled closed/open; what Plugin as APS?
final LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); final LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (activeloop != null && activeloop.isEnabled(activeloop.getType())) { if (loopPlugin.isEnabled(loopPlugin.getType())) {
if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) { if (MainApp.getConstraintChecker().isClosedLoopAllowed().value()) {
ret += "CLOSED LOOP\n"; ret += "CLOSED LOOP\n";
} else { } else {
ret += "OPEN LOOP\n"; ret += "OPEN LOOP\n";
} }
final APSInterface aps = MainApp.getConfigBuilder().getActiveAPS(); final APSInterface aps = ConfigBuilderPlugin.getActiveAPS();
ret += "APS: " + ((aps == null) ? "NO APS SELECTED!" : ((PluginBase) aps).getName()); ret += "APS: " + ((aps == null) ? "NO APS SELECTED!" : ((PluginBase) aps).getName());
if (activeloop.lastRun != null) { if (LoopPlugin.lastRun != null) {
if (activeloop.lastRun.lastAPSRun != null) if (LoopPlugin.lastRun.lastAPSRun != null)
ret += "\nLast Run: " + DateUtil.timeString(activeloop.lastRun.lastAPSRun); ret += "\nLast Run: " + DateUtil.timeString(LoopPlugin.lastRun.lastAPSRun);
if (activeloop.lastRun.lastEnact != null) if (LoopPlugin.lastRun.lastEnact != null)
ret += "\nLast Enact: " + DateUtil.timeString(activeloop.lastRun.lastEnact); ret += "\nLast Enact: " + DateUtil.timeString(LoopPlugin.lastRun.lastEnact);
} }
@ -502,7 +502,7 @@ public class ActionStringHandler {
return "No profile set :("; return "No profile set :(";
} }
APSInterface usedAPS = MainApp.getConfigBuilder().getActiveAPS(); APSInterface usedAPS = ConfigBuilderPlugin.getActiveAPS();
if (usedAPS == null) { if (usedAPS == null) {
return "No active APS :(!"; return "No active APS :(!";
} }
@ -622,10 +622,7 @@ public class ActionStringHandler {
} else { } else {
tempTarget.low(0).high(0); tempTarget.low(0).high(0);
} }
MainApp.getDbHelper().createOrUpdate(tempTarget); TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
//TODO: Nightscout-Treatment for Temp-Target!
//ConfigBuilderPlugin.uploadCareportalEntryToNS(data);
} }
private static void doFillBolus(final Double amount) { private static void doFillBolus(final Double amount) {

View file

@ -140,11 +140,7 @@ public class WearPlugin extends PluginBase {
@Subscribe @Subscribe
public void onStatusEvent(final EventRefreshOverview ev) { public void onStatusEvent(final EventRefreshOverview ev) {
if (WatchUpdaterService.shouldReportLoopStatus(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) {
LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop();
if (activeloop == null) return;
if (WatchUpdaterService.shouldReportLoopStatus(activeloop.isEnabled(PluginType.LOOP))) {
sendDataToWatch(true, false, false); sendDataToWatch(true, false, false);
} }
} }

View file

@ -666,12 +666,12 @@ public class WatchUpdaterService extends WearableListenerService implements
return status; return status;
} }
LoopPlugin activeloop = MainApp.getConfigBuilder().getActiveLoop(); LoopPlugin activeloop = LoopPlugin.getPlugin();
if (activeloop != null && !activeloop.isEnabled(PluginType.LOOP)) { if (!activeloop.isEnabled(PluginType.LOOP)) {
status += getString(R.string.disabledloop) + "\n"; status += getString(R.string.disabledloop) + "\n";
lastLoopStatus = false; lastLoopStatus = false;
} else if (activeloop != null && activeloop.isEnabled(PluginType.LOOP)) { } else {
lastLoopStatus = true; lastLoopStatus = true;
} }

View file

@ -108,12 +108,12 @@ public class StatuslinePlugin extends PluginBase {
@NonNull @NonNull
private String buildStatusString(Profile profile) { private String buildStatusString(Profile profile) {
String status = ""; String status = "";
LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop(); LoopPlugin loopPlugin = LoopPlugin.getPlugin();
if (activeloop != null && !activeloop.isEnabled(PluginType.LOOP)) { if (!loopPlugin.isEnabled(PluginType.LOOP)) {
status += ctx.getString(R.string.disabledloop) + "\n"; status += ctx.getString(R.string.disabledloop) + "\n";
lastLoopStatus = false; lastLoopStatus = false;
} else if (activeloop != null && activeloop.isEnabled(PluginType.LOOP)) { } else if (loopPlugin.isEnabled(PluginType.LOOP)) {
lastLoopStatus = true; lastLoopStatus = true;
} }
@ -179,13 +179,8 @@ public class StatuslinePlugin extends PluginBase {
@Subscribe @Subscribe
public void onStatusEvent(final EventRefreshOverview ev) { public void onStatusEvent(final EventRefreshOverview ev) {
//Filter events where loop is (de)activated //Filter events where loop is (de)activated
if ((lastLoopStatus != LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) {
LoopPlugin activeloop = ConfigBuilderPlugin.getActiveLoop();
if (activeloop == null) return;
if ((lastLoopStatus != activeloop.isEnabled(PluginType.LOOP))) {
sendStatus(); sendStatus();
} }
} }

View file

@ -166,14 +166,19 @@ public class CommandQueue {
public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) {
Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS; Command.CommandType type = detailedBolusInfo.isSMB ? Command.CommandType.SMB_BOLUS : Command.CommandType.BOLUS;
if (isRunning(type)) { if(type.equals(Command.CommandType.BOLUS) && detailedBolusInfo.carbs > 0 && detailedBolusInfo.insulin == 0){
if (callback != null) type = Command.CommandType.CARBS_ONLY_TREATMENT;
callback.result(executingNowError()).run(); //Carbs only can be added in parallel as they can be "in the future".
return false; } else {
} if (isRunning(type)) {
if (callback != null)
callback.result(executingNowError()).run();
return false;
}
// remove all unfinished boluses // remove all unfinished boluses
removeAll(type); removeAll(type);
}
// apply constraints // apply constraints
detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value(); detailedBolusInfo.insulin = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
@ -183,12 +188,14 @@ public class CommandQueue {
if (detailedBolusInfo.isSMB) { if (detailedBolusInfo.isSMB) {
add(new CommandSMBBolus(detailedBolusInfo, callback)); add(new CommandSMBBolus(detailedBolusInfo, callback));
} else { } else {
add(new CommandBolus(detailedBolusInfo, callback)); add(new CommandBolus(detailedBolusInfo, callback, type));
// Bring up bolus progress dialog (start here, so the dialog is shown when the bolus is requested, if(type.equals(Command.CommandType.BOLUS)) {
// not when the Bolus command is starting. The command closes the dialog upon completion). // Bring up bolus progress dialog (start here, so the dialog is shown when the bolus is requested,
showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context); // not when the Bolus command is starting. The command closes the dialog upon completion).
// Notify Wear about upcoming bolus showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context);
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); // Notify Wear about upcoming bolus
MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin));
}
} }
notifyAboutNewCommand(); notifyAboutNewCommand();

View file

@ -53,6 +53,12 @@ public class QueueThread extends Thread {
try { try {
while (true) { while (true) {
PumpInterface pump = ConfigBuilderPlugin.getActivePump(); PumpInterface pump = ConfigBuilderPlugin.getActivePump();
if (pump == null) {
log.debug("QUEUE: pump == null");
MainApp.bus().post(new EventPumpStatusChanged(MainApp.sResources.getString(R.string.pumpNotInitialized)));
SystemClock.sleep(1000);
continue;
}
long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000;
if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) { if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) {

View file

@ -12,6 +12,7 @@ public abstract class Command {
public enum CommandType { public enum CommandType {
BOLUS, BOLUS,
SMB_BOLUS, SMB_BOLUS,
CARBS_ONLY_TREATMENT,
TEMPBASAL, TEMPBASAL,
EXTENDEDBOLUS, EXTENDEDBOLUS,
BASALPROFILE, BASALPROFILE,

View file

@ -16,8 +16,8 @@ import info.nightscout.utils.DecimalFormatter;
public class CommandBolus extends Command { public class CommandBolus extends Command {
DetailedBolusInfo detailedBolusInfo; DetailedBolusInfo detailedBolusInfo;
public CommandBolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { public CommandBolus(DetailedBolusInfo detailedBolusInfo, Callback callback, CommandType type) {
commandType = CommandType.BOLUS; commandType = type;
this.detailedBolusInfo = detailedBolusInfo; this.detailedBolusInfo = detailedBolusInfo;
this.callback = callback; this.callback = callback;
} }

View file

@ -0,0 +1,46 @@
package info.nightscout.androidaps.startupwizard;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.NSClientInternal.NSClientPlugin;
import info.nightscout.utils.SP;
public class SWDefinition {
private static SWDefinition swDefinition = null;
public static SWDefinition getInstance() {
if (swDefinition == null)
swDefinition = new SWDefinition();
return swDefinition;
}
static List<SWScreen> screens = new ArrayList<>();
public static List<SWScreen> getScreens() {
return screens;
}
SWDefinition add(SWScreen newScreen) {
screens.add(newScreen);
return this;
}
SWDefinition() {
add(new SWScreen(R.string.nsclientinternal_title)
.skippable(false)
.add(new SWUrl().preferenceId(R.string.key_nsclientinternal_url).label(R.string.nsclientinternal_url_title).comment(R.string.nsclientinternal_url_dialogmessage))
.add(new SWString().preferenceId(R.string.key_nsclientinternal_api_secret).label(R.string.nsclientinternal_secret_dialogtitle).comment(R.string.nsclientinternal_secret_dialogmessage))
.validator(() -> NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)
)
.add(new SWScreen(R.string.patientage)
.skippable(false)
.add(new SWRadioButton().option(R.array.ageArray, R.array.ageValues).preferenceId(R.string.key_age).label(R.string.patientage).comment(R.string.patientage_summary))
.validator(() -> SP.contains(R.string.key_age))
)
;
}
}

View file

@ -0,0 +1,62 @@
package info.nightscout.androidaps.startupwizard;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.utils.SP;
public class SWItem {
enum Type {
NONE,
URL,
STRING,
NUMBER,
DECIMALNUMBER,
CHECKBOX,
RADIOBUTTON
}
Type type;
Integer label;
Integer comment;
int preferenceId;
public SWItem(Type type) {
this.type = type;
}
String getLabel() {
return MainApp.gs(label);
}
String getComment() {
if (comment != null)
return MainApp.gs(comment);
else
return "";
}
Type getType() {
return type;
}
public SWItem label(int label) {
this.label = label;
return this;
}
public SWItem comment(int comment) {
this.comment = comment;
return this;
}
SWItem preferenceId(int preferenceId) {
this.preferenceId = preferenceId;
return this;
}
public void save(String value) {
SP.putString(preferenceId, value);
MainApp.bus().post(new EventPreferenceChange(preferenceId));
}
}

View file

@ -0,0 +1,28 @@
package info.nightscout.androidaps.startupwizard;
import info.nightscout.androidaps.MainApp;
public class SWRadioButton extends SWItem {
int labelsArray;
int valuesArray;
public SWRadioButton() {
super(Type.RADIOBUTTON);
}
public SWRadioButton option(int labels, int values) {
this.labelsArray = labels;
this.valuesArray = values;
return this;
}
public String[] labels() {
return MainApp.sResources.getStringArray(labelsArray);
}
public String[] values() {
return MainApp.sResources.getStringArray(valuesArray);
}
}

View file

@ -0,0 +1,43 @@
package info.nightscout.androidaps.startupwizard;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
public class SWScreen {
int header;
List<SWItem> items = new ArrayList<>();
SWValidator validator;
boolean skippable = false;
public SWScreen(int header) {
this.header = header;
}
public String getHeader() {
return MainApp.gs(header);
}
public SWScreen skippable(boolean skippable) {
this.skippable = skippable;
return this;
}
public SWScreen add(SWItem newItem) {
items.add(newItem);
return this;
}
public SWScreen validator(SWValidator validator) {
this.validator = validator;
return this;
}
boolean isValid() {
if (validator != null)
return validator.isValid();
return true;
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.startupwizard;
public class SWString extends SWItem {
public SWString() {
super(Type.STRING);
}
}

View file

@ -0,0 +1,8 @@
package info.nightscout.androidaps.startupwizard;
public class SWUrl extends SWItem {
public SWUrl() {
super(Type.URL);
}
}

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.startupwizard;
public interface SWValidator {
boolean isValid();
}

View file

@ -0,0 +1,165 @@
package info.nightscout.androidaps.startupwizard;
import android.annotation.SuppressLint;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import info.nightscout.androidaps.R;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
public class SetupWizardActivity extends AppCompatActivity {
/**
* Whether or not the system UI should be auto-hidden after
* {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300;
private final Handler mHideHandler = new Handler();
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable() {
@SuppressLint("InlinedApi")
@Override
public void run() {
// Delayed removal of status and navigation bar
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
};
private View mControlsView;
private final Runnable mShowPart2Runnable = new Runnable() {
@Override
public void run() {
// Delayed display of UI elements
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
mControlsView.setVisibility(View.VISIBLE);
}
};
private boolean mVisible;
private final Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
hide();
}
};
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
private final View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setupwizard);
mVisible = true;
mControlsView = findViewById(R.id.fullscreen_content_controls);
mContentView = findViewById(R.id.fullscreen_content);
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
toggle();
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide(100);
}
private void toggle() {
if (mVisible) {
hide();
} else {
show();
}
}
private void hide() {
// Hide UI first
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
mControlsView.setVisibility(View.GONE);
mVisible = false;
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler.removeCallbacks(mShowPart2Runnable);
mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}
@SuppressLint("InlinedApi")
private void show() {
// Show the system bar
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mVisible = true;
// Schedule a runnable to display UI elements after a delay
mHideHandler.removeCallbacks(mHidePart2Runnable);
mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
}
/**
* Schedules a call to hide() in delay milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
}

View file

@ -0,0 +1,90 @@
package info.nightscout.utils;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R;
public class DefaultValueHelper {
/**
* returns the corresponding EatingSoon TempTarget based on the given units (MMOL / MGDL)
*
* @param units
* @return
*/
public double getDefaultEatingSoonTT(String units) {
return Constants.MMOL.equals(units) ? Constants.defaultEatingSoonTTmmol
: Constants.defaultEatingSoonTTmgdl;
}
/**
* returns the corresponding Activity TempTarget based on the given units (MMOL / MGDL)
*
* @param units
* @return
*/
public double getDefaultActivityTT(String units) {
return Constants.MMOL.equals(units) ? Constants.defaultActivityTTmmol
: Constants.defaultActivityTTmgdl;
}
/**
* returns the corresponding Hypo TempTarget based on the given units (MMOL / MGDL)
*
* @param units
* @return
*/
public double getDefaultHypoTT(String units) {
return Constants.MMOL.equals(units) ? Constants.defaultHypoTTmmol
: Constants.defaultHypoTTmgdl;
}
/**
* returns the configured EatingSoon TempTarget, if this is set to 0, the Default-Value is returned.
*
* @param units
* @return
*/
public double determineEatingSoonTT(String units) {
double value = SP.getDouble(R.string.key_eatingsoon_target, this.getDefaultEatingSoonTT(units));
return value > 0 ? value : this.getDefaultEatingSoonTT(units);
}
public int determineEatingSoonTTDuration() {
int value = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration);
return value > 0 ? value : Constants.defaultEatingSoonTTDuration;
}
/**
* returns the configured Activity TempTarget, if this is set to 0, the Default-Value is returned.
*
* @param units
* @return
*/
public double determineActivityTT(String units) {
double value = SP.getDouble(R.string.key_activity_target, this.getDefaultActivityTT(units));
return value > 0 ? value : this.getDefaultActivityTT(units);
}
public int determineActivityTTDuration() {
int value = SP.getInt(R.string.key_activity_duration, Constants.defaultActivityTTDuration);
return value > 0 ? value : Constants.defaultActivityTTDuration;
}
/**
* returns the configured Hypo TempTarget, if this is set to 0, the Default-Value is returned.
*
* @param units
* @return
*/
public double determineHypoTT(String units) {
double value = SP.getDouble(R.string.key_hypo_target, this.getDefaultHypoTT(units));
return value > 0 ? value : this.getDefaultHypoTT(units);
}
public int determineHypoTTDuration() {
int value = SP.getInt(R.string.key_hypo_duration, Constants.defaultHypoTTDuration);
return value > 0 ? value : Constants.defaultHypoTTDuration;
}
}

View file

@ -1,5 +1,7 @@
package info.nightscout.utils; package info.nightscout.utils;
import android.support.annotation.Nullable;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -17,6 +19,20 @@ public class JsonHelper {
private JsonHelper() {}; private JsonHelper() {};
public static Object safeGetObject(JSONObject json, String fieldName, Object defaultValue) {
Object result = defaultValue;
if (json.has(fieldName)) {
try {
result = json.get(fieldName);
} catch (JSONException ignored) {
}
}
return result;
}
@Nullable
public static String safeGetString(JSONObject json, String fieldName) { public static String safeGetString(JSONObject json, String fieldName) {
String result = null; String result = null;

View file

@ -13,10 +13,10 @@ import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.receivers.KeepAliveReceiver;
import info.nightscout.utils.NSUpload;
/** /**
* Created by adrian on 17/12/17. * Created by adrian on 17/12/17.
@ -25,12 +25,12 @@ import info.nightscout.utils.NSUpload;
public class LocalAlertUtils { public class LocalAlertUtils {
private static Logger log = LoggerFactory.getLogger(LocalAlertUtils.class); private static Logger log = LoggerFactory.getLogger(LocalAlertUtils.class);
public static int missedReadingsThreshold() { public static long missedReadingsThreshold() {
return SP.getInt(MainApp.sResources.getString(R.string.key_missed_bg_readings_threshold), 30) * 60 * 1000; return T.mins(SP.getInt(MainApp.sResources.getString(R.string.key_missed_bg_readings_threshold), 30)).msecs();
} }
private static int pumpUnreachableThreshold() { private static long pumpUnreachableThreshold() {
return SP.getInt(MainApp.sResources.getString(R.string.key_pump_unreachable_threshold), 30) * 60 * 1000; return T.mins(SP.getInt(MainApp.sResources.getString(R.string.key_pump_unreachable_threshold), 30)).msecs();
} }
public static void checkPumpUnreachableAlarm(Date lastConnection, boolean isStatusOutdated) { public static void checkPumpUnreachableAlarm(Date lastConnection, boolean isStatusOutdated) {
@ -38,7 +38,7 @@ public class LocalAlertUtils {
boolean nextAlarmOccurrenceReached = SP.getLong("nextPumpDisconnectedAlarm", 0L) < System.currentTimeMillis(); boolean nextAlarmOccurrenceReached = SP.getLong("nextPumpDisconnectedAlarm", 0L) < System.currentTimeMillis();
if (Config.APS && SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_pump_unreachable_alert), true) if (Config.APS && SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_pump_unreachable_alert), true)
&& isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !ConfigBuilderPlugin.getActiveLoop().isDisconnected()) { && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached && !LoopPlugin.getPlugin().isDisconnected()) {
log.debug("Generating pump unreachable alarm. lastConnection: " + DateUtil.dateAndTimeString(lastConnection) + " isStatusOutdated: " + isStatusOutdated); log.debug("Generating pump unreachable alarm. lastConnection: " + DateUtil.dateAndTimeString(lastConnection) + " isStatusOutdated: " + isStatusOutdated);
Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.sResources.getString(R.string.pump_unreachable), Notification.URGENT); Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.sResources.getString(R.string.pump_unreachable), Notification.URGENT);
n.soundId = R.raw.alarm; n.soundId = R.raw.alarm;
@ -48,11 +48,13 @@ public class LocalAlertUtils {
NSUpload.uploadError(n.text); NSUpload.uploadError(n.text);
} }
} }
if (!isStatusOutdated && !alarmTimeoutExpired)
MainApp.bus().post(new EventDismissNotification(Notification.PUMP_UNREACHABLE));
} }
/*Presnoozes the alarms with 5 minutes if no snooze exists. /*Presnoozes the alarms with 5 minutes if no snooze exists.
* Call only at startup! * Call only at startup!
*/ */
public static void presnoozeAlarms() { public static void presnoozeAlarms() {
if (SP.getLong("nextMissedReadingsAlarm", 0l) < System.currentTimeMillis()) { if (SP.getLong("nextMissedReadingsAlarm", 0l) < System.currentTimeMillis()) {
SP.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + 5 * 60 * 1000); SP.putLong("nextMissedReadingsAlarm", System.currentTimeMillis() + 5 * 60 * 1000);
@ -73,7 +75,7 @@ public class LocalAlertUtils {
SP.putLong("nextPumpDisconnectedAlarm", nextPumpDisconnectedAlarm); SP.putLong("nextPumpDisconnectedAlarm", nextPumpDisconnectedAlarm);
} }
public static void notifyPumpStatusRead(){ public static void notifyPumpStatusRead() {
//TODO: persist the actual time the pump is read and simplify the whole logic when to alarm //TODO: persist the actual time the pump is read and simplify the whole logic when to alarm
final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); final PumpInterface pump = ConfigBuilderPlugin.getActivePump();

View file

@ -7,7 +7,9 @@ import android.content.pm.ResolveInfo;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -28,6 +30,7 @@ import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.plugins.Loop.APSResult;
@ -256,7 +259,7 @@ public class NSUpload {
} }
} }
public static void uploadBolusWizardRecord(DetailedBolusInfo detailedBolusInfo) { public static void uploadTreatmentRecord(DetailedBolusInfo detailedBolusInfo) {
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
try { try {
data.put("eventType", detailedBolusInfo.eventType); data.put("eventType", detailedBolusInfo.eventType);
@ -275,6 +278,9 @@ public class NSUpload {
data.put("boluscalc", detailedBolusInfo.boluscalc); data.put("boluscalc", detailedBolusInfo.boluscalc);
if (detailedBolusInfo.carbTime != 0) if (detailedBolusInfo.carbTime != 0)
data.put("preBolus", detailedBolusInfo.carbTime); data.put("preBolus", detailedBolusInfo.carbTime);
if (!StringUtils.isEmpty(detailedBolusInfo.notes)) {
data.put("notes", detailedBolusInfo.notes);
}
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
@ -302,6 +308,30 @@ public class NSUpload {
} }
} }
public static void uploadTempTarget(TempTarget tempTarget) {
try {
Profile profile = MainApp.getConfigBuilder().getProfile();
if (profile == null) {
log.error("Profile is null. Skipping upload");
return;
}
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPORARYTARGET);
data.put("duration", tempTarget.durationInMinutes);
data.put("reason", tempTarget.reason);
data.put("targetBottom", Profile.fromMgdlToUnits(tempTarget.low, profile.getUnits()));
data.put("targetTop", Profile.fromMgdlToUnits(tempTarget.high, profile.getUnits()));
data.put("created_at", DateUtil.toISOString(tempTarget.date));
data.put("units", profile.getUnits());
data.put("enteredBy", MainApp.instance().getString(R.string.app_name));
uploadCareportalEntryToNS(data);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
public static void updateProfileSwitch(ProfileSwitch profileSwitch) { public static void updateProfileSwitch(ProfileSwitch profileSwitch) {
try { try {
JSONObject data = new JSONObject(); JSONObject data = new JSONObject();
@ -466,7 +496,7 @@ public class NSUpload {
try { try {
data.put("eventType", "Note"); data.put("eventType", "Note");
data.put("created_at", DateUtil.toISOString(new Date())); data.put("created_at", DateUtil.toISOString(new Date()));
data.put("notes", MainApp.sResources.getString(R.string.androidaps_start)); data.put("notes", MainApp.sResources.getString(R.string.androidaps_start)+" - "+ Build.MANUFACTURER + " "+ Build.MODEL);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }
@ -476,10 +506,10 @@ public class NSUpload {
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent); context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString()); DbLogger.dbAdd(intent, data.toString());
} }
} }
public static void uploadEvent(String careportalEvent, long time) { public static void uploadEvent(String careportalEvent, long time, @Nullable String notes) {
Context context = MainApp.instance().getApplicationContext(); Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd"); bundle.putString("action", "dbAdd");
@ -489,6 +519,9 @@ public class NSUpload {
data.put("eventType", careportalEvent); data.put("eventType", careportalEvent);
data.put("created_at", DateUtil.toISOString(time)); data.put("created_at", DateUtil.toISOString(time));
data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name))); data.put("enteredBy", SP.getString("careportal_enteredby", MainApp.gs(R.string.app_name)));
if (notes != null) {
data.put("notes", notes);
}
} catch (JSONException e) { } catch (JSONException e) {
log.error("Unhandled exception", e); log.error("Unhandled exception", e);
} }

View file

@ -5,6 +5,7 @@ import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -148,7 +149,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
} }
public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, TextWatcher textWatcher) { public void setParams(Double initValue, Double minValue, Double maxValue, Double step, NumberFormat formater, boolean allowZero, TextWatcher textWatcher) {
if(this.textWatcher != null) { if (this.textWatcher != null) {
editText.removeTextChangedListener(this.textWatcher); editText.removeTextChangedListener(this.textWatcher);
} }
setParams(initValue, minValue, maxValue, step, formater, allowZero); setParams(initValue, minValue, maxValue, step, formater, allowZero);
@ -164,6 +165,8 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
this.formater = formater; this.formater = formater;
this.allowZero = allowZero; this.allowZero = allowZero;
editText.setKeyListener(DigitsKeyListener.getInstance(minValue < 0, step != Math.rint(step)));
if (textWatcher != null) if (textWatcher != null)
editText.removeTextChangedListener(textWatcher); editText.removeTextChangedListener(textWatcher);
updateEditText(); updateEditText();
@ -202,7 +205,7 @@ public class NumberPicker extends LinearLayout implements View.OnKeyListener,
updateEditText(); updateEditText();
} }
private void dec( int multiplier) { private void dec(int multiplier) {
value -= step * multiplier; value -= step * multiplier;
if (value < minValue) { if (value < minValue) {
value = minValue; value = minValue;

View file

@ -16,6 +16,10 @@ public class SP {
return sharedPreferences.contains(key); return sharedPreferences.contains(key);
} }
static public boolean contains(int resourceId) {
return sharedPreferences.contains(MainApp.gs(resourceId));
}
static public String getString(int resourceID, String defaultValue) { static public String getString(int resourceID, String defaultValue) {
return sharedPreferences.getString(MainApp.sResources.getString(resourceID), defaultValue); return sharedPreferences.getString(MainApp.sResources.getString(resourceID), defaultValue);
} }
@ -24,7 +28,7 @@ public class SP {
return sharedPreferences.getString(key, defaultValue); return sharedPreferences.getString(key, defaultValue);
} }
static public boolean getBoolean(int resourceID, boolean defaultValue) { static public boolean getBoolean(int resourceID, Boolean defaultValue) {
try { try {
return sharedPreferences.getBoolean(MainApp.sResources.getString(resourceID), defaultValue); return sharedPreferences.getBoolean(MainApp.sResources.getString(resourceID), defaultValue);
} catch (Exception e) { } catch (Exception e) {
@ -32,7 +36,7 @@ public class SP {
} }
} }
static public boolean getBoolean(String key, boolean defaultValue) { static public boolean getBoolean(String key, Boolean defaultValue) {
try { try {
return sharedPreferences.getBoolean(key, defaultValue); return sharedPreferences.getBoolean(key, defaultValue);
} catch (Exception e) { } catch (Exception e) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,97 +1,153 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content">
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_gravity="center"
android:focusableInTouchMode="true" android:orientation="horizontal">
android:padding="10dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:padding="5dp"
android:src="@drawable/icon_cp_pump_canula" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:paddingBottom="10dp"
android:padding="5dp" android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="10dp"
android:text="@string/primefill" android:text="@string/primefill"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/colorInsulinButton" /> android:textColor="@color/colorInsulinButton" />
<ImageView </LinearLayout>
android:layout_width="match_parent"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<CheckBox
android:id="@+id/fill_catheter_change"
android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:padding="5dp" android:text="@string/careportal_pumpsitechange" />
android:layout_gravity="center_horizontal"
android:src="@drawable/icon_cp_pump_canula" />
<LinearLayout <CheckBox
android:id="@+id/careportal_newnstreatment_insulin_layout" android:id="@+id/fill_cartridge_change"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<CheckBox
android:id="@+id/catheter_change"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:text="Pump site change" />
<CheckBox
android:id="@+id/cartridge_change"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:text="Insulin cartridge change" />
<info.nightscout.utils.NumberPicker
android:id="@+id/treatments_newtreatment_insulinamount"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="end"
android:layout_marginBottom="10dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="10dp" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="5dp"> android:text="@string/careportal_insulincartridgechange" />
<Button
android:id="@+id/fill_preset_button1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0.3U" />
<Button
android:id="@+id/fill_preset_button2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0.7U" />
<Button
android:id="@+id/fill_preset_button3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="1.2U" />
</LinearLayout>
<include layout="@layout/mdtp_done_button" />
</LinearLayout> </LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="@color/listdelimiter" />
</ScrollView> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingTop="5dp">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:text="@string/overview_insulin_label" />
<info.nightscout.utils.NumberPicker
android:id="@+id/fill_insulinamount"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="end"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/insulin_unit_shortname" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/fill_preset_button1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0.3U" />
<Button
android:id="@+id/fill_preset_button2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="0.7U" />
<Button
android:id="@+id/fill_preset_button3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="1.2U" />
</LinearLayout>
<LinearLayout
android:id="@+id/fill_notes_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:width="60dp"
android:padding="2dp"
android:text="@string/careportal_newnstreatment_notes_label"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:textStyle="bold" />
<EditText
android:id="@+id/fill_notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text|textCapSentences" />
</LinearLayout>
<include layout="@layout/mdtp_done_button" />
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".startupwizard.SetupWizardActivity">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<TextView
android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:keepScreenOn="true"
android:text="@string/dummy_content"
android:textColor="#33b5e5"
android:textSize="50sp"
android:textStyle="bold" />
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/fullscreen_content_controls"
style="?metaButtonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/black_overlay"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button
android:id="@+id/dummy_button"
style="?metaButtonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button" />
</LinearLayout>
</FrameLayout>
</FrameLayout>

View file

@ -151,7 +151,7 @@
android:paddingLeft="10dp" android:paddingLeft="10dp"
android:paddingRight="10dp" android:paddingRight="10dp"
android:text="@string/activate_profile" android:text="@string/activate_profile"
android:textColor="@color/colorProfileSwitchButton" /> android:drawableLeft="@drawable/icon_local_activate" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -172,7 +172,7 @@
android:paddingLeft="10dp" android:paddingLeft="10dp"
android:paddingRight="10dp" android:paddingRight="10dp"
android:text="@string/reset" android:text="@string/reset"
android:textColor="@color/colorProfileSwitchButton" /> android:drawableLeft="@drawable/icon_local_reset" />
<Button <Button
android:id="@+id/localprofile_save" android:id="@+id/localprofile_save"
@ -188,7 +188,7 @@
android:paddingLeft="10dp" android:paddingLeft="10dp"
android:paddingRight="10dp" android:paddingRight="10dp"
android:text="@string/save" android:text="@string/save"
android:textColor="@color/colorProfileSwitchButton" /> android:drawableLeft="@drawable/icon_local_save" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View file

@ -23,8 +23,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="1" android:text="1"
android:textColor="@android:color/black" android:textColor="@android:color/black"
android:inputType="numberDecimal" android:inputType="number"
android:digits="0123456789.,"
android:gravity="center" android:gravity="center"
android:imeOptions="actionDone" android:imeOptions="actionDone"
/> />

View file

@ -11,6 +11,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -18,19 +19,32 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="10dp"> android:padding="10dp">
<TextView <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/carbs"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/colorCarbsButton" />
<ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:padding="5dp" android:layout_gravity="center"
android:src="@drawable/icon_cp_bolus_carbs" /> android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="5dp"
android:layout_gravity="center"
android:src="@drawable/icon_cp_bolus_carbs" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="10dp"
android:text="@string/carbs"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/colorCarbsButton" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -55,44 +69,102 @@
android:id="@+id/newcarbs_hypo_tt" android:id="@+id/newcarbs_hypo_tt"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:text="@string/start_hypo_tt" /> android:text="@string/start_hypo_tt" />
</LinearLayout> </LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="@color/listdelimiter" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingTop="5dp">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:text="@string/time" />
<info.nightscout.utils.NumberPicker
android:id="@+id/newcarbs_time"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="end"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/shortminute" />
</LinearLayout>
<LinearLayout
android:id="@+id/newcarbs_duration_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:text="@string/duration"/>
<info.nightscout.utils.NumberPicker
android:id="@+id/new_carbs_duration"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:layout_gravity="end" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/shorthour"/>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:paddingBottom="5dp"
android:padding="5dp"> android:paddingTop="5dp">
<TextView <TextView
android:id="@+id/newcarbs_eventdate" android:layout_width="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_vertical"
android:padding="5dp" android:textStyle="bold"
android:text="2017/05/05" /> android:text="@string/overview_carbs_label" />
<info.nightscout.utils.NumberPicker
android:id="@+id/newcarb_carbsamount"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="end"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<TextView <TextView
android:id="@+id/newcarb_eventtime"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_vertical"
android:padding="5dp" android:text="@string/shortgramm" />
android:text="08:20pm" />
</LinearLayout> </LinearLayout>
<info.nightscout.utils.NumberPicker
android:id="@+id/newcarb_carbsamount"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="end"
android:layout_marginBottom="10dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="10dp" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -122,9 +194,35 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/newcarbs_notes_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:width="60dp"
android:padding="2dp"
android:text="@string/careportal_newnstreatment_notes_label"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:textStyle="bold" />
<EditText
android:id="@+id/newcarbs_notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text|textCapSentences" />
</LinearLayout>
<include layout="@layout/mdtp_done_button" /> <include layout="@layout/mdtp_done_button" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</FrameLayout> </FrameLayout>

View file

@ -16,20 +16,31 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="10dp"> android:padding="10dp">
<TextView <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/overview_insulin_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/colorInsulinButton" />
<ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginTop="5dp" android:layout_gravity="center"
android:padding="5dp" android:orientation="horizontal">
android:src="@drawable/icon_bolus" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="5dp"
android:layout_gravity="center"
android:src="@drawable/icon_bolus" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="10dp"
android:textAlignment="center"
android:text="@string/overview_insulin_label"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@color/colorInsulinButton" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -52,46 +63,74 @@
</LinearLayout> </LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="@color/listdelimiter" />
<LinearLayout
android:id="@+id/newinsulin_time_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingTop="5dp">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:text="@string/time" />
<info.nightscout.utils.NumberPicker
android:id="@+id/newinsulin_time"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="end"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/shortminute" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:paddingBottom="5dp"
android:padding="5dp"> android:paddingTop="5dp">
<TextView <TextView
android:id="@+id/newinsulin_eventdate" android:layout_width="60dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_vertical"
android:enabled="false" android:textStyle="bold"
android:padding="5dp" android:text="@string/overview_insulin_label" />
android:text="2017/05/05" />
<info.nightscout.utils.NumberPicker
android:id="@+id/newinsulin_amount"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="end"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<TextView <TextView
android:id="@+id/newinsulin_eventtime"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_vertical"
android:enabled="false" android:text="@string/insulin_unit_shortname" />
android:padding="5dp"
android:text="08:20pm" />
</LinearLayout> </LinearLayout>
<info.nightscout.utils.NumberPicker
android:id="@+id/treatments_newinsulin_amount"
android:layout_width="130dp"
android:layout_height="40dp"
android:layout_gravity="end"
android:layout_marginBottom="10dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="10dp" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:orientation="horizontal"> android:orientation="horizontal">
<Button <Button
@ -117,6 +156,31 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/newinsulin_notes_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:width="60dp"
android:padding="2dp"
android:text="@string/careportal_newnstreatment_notes_label"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:textStyle="bold" />
<EditText
android:id="@+id/newinsulin_notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text|textCapSentences" />
</LinearLayout>
<include layout="@layout/mdtp_done_button" /> <include layout="@layout/mdtp_done_button" />
</LinearLayout> </LinearLayout>

View file

@ -199,6 +199,33 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/treatments_wizard_notes_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:width="120dp"
android:padding="10dp"
android:text="@string/careportal_newnstreatment_notes_label"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:textStyle="bold" />
<EditText
android:id="@+id/treatment_wizard_notes"
android:layout_width="155dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="left"
android:inputType="text|textCapSentences"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<include layout="@layout/mdtp_done_button" /> <include layout="@layout/mdtp_done_button" />
<View <View

View file

@ -7,6 +7,9 @@
<item <item
android:id="@+id/nav_historybrowser" android:id="@+id/nav_historybrowser"
android:title="@string/nav_historybrowser" /> android:title="@string/nav_historybrowser" />
<item
android:id="@+id/nav_setupwizard"
android:title="@string/nav_setupwizard" />
<item <item
android:id="@+id/nav_resetdb" android:id="@+id/nav_resetdb"
android:title="@string/nav_resetdb" /> android:title="@string/nav_resetdb" />

View file

@ -0,0 +1,12 @@
<resources>
<!-- Declare custom theme attributes that allow changing which styles are
used for button bars depending on the API level.
?android:attr/buttonBarStyle is new as of API 11 so this is
necessary to support previous API levels. -->
<declare-styleable name="ButtonBarContainerTheme">
<attr name="metaButtonBarStyle" format="reference" />
<attr name="metaButtonBarButtonStyle" format="reference" />
</declare-styleable>
</resources>

View file

@ -49,7 +49,7 @@
<color name="colorSetExtendedButton">#FFDD7792</color> <color name="colorSetExtendedButton">#FFDD7792</color>
<color name="colorProfileSwitchButton">#ca77dd</color> <color name="colorProfileSwitchButton">#ca77dd</color>
<color name="colorInProgress">#c45026</color> <color name="colorScheduled">#de7550</color>
<color name="colorActive">#1b5e20</color> <color name="colorActive">#1b5e20</color>
<color name="loopenabled">#47c8ff</color> <color name="loopenabled">#47c8ff</color>
@ -62,4 +62,6 @@
<color name="notificationLow">#ff827c</color> <color name="notificationLow">#ff827c</color>
<color name="notificationInfo">#009705</color> <color name="notificationInfo">#009705</color>
<color name="black_overlay">#66000000</color>
</resources> </resources>

View file

@ -715,6 +715,8 @@
<string name="connectiontimedout">Connection timed out</string> <string name="connectiontimedout">Connection timed out</string>
<string name="food">Food</string> <string name="food">Food</string>
<string name="shortgramm">g</string> <string name="shortgramm">g</string>
<string name="shortminute">m</string>
<string name="shorthour">h</string>
<string name="none"><![CDATA[<none>]]></string> <string name="none"><![CDATA[<none>]]></string>
<string name="shortkilojoul">kJ</string> <string name="shortkilojoul">kJ</string>
<string name="shortenergy">En</string> <string name="shortenergy">En</string>
@ -995,4 +997,12 @@
<string name="key_openapssmb_max_iob" translatable="false">openapsmb_max_iob</string> <string name="key_openapssmb_max_iob" translatable="false">openapsmb_max_iob</string>
<string name="openapssmb_maxiob_title">Maximum total IOB OpenAPS can\'t go over [U]</string> <string name="openapssmb_maxiob_title">Maximum total IOB OpenAPS can\'t go over [U]</string>
<string name="openapssmb_maxiob_summary">This value is called Max IOB in OpenAPS context\nOpenAPS will not add more insulin if current IOB is greater than this value</string> <string name="openapssmb_maxiob_summary">This value is called Max IOB in OpenAPS context\nOpenAPS will not add more insulin if current IOB is greater than this value</string>
<string name="time">Time</string>
<string name="key_show_notes_entry_dialogs">show_notes_entry_dialogs</string>
<string name="overview_show_notes_field_in_dialogs_title">Show notes field in treatment dialogs</string>
<string name="title_activity_setup_wizard">SetupWizardActivity</string>
<string name="dummy_button">Dummy Button</string>
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="nav_setupwizard">Setup Wizard</string>
</resources> </resources>

View file

@ -24,5 +24,17 @@
<item name="android:textSize">10sp</item> <item name="android:textSize">10sp</item>
</style> </style>
<style name="FullscreenTheme" parent="AppTheme">
<item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowBackground">@null</item>
<item name="metaButtonBarStyle">?android:attr/buttonBarStyle</item>
<item name="metaButtonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
</style>
<style name="FullscreenActionBarStyle" parent="Widget.AppCompat.ActionBar">
<item name="android:background">@color/black_overlay</item>
</style>
<!-- Preferences --> <!-- Preferences -->
</resources> </resources>

View file

@ -110,6 +110,10 @@
android:key="@string/key_show_calibration_button" android:key="@string/key_show_calibration_button"
android:title="@string/overview_calibration" android:title="@string/overview_calibration"
android:summary="@string/show_calibration_button_summary"/> android:summary="@string/show_calibration_button_summary"/>
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_show_notes_entry_dialogs"
android:title="@string/overview_show_notes_field_in_dialogs_title" />
</PreferenceScreen> </PreferenceScreen>
</PreferenceCategory> </PreferenceCategory>

View file

@ -1,11 +1,13 @@
package info; package info;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import com.squareup.otto.Bus; import com.squareup.otto.Bus;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.junit.Assert;
import org.powermock.api.mockito.PowerMockito; import org.powermock.api.mockito.PowerMockito;
import java.util.Locale; import java.util.Locale;
@ -15,8 +17,10 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ConstraintChecker; import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentService;
import info.nightscout.androidaps.queue.CommandQueue; import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
@ -33,6 +37,10 @@ import static org.mockito.Mockito.when;
public class AAPSMocker { public class AAPSMocker {
private static String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"; private static String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
private static Profile profile; private static Profile profile;
private static ProfileStore profileStore;
public static final String TESTPROFILENAME = "someProfile";
public static Intent intentSent = null;
public static void mockStrings() { public static void mockStrings() {
Locale.setDefault(new Locale("en", "US")); Locale.setDefault(new Locale("en", "US"));
@ -81,6 +89,7 @@ public class AAPSMocker {
when(MainApp.gs(R.string.basalprofilenotaligned)).thenReturn("Basal values not aligned to hours: %s"); when(MainApp.gs(R.string.basalprofilenotaligned)).thenReturn("Basal values not aligned to hours: %s");
when(MainApp.gs(R.string.minago)).thenReturn("%d min ago"); when(MainApp.gs(R.string.minago)).thenReturn("%d min ago");
when(MainApp.gs(R.string.hoursago)).thenReturn("%.1fh ago"); when(MainApp.gs(R.string.hoursago)).thenReturn("%.1fh ago");
when(MainApp.gs(R.string.careportal_profileswitch)).thenReturn("Profile Switch");
} }
public static MainApp mockMainApp() { public static MainApp mockMainApp() {
@ -128,6 +137,11 @@ public class AAPSMocker {
when(ConfigBuilderPlugin.getCommandQueue()).thenReturn(queue); when(ConfigBuilderPlugin.getCommandQueue()).thenReturn(queue);
} }
public static void mockTreatmentService() throws Exception {
TreatmentService treatmentService = PowerMockito.mock(TreatmentService.class);
PowerMockito.whenNew(TreatmentService.class).withNoArguments().thenReturn(treatmentService);
}
public static Profile getValidProfile() { public static Profile getValidProfile() {
try { try {
if (profile == null) if (profile == null)
@ -137,6 +151,24 @@ public class AAPSMocker {
return profile; return profile;
} }
public static ProfileStore getValidProfileStore() {
try {
if (profileStore == null) {
JSONObject json = new JSONObject();
JSONObject store = new JSONObject();
JSONObject profile = new JSONObject(validProfile);
json.put("defaultProfile", TESTPROFILENAME);
json.put("store", store);
store.put(TESTPROFILENAME, profile);
profileStore = new ProfileStore(json);
}
} catch (JSONException ignored) {
Assert.fail("getValidProfileStore() failed");
}
return profileStore;
}
private static MockedBus bus = new MockedBus(); private static MockedBus bus = new MockedBus();
public static void prepareMockedBus() { public static void prepareMockedBus() {

View file

@ -0,0 +1,223 @@
package info;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.SparseArray;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyByte;
import static org.mockito.Matchers.anyChar;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyShort;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
public final class BundleMock {
public static Bundle mock() {
return mock(new HashMap<String, Object>());
}
public static Bundle mock(final HashMap<String, Object> map) {
Answer unsupported = new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
throw new UnsupportedOperationException();
}
};
Answer put = new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
map.put((String)invocation.getArguments()[0], invocation.getArguments()[1]);
return null;
}
};
Answer<Object> get = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return map.get(invocation.getArguments()[0]);
}
};
Answer<Object> getOrDefault = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object key = invocation.getArguments()[0];
return map.containsKey(key) ? map.get(key) : invocation.getArguments()[1];
}
};
Bundle bundle = Mockito.mock(Bundle.class);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return map.size();
}
}).when(bundle).size();
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return map.isEmpty();
}
}).when(bundle).isEmpty();
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
map.clear();
return null;
}
}).when(bundle).clear();
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return map.containsKey(invocation.getArguments()[0]);
}
}).when(bundle).containsKey(anyString());
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return map.get(invocation.getArguments()[0]);
}
}).when(bundle).get(anyString());
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
map.remove(invocation.getArguments()[0]);
return null;
}
}).when(bundle).remove(anyString());
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return map.keySet();
}
}).when(bundle).keySet();
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return BundleMock.class.getSimpleName() + "{map=" + map.toString() + "}";
}
}).when(bundle).toString();
doAnswer(put).when(bundle).putBoolean(anyString(), anyBoolean());
when(bundle.getBoolean(anyString())).thenAnswer(get);
when(bundle.getBoolean(anyString(), anyBoolean())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putByte(anyString(), anyByte());
when(bundle.getByte(anyString())).thenAnswer(get);
when(bundle.getByte(anyString(), anyByte())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putChar(anyString(), anyChar());
when(bundle.getChar(anyString())).thenAnswer(get);
when(bundle.getChar(anyString(), anyChar())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putInt(anyString(), anyShort());
when(bundle.getShort(anyString())).thenAnswer(get);
when(bundle.getShort(anyString(), anyShort())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putLong(anyString(), anyLong());
when(bundle.getLong(anyString())).thenAnswer(get);
when(bundle.getLong(anyString(), anyLong())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putFloat(anyString(), anyFloat());
when(bundle.getFloat(anyString())).thenAnswer(get);
when(bundle.getFloat(anyString(), anyFloat())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putDouble(anyString(), anyDouble());
when(bundle.getDouble(anyString())).thenAnswer(get);
when(bundle.getDouble(anyString(), anyDouble())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putString(anyString(), anyString());
when(bundle.getString(anyString())).thenAnswer(get);
when(bundle.getString(anyString(), anyString())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putBooleanArray(anyString(), any(boolean[].class));
when(bundle.getBooleanArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putLongArray(anyString(), any(long[].class));
when(bundle.getLongArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putDoubleArray(anyString(), any(double[].class));
when(bundle.getDoubleArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putIntArray(anyString(), any(int[].class));
when(bundle.getIntArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putInt(anyString(), anyInt());
when(bundle.getInt(anyString())).thenAnswer(get);
when(bundle.getInt(anyString(), anyInt())).thenAnswer(getOrDefault);
doAnswer(unsupported).when(bundle).putAll(any(Bundle.class));
when(bundle.hasFileDescriptors()).thenAnswer(unsupported);
doAnswer(put).when(bundle).putShort(anyString(), anyShort());
when(bundle.getShort(anyString())).thenAnswer(get);
when(bundle.getShort(anyString(), anyShort())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putFloat(anyString(), anyFloat());
when(bundle.getFloat(anyString())).thenAnswer(get);
when(bundle.getFloat(anyString(), anyFloat())).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putCharSequence(anyString(), any(CharSequence.class));
when(bundle.getCharSequence(anyString())).thenAnswer(get);
when(bundle.getCharSequence(anyString(), any(CharSequence.class))).thenAnswer(getOrDefault);
doAnswer(put).when(bundle).putBundle(anyString(), any(Bundle.class));
when(bundle.getBundle(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putParcelable(anyString(), any(Parcelable.class));
when(bundle.getParcelable(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putParcelableArray(anyString(), any(Parcelable[].class));
when(bundle.getParcelableArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putParcelableArrayList(anyString(), any(ArrayList.class));
when(bundle.getParcelableArrayList(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putSparseParcelableArray(anyString(), any(SparseArray.class));
when(bundle.getSparseParcelableArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putSerializable(anyString(), any(Serializable.class));
when(bundle.getSerializable(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putIntegerArrayList(anyString(), any(ArrayList.class));
when(bundle.getIntegerArrayList(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putStringArrayList(anyString(), any(ArrayList.class));
when(bundle.getStringArrayList(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putCharSequenceArrayList(anyString(), any(ArrayList.class));
when(bundle.getCharSequenceArrayList(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putCharArray(anyString(), any(char[].class));
when(bundle.getCharArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putByteArray(anyString(), any(byte[].class));
when(bundle.getByteArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putShortArray(anyString(), any(short[].class));
when(bundle.getShortArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putFloatArray(anyString(), any(float[].class));
when(bundle.getFloatArray(anyString())).thenAnswer(get);
doAnswer(put).when(bundle).putCharSequenceArray(anyString(), any(CharSequence[].class));
when(bundle.getCharSequenceArray(anyString())).thenAnswer(get);
return bundle;
}
}

View file

@ -2,17 +2,12 @@ package info;
import org.junit.Assert; import org.junit.Assert;
import org.mockito.ArgumentMatchers; import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito; import org.powermock.api.mockito.PowerMockito;
import java.util.HashMap; import java.util.HashMap;
import info.nightscout.utils.SP; import info.nightscout.utils.SP;
import static org.powermock.api.mockito.PowerMockito.when;
public class SPMocker { public class SPMocker {
static HashMap<String, Object> data = new HashMap<>(); static HashMap<String, Object> data = new HashMap<>();
@ -24,20 +19,48 @@ public class SPMocker {
PowerMockito.when(SP.class, "putString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> { PowerMockito.when(SP.class, "putString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> {
String key = invocation.getArgument(0); String key = invocation.getArgument(0);
String value = invocation.getArgument(1); String value = invocation.getArgument(1);
data.put(key,value); data.put(key, value);
System.out.print("putString " + key + " " + value + "\n");
return null; return null;
}); });
PowerMockito.when(SP.class, "getString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> { PowerMockito.when(SP.class, "getString", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> {
String key = invocation.getArgument(0); String key = invocation.getArgument(0);
String def = invocation.getArgument(1); String def = invocation.getArgument(1);
String value = (String) data.get(key); String value = (String) data.get(key);
if (value == null) value = def; if (value == null) value = def;
System.out.print("getString " + key + " " + value + "\n");
return value; return value;
}); });
PowerMockito.when(SP.class, "putBoolean", ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean()).then(invocation -> {
String key = invocation.getArgument(0);
Boolean value = invocation.getArgument(1);
data.put(key, value);
System.out.print("putBoolean " + key + " " + value + "\n");
return null;
});
PowerMockito.when(SP.class, "getBoolean", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> {
String key = invocation.getArgument(0);
Boolean def = invocation.getArgument(1);
Boolean value = (Boolean) data.get(key);
if (value == null) value = def;
System.out.print("getBoolean " + key + " " + value + "\n");
return value;
});
PowerMockito.when(SP.class, "getDouble", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> {
String key = invocation.getArgument(0);
Double def = invocation.getArgument(1);
Double value = (Double) data.get(key);
if (value == null) value = def;
System.out.print("getDouble " + key + " " + value + "\n");
return value;
});
} catch (Exception e) { } catch (Exception e) {
Assert.fail("Unable to mock the construction of " Assert.fail("Unable to mock the construction of the SP object: " + e.getMessage());
+ "the SP object");
} }
} }

View file

@ -0,0 +1,89 @@
package info.nightscout.androidaps.plugins.Careportal.Dialogs;
import android.content.Context;
import org.json.JSONObject;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.SPMocker;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
import info.nightscout.androidaps.plugins.Treatments.TreatmentService;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.NSUpload;
import info.nightscout.utils.SP;
import static info.nightscout.androidaps.plugins.Careportal.CareportalFragment.PROFILESWITCH;
import static org.powermock.api.mockito.PowerMockito.doAnswer;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest({SP.class, MainApp.class, ConfigBuilderPlugin.class, Context.class, NSUpload.class, TreatmentsPlugin.class, TreatmentService.class, DatabaseHelper.class})
public class NewNSTreatmentDialogTest {
NewNSTreatmentDialog dialog;
ProfileSwitch profileSwitchUpload = null;
@Test
public void createNSTreatmentTest() throws Exception {
// Test profile creation
doAnswer(invocation -> {
ProfileSwitch ps = invocation.getArgument(0);
profileSwitchUpload = ps;
return null;
}).when(NSUpload.class, "uploadProfileSwitch", ArgumentMatchers.any());
PROFILESWITCH.executeProfileSwitch = true;
dialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch);
dialog.profileStore = AAPSMocker.getValidProfileStore();
JSONObject data = new JSONObject();
data.put("profile", AAPSMocker.TESTPROFILENAME);
data.put("duration", 0);
data.put("percentage", 110);
data.put("timeshift", 0);
dialog.createNSTreatment(data);
// Profile should be sent to NS
Assert.assertEquals(AAPSMocker.TESTPROFILENAME, profileSwitchUpload.profileName);
}
@Test
public void doProfileSwitch() {
}
@Test
public void doProfileSwitch1() {
}
@Before
public void prepareMock() throws Exception {
AAPSMocker.mockMainApp();
SPMocker.prepareMock();
SP.putString("profile", AAPSMocker.getValidProfileStore().getData().toString());
AAPSMocker.mockConfigBuilder();
AAPSMocker.mockApplicationContext();
AAPSMocker.mockStrings();
PowerMockito.mockStatic(NSUpload.class);
AAPSMocker.mockTreatmentService();
AAPSMocker.mockBus();
AAPSMocker.mockDatabaseHelper();
NSProfilePlugin profilePlugin = NSProfilePlugin.getPlugin();
when(MainApp.getConfigBuilder().getActiveProfileInterface())
.thenReturn(profilePlugin);
dialog = new NewNSTreatmentDialog();
}
}

View file

@ -0,0 +1,71 @@
package info.nightscout.androidaps.plugins.ConstraintsObjectives;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ObjectivesFragmentTest {
@Test
public void testModifyVisibility() {
ObjectivesFragment fragment = new ObjectivesFragment();
int currentPosition = 1;
long prevObjectiveAccomplishedTime = 0;
long objectiveStartedTime = 0;
int durationInDays = 0;
long objectiveAccomplishedTime = 0;
boolean requirementsMet = false;
boolean enableFakeValue = false;
// previous objective is not accomplished yet
assertEquals(0, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
// not started yet
prevObjectiveAccomplishedTime = 4711;
assertEquals(1, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
// started
// time calculation is true, requirements met is false
objectiveStartedTime = Long.MAX_VALUE;
durationInDays = 0;
assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
// started
// time calculation is false, requirements met is false
objectiveStartedTime = 10;
durationInDays = 0;
requirementsMet = true;
assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
// started
// time calculation is false, requirements met is true
objectiveStartedTime = 10;
durationInDays = 999999;
requirementsMet = true;
assertEquals(2, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
// started, after duration, requirements met --> show verify
objectiveStartedTime = Long.MAX_VALUE;
durationInDays = 0;
requirementsMet = true;
assertEquals(3, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
// finished
objectiveStartedTime = Long.MAX_VALUE;
durationInDays = 0;
requirementsMet = true;
objectiveAccomplishedTime = Long.MAX_VALUE;
assertEquals(4, fragment.modifyVisibility(currentPosition, prevObjectiveAccomplishedTime,
objectiveStartedTime, durationInDays, objectiveAccomplishedTime, requirementsMet, enableFakeValue));
}
}

View file

@ -7,7 +7,7 @@ buildscript {
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' classpath 'com.android.tools.build:gradle:3.1.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View file

@ -31,7 +31,7 @@ android {
defaultConfig { defaultConfig {
applicationId "info.nightscout.androidaps" applicationId "info.nightscout.androidaps"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 23
versionCode 1 versionCode 1
versionName "1.0.2" versionName "1.0.2"
buildConfigField "String", "BUILDVERSION", generateGitBuild() buildConfigField "String", "BUILDVERSION", generateGitBuild()