Merge pull request #17 from jotomo/combo-scripter-v2

10.01
This commit is contained in:
Simon Pauwels 2018-01-10 22:09:19 +01:00 committed by GitHub
commit 0c2ef80854
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 152 additions and 29 deletions

View file

@ -11,7 +11,7 @@ Hardware requirements:
Software to configure the pump. Software to configure the pump.
Roche sends out Smartpix devices and the configuration software Roche sends out Smartpix devices and the configuration software
free of charge to their customers upon request. free of charge to their customers upon request.
- A compatible phone: An Android phone with a phone running LineageOS 14.1 (formerly CyanogenMod) - A compatible phone: An Android phone with a phone running LineageOS 14.1 (formerly CyanogenMod) or Android 8.1 (Oreo)
- To build AndroidAPS with Combo support you need the latest Android Studio 3 version - To build AndroidAPS with Combo support you need the latest Android Studio 3 version
Limitations: Limitations:
@ -49,6 +49,7 @@ Setup:
menus/actions on the pump and hide those which are unsupported (extended/multiwave bolus, menus/actions on the pump and hide those which are unsupported (extended/multiwave bolus,
multiple basal rates), which cause the loop functionality to be restricted when used because multiple basal rates), which cause the loop functionality to be restricted when used because
it's not possible to run the loop in a safe manner when used. it's not possible to run the loop in a safe manner when used.
- Verify the _Quick Info Text_ is set to "QUICK INFO" (without the quotes, found under _Insulin Pump Options_).
- Set maximum TBR to 500% - Set maximum TBR to 500%
- Disable end of TBR alert - Disable end of TBR alert
- Set TBR duration step-size to 15 min - Set TBR duration step-size to 15 min

View file

@ -178,6 +178,10 @@ dependencies {
compile 'junit:junit:4.12' compile 'junit:junit:4.12'
testCompile 'org.json:json:20140107' testCompile 'org.json:json:20140107'
testCompile 'org.mockito:mockito-core:2.7.22' testCompile 'org.mockito:mockito-core:2.7.22'
testCompile 'org.powermock:powermock-api-mockito2:1.7.3'
testCompile 'org.powermock:powermock-module-junit4-rule-agent:1.7.3'
testCompile 'org.powermock:powermock-module-junit4-rule:1.7.3'
testCompile 'org.powermock:powermock-module-junit4:1.7.3'
androidTestCompile 'org.mockito:mockito-core:2.7.22' androidTestCompile 'org.mockito:mockito-core:2.7.22'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'

View file

@ -30,7 +30,9 @@ import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config; 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.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventExtendedBolusChange;
import info.nightscout.androidaps.events.EventFoodDatabaseChanged; import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
@ -43,7 +45,10 @@ import info.nightscout.androidaps.events.EventReloadTreatmentData;
import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.events.EventTempTargetChange;
import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.events.EventTreatmentChange;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData; import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistoryData;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync; import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.PercentageSplitter; import info.nightscout.utils.PercentageSplitter;
@ -1709,6 +1714,19 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
profileSwitch.percentage = trJson.getInt("percentage"); profileSwitch.percentage = trJson.getInt("percentage");
if (trJson.has("profileJson")) if (trJson.has("profileJson"))
profileSwitch.profileJson = trJson.getString("profileJson"); profileSwitch.profileJson = trJson.getString("profileJson");
else {
ProfileStore store = ConfigBuilderPlugin.getActiveProfileInterface().getProfile();
Profile profile = store.getSpecificProfile(profileSwitch.profileName);
if (profile != null) {
profileSwitch.profileJson = profile.getData().toString();
log.debug("Profile switch prefilled with JSON from local store");
} else {
Notification notification = new Notification(Notification.NO_LOCALE_PROFILE_FOUND, MainApp.sResources.getString(R.string.nolocaleprofilefound), Notification.URGENT);
MainApp.bus().post(new EventNewNotification(notification));
log.debug("JSON for profile switch doesn't exist. Ignoring ...");
return;
}
}
if (trJson.has("profilePlugin")) if (trJson.has("profilePlugin"))
profileSwitch.profilePlugin = trJson.getString("profilePlugin"); profileSwitch.profilePlugin = trJson.getString("profilePlugin");
createOrUpdate(profileSwitch); createOrUpdate(profileSwitch);

View file

@ -114,6 +114,18 @@ public class NSClientService extends Service {
initialize(); initialize();
} }
@Override
public void onCreate() {
super.onCreate();
mWakeLock.acquire();
}
@Override
public void onDestroy() {
super.onDestroy();
mWakeLock.release();
}
public class LocalBinder extends Binder { public class LocalBinder extends Binder {
public NSClientService getServiceInstance() { public NSClientService getServiceInstance() {
return NSClientService.this; return NSClientService.this;
@ -182,8 +194,6 @@ public class NSClientService extends Service {
public void initialize() { public void initialize() {
dataCounter = 0; dataCounter = 0;
NSClientService.mWakeLock.acquire();
readPreferences(); readPreferences();
if (!nsAPISecret.equals("")) if (!nsAPISecret.equals(""))
@ -221,7 +231,6 @@ public class NSClientService extends Service {
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "No NS URL specified")); MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "No NS URL specified"));
MainApp.bus().post(new EventNSClientStatus("Not configured")); MainApp.bus().post(new EventNSClientStatus("Not configured"));
} }
NSClientService.mWakeLock.release();
} }
private Emitter.Listener onConnect = new Emitter.Listener() { private Emitter.Listener onConnect = new Emitter.Listener() {
@ -242,6 +251,15 @@ public class NSClientService extends Service {
public void destroy() { public void destroy() {
if (mSocket != null) { if (mSocket != null) {
mSocket.off(Socket.EVENT_CONNECT);
mSocket.off(Socket.EVENT_DISCONNECT);
mSocket.off(Socket.EVENT_PING);
mSocket.off("dataUpdate");
mSocket.off("announcement");
mSocket.off("alarm");
mSocket.off("urgent_alarm");
mSocket.off("clear_alarm");
MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "destroy")); MainApp.bus().post(new EventNSClientNewLog("NSCLIENT", "destroy"));
isConnected = false; isConnected = false;
hasWriteAuth = false; hasWriteAuth = false;

View file

@ -248,9 +248,11 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
determineBasalResultAMA.changeRequested = false; determineBasalResultAMA.changeRequested = false;
// limit requests on openloop mode // limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultAMA.rate == 0 && determineBasalResultAMA.duration == 0) {
// going to cancel
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
determineBasalResultAMA.changeRequested = false; determineBasalResultAMA.changeRequested = false;
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1) } else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultAMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
determineBasalResultAMA.changeRequested = false; determineBasalResultAMA.changeRequested = false;
} }

View file

@ -232,9 +232,11 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
determineBasalResultMA.changeRequested = false; determineBasalResultMA.changeRequested = false;
// limit requests on openloop mode // limit requests on openloop mode
if (!MainApp.getConfigBuilder().isClosedModeEnabled()) { if (!MainApp.getConfigBuilder().isClosedModeEnabled()) {
if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) if (MainApp.getConfigBuilder().isTempBasalInProgress() && determineBasalResultMA.rate == 0 && determineBasalResultMA.duration == 0) {
// going to cancel
} else if (MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - MainApp.getConfigBuilder().getTempBasalAbsoluteRateHistory()) < 0.1) {
determineBasalResultMA.changeRequested = false; determineBasalResultMA.changeRequested = false;
if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1) } else if (!MainApp.getConfigBuilder().isTempBasalInProgress() && Math.abs(determineBasalResultMA.rate - ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) < 0.1)
determineBasalResultMA.changeRequested = false; determineBasalResultMA.changeRequested = false;
} }

View file

@ -60,6 +60,7 @@ public class Notification {
public static final int MINIMAL_BASAL_VALUE_REPLACED = 29; public static final int MINIMAL_BASAL_VALUE_REPLACED = 29;
public static final int BASAL_PROFILE_NOT_ALIGNED_TO_HOURS = 30; public static final int BASAL_PROFILE_NOT_ALIGNED_TO_HOURS = 30;
public static final int ZERO_VALUE_IN_PROFILE = 31; public static final int ZERO_VALUE_IN_PROFILE = 31;
public static final int NO_LOCALE_PROFILE_FOUND = 32;
public int id; public int id;
public Date date; public Date date;

View file

@ -172,17 +172,17 @@ public class ComboFragment extends SubscriberFragment implements View.OnClickLis
} }
// reservoir // reservoir
int reservoirLevel = plugin.getPump().reservoirLevel;
reservoirView.setText(reservoirLevel == -1 ? "" : "" + reservoirLevel + " "
+ MainApp.sResources.getString(R.string.treatments_wizard_unit_label));
if (ps.insulinState == PumpState.LOW) { if (ps.insulinState == PumpState.LOW) {
reservoirView.setTextColor(Color.YELLOW); reservoirView.setTextColor(Color.YELLOW);
reservoirView.setText(R.string.combo_reservoir_low);
reservoirView.setTypeface(null, Typeface.BOLD); reservoirView.setTypeface(null, Typeface.BOLD);
} else if (ps.insulinState == PumpState.EMPTY) { } else if (ps.insulinState == PumpState.EMPTY) {
reservoirView.setTextColor(Color.RED); reservoirView.setTextColor(Color.RED);
reservoirView.setText(R.string.combo_reservoir_empty);
reservoirView.setTypeface(null, Typeface.BOLD); reservoirView.setTypeface(null, Typeface.BOLD);
} else { } else {
reservoirView.setTextColor(Color.WHITE); reservoirView.setTextColor(Color.WHITE);
reservoirView.setText(R.string.combo_reservoir_normal);
reservoirView.setTypeface(null, Typeface.NORMAL); reservoirView.setTypeface(null, Typeface.NORMAL);
} }

View file

@ -339,7 +339,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
if (!pump.initialized) { if (!pump.initialized) {
initializePump(); initializePump();
} else { } else {
runCommand(MainApp.sResources.getString(R.string.combo_pump_action_refreshing), 1, ruffyScripter::readReservoirLevelAndLastBolus); runCommand(MainApp.sResources.getString(R.string.combo_pump_action_refreshing), 1, ruffyScripter::readPumpState);
} }
} }
@ -379,13 +379,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
MainApp.bus().post(new EventInitializationChanged()); MainApp.bus().post(new EventInitializationChanged());
// ComboFragment updates state fully only after the pump has initialized, so run this manually here // ComboFragment updates state fully only after the pump has initialized, so run this manually here
updateLocalData(runCommand(null, 1, ruffyScripter::readReservoirLevelAndLastBolus)); updateLocalData(readBasalResult);
} }
private void updateLocalData(CommandResult result) { private void updateLocalData(CommandResult result) {
if (result.reservoirLevel != PumpState.UNKNOWN) {
pump.reservoirLevel = result.reservoirLevel;
}
if (result.state.menu != null) { if (result.state.menu != null) {
pump.state = result.state; pump.state = result.state;
} }
@ -470,18 +467,13 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
} }
lastRequestedBolus = new Bolus(System.currentTimeMillis(), detailedBolusInfo.insulin, true); lastRequestedBolus = new Bolus(System.currentTimeMillis(), detailedBolusInfo.insulin, true);
CommandResult stateResult = runCommand(null, 1, ruffyScripter::readReservoirLevelAndLastBolus); CommandResult stateResult = runCommand(null, 1, ruffyScripter::readPumpState);
long pumpTimeWhenBolusWasRequested = stateResult .state.pumpTime; long pumpTimeWhenBolusWasRequested = stateResult .state.pumpTime;
if (!stateResult.success || pumpTimeWhenBolusWasRequested == 0) { if (!stateResult.success || pumpTimeWhenBolusWasRequested == 0) {
return new PumpEnactResult().success(false).enacted(false) return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.sResources.getString(R.string.combo_error_no_bolus_delivered)); .comment(MainApp.sResources.getString(R.string.combo_error_no_bolus_delivered));
} }
if (stateResult.reservoirLevel < detailedBolusInfo.insulin) {
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.sResources.getString(R.string.combo_reservoir_level_insufficient_for_bolus));
}
try { try {
pump.activity = MainApp.sResources.getString(R.string.combo_pump_action_bolusing, detailedBolusInfo.insulin); pump.activity = MainApp.sResources.getString(R.string.combo_pump_action_bolusing, detailedBolusInfo.insulin);
MainApp.bus().post(new EventComboPumpUpdateGUI()); MainApp.bus().post(new EventComboPumpUpdateGUI());
@ -1034,9 +1026,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
try { try {
JSONObject pumpJson = new JSONObject(); JSONObject pumpJson = new JSONObject();
pumpJson.put("clock", DateUtil.toISOString(pump.lastSuccessfulCmdTime)); pumpJson.put("clock", DateUtil.toISOString(pump.lastSuccessfulCmdTime));
if (pump.reservoirLevel != -1) {
pumpJson.put("reservoir", pump.reservoirLevel); int level = 150;
} if (pump.state.insulinState == PumpState.LOW) level = 8;
else if (pump.state.insulinState == PumpState.EMPTY) level = 0;
pumpJson.put("reservoir", level);
JSONObject statusJson = new JSONObject(); JSONObject statusJson = new JSONObject();
statusJson.put("status", getStateSummary()); statusJson.put("status", getStateSummary());

View file

@ -17,7 +17,6 @@ class ComboPump {
public volatile String activity; public volatile String activity;
@NonNull @NonNull
volatile PumpState state = new PumpState(); volatile PumpState state = new PumpState();
volatile int reservoirLevel = -1;
@NonNull @NonNull
volatile BasalProfile basalProfile = new BasalProfile(); volatile BasalProfile basalProfile = new BasalProfile();

View file

@ -227,7 +227,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
@Override @Override
public boolean isThisProfileSet(Profile profile) { public boolean isThisProfileSet(Profile profile) {
return false; return true;
} }
@Override @Override

View file

@ -778,5 +778,4 @@
<string name="openapsama_bolussnooze_dia_divisor_summary">Standarwert: 2\nBolus snooze (\"Bolus-Schlummer\") bremst den Loop nach einem Mahleiten-Bolus, damit dieser nicht mit niedrigen TBR reagiert, wenn Du gerade gegessen hast. Beispiel: Der Standardwert 2 bewirkt, dass bei einem 3 Stunden DIA der Bolus snooze während 1.5 Stunden nach dem Bolus linear ausläuft (3 h Dia / 2 = 1.5 h Bolus snooze).</string> <string name="openapsama_bolussnooze_dia_divisor_summary">Standarwert: 2\nBolus snooze (\"Bolus-Schlummer\") bremst den Loop nach einem Mahleiten-Bolus, damit dieser nicht mit niedrigen TBR reagiert, wenn Du gerade gegessen hast. Beispiel: Der Standardwert 2 bewirkt, dass bei einem 3 Stunden DIA der Bolus snooze während 1.5 Stunden nach dem Bolus linear ausläuft (3 h Dia / 2 = 1.5 h Bolus snooze).</string>
<string name="openapsama_min_5m_carbimpact_summary">Standardwert: 3.0\nDies ist eine Einstellung für die Standard-Kohlenhydrat-Absorptionswirkung pro 5 Minuten. Der Standardwert ist 3mg/dl/5min. Dies wirkt sich darauf aus, wie schnell der COB-Wert fällt und wieviel KH-Absorption bei der Berechnung des vorhergesagten BZ angenommen wird, wenn der BZ stärker als erwartet fällt oder nicht so stark wie erwartet steigt.</string> <string name="openapsama_min_5m_carbimpact_summary">Standardwert: 3.0\nDies ist eine Einstellung für die Standard-Kohlenhydrat-Absorptionswirkung pro 5 Minuten. Der Standardwert ist 3mg/dl/5min. Dies wirkt sich darauf aus, wie schnell der COB-Wert fällt und wieviel KH-Absorption bei der Berechnung des vorhergesagten BZ angenommen wird, wenn der BZ stärker als erwartet fällt oder nicht so stark wie erwartet steigt.</string>
<string name="openapsama_link_to_preferncejson_doc_txt">Achtung! Normalerweise musst Du diese Werte nicht ändern. Bitte KLICKE HIER und LESE den Text. Verändere Werte erst, wenn Du den Inhalt des Textes verstanden hast.</string> <string name="openapsama_link_to_preferncejson_doc_txt">Achtung! Normalerweise musst Du diese Werte nicht ändern. Bitte KLICKE HIER und LESE den Text. Verändere Werte erst, wenn Du den Inhalt des Textes verstanden hast.</string>
<string name="combo_reservoir_level_insufficient_for_bolus">Nicht mehr genug Insulin im Reservoir für den Bolus</string>
</resources> </resources>

View file

@ -811,6 +811,7 @@
<string name="hasbgdata">BG available from selected source</string> <string name="hasbgdata">BG available from selected source</string>
<string name="basalprofilenotaligned">Basal values not aligned to hours</string> <string name="basalprofilenotaligned">Basal values not aligned to hours</string>
<string name="zerovalueinprofile">Zero value in profile</string> <string name="zerovalueinprofile">Zero value in profile</string>
<string name="nolocaleprofilefound">Received profile switch from NS but profile doesn\'t exist localy</string>
<string name="bolusstopping">Stopping bolus delivery</string> <string name="bolusstopping">Stopping bolus delivery</string>
<string name="bolusstopped">Bolus delivery stopped</string> <string name="bolusstopped">Bolus delivery stopped</string>
<string name="combo_programming_bolus">Programming pump for bolusing</string> <string name="combo_programming_bolus">Programming pump for bolusing</string>
@ -864,6 +865,5 @@
<string name="combo_error_partial_bolus_delivered">Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.</string> <string name="combo_error_partial_bolus_delivered">Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.</string>
<string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string> <string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string>
<string name="combo_error_bolus_recovery_progress">Recovering from connection loss</string> <string name="combo_error_bolus_recovery_progress">Recovering from connection loss</string>
<string name="combo_reservoir_level_insufficient_for_bolus">Not enough insulin left in reservoir for bolus</string>
</resources> </resources>

View file

@ -0,0 +1,85 @@
package info.nightscout.utils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Created by kuchjir on 12/12/2017.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest( { MainApp.class, GlucoseStatus.class, ConfigBuilderPlugin.class })
public class BolusWizardTest {
private static final double PUMP_BOLUS_STEP = 0.1;
@Test
/** Should calculate the same bolus when different blood glucose but both in target range */
public void shuldCalculateTheSameBolusWhenBGsInRange() throws Exception {
BolusWizard bw = new BolusWizard();
Profile profile = setupProfile(4d, 8d, 20d, 12d);
Double bolusForBg42 = bw.doCalc(profile, null, 20, 0.0,4.2, 0d, 100d, true, true, false, false);
Double bolusForBg54 = bw.doCalc(profile, null, 20, 0.0,5.4, 0d, 100d, true, true, false, false);
Assert.assertEquals(bolusForBg42, bolusForBg54);
}
@Test
public void shuldCalculateHigherBolusWhenHighBG() throws Exception {
BolusWizard bw = new BolusWizard();
Profile profile = setupProfile(4d, 8d, 20d, 12d);
Double bolusForHighBg = bw.doCalc(profile, null, 20, 0d,9.8, 0d, 100d, true, true, false, false);
Double bolusForBgInRange = bw.doCalc(profile, null, 20, 0.0,5.4, 0d, 100d, true, true, false, false);
Assert.assertTrue(bolusForHighBg > bolusForBgInRange);
}
@Test
public void shuldCalculateLowerBolusWhenLowBG() throws Exception {
BolusWizard bw = new BolusWizard();
Profile profile = setupProfile(4d, 8d, 20d, 12d);
Double bolusForLowBg = bw.doCalc(profile, null, 20, 0d,3.6, 0d, 100d, true, true, false, false);
Double bolusForBgInRange = bw.doCalc(profile, null, 20, 0.0,5.4, 0d, 100d, true, true, false, false);
Assert.assertTrue(bolusForLowBg < bolusForBgInRange);
}
private Profile setupProfile(Double targetLow, Double targetHigh, Double insulinSensitivityFactor, Double insulinToCarbRatio) {
Profile profile = mock(Profile.class);
when(profile.getTargetLow()).thenReturn(targetLow);
when(profile.getTargetHigh()).thenReturn(targetHigh);
when(profile.getIsf()).thenReturn(insulinSensitivityFactor);
when(profile.getIc()).thenReturn(insulinToCarbRatio);
PowerMockito.mockStatic(GlucoseStatus.class);
when(GlucoseStatus.getGlucoseStatusData()).thenReturn(null);
ConfigBuilderPlugin treatment = mock(ConfigBuilderPlugin.class);
IobTotal iobTotalZero = new IobTotal(System.currentTimeMillis());
when(treatment.getLastCalculationTreatments()).thenReturn(iobTotalZero);
when(treatment.getLastCalculationTempBasals()).thenReturn(iobTotalZero);
PowerMockito.mockStatic(MainApp.class);
when(MainApp.getConfigBuilder()).thenReturn(treatment);
PowerMockito.mockStatic(ConfigBuilderPlugin.class);
PumpInterface pump = MDIPlugin.getPlugin();
pump.getPumpDescription().bolusStep = PUMP_BOLUS_STEP;
when(ConfigBuilderPlugin.getActivePump()).thenReturn(pump);
return profile;
}
}