diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt index 00a76778d8..22453eed25 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt @@ -201,7 +201,8 @@ object AutomationPlugin : PluginBase(PluginDescription() ActionStartTempTarget(), ActionStopTempTarget(), ActionNotification(), - ActionProfileSwitchPercent() + ActionProfileSwitchPercent(), + ActionProfileSwitch() ) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitch.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitch.java new file mode 100644 index 0000000000..9860fca735 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitch.java @@ -0,0 +1,126 @@ +package info.nightscout.androidaps.plugins.general.automation.actions; + +import android.widget.LinearLayout; + +import com.google.common.base.Optional; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.ProfileInterface; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.automation.elements.InputProfileName; +import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement; +import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.androidaps.utils.JsonHelper; + +public class ActionProfileSwitch extends Action { + private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); + public InputProfileName inputProfileName = new InputProfileName("-"); + String profileName = ""; + String profileStoreName; + String profileInterfaceString; + + public ActionProfileSwitch() { + // Prevent action if active profile is already active + // but we don't have a trigger IS_NOT_EQUAL + // so check is in the doRun() + } + + @Override + public int friendlyName() { + return R.string.profilename; + } + + @Override + public String shortDescription() { + String returned = MainApp.gs(R.string.changengetoprofilename, inputProfileName.getValue()); + return returned; + } + + @Override + public void doAction(Callback callback) { + String activeProfileName = ProfileFunctions.getInstance().getProfileName(); + + /*log.debug("Current profile is: " + activeProfileName); + log.debug("Wanted profile is: " + profileName); + log.debug("Do they match: " + (profileName.equals(activeProfileName))); +*/ + if (profileName.equals(activeProfileName)) { + // Profile is already switched + return; + } + ProfileInterface profileInterface = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); + profileInterfaceString = profileInterface.toString(); + ProfileStore profileStore = NSProfilePlugin.getPlugin().getProfile(); + log.debug("NS profileStore is: " +profileStore.toString()); + if (profileStore == null) { + log.error("ProfileStore is null"); + return; + } + profileStoreName = profileStore.toString(); + if(profileStore.getSpecificProfile(profileName) == null) { + log.error("Selected profile does not exist! - "+ profileName); + return; + } + + ProfileFunctions.doProfileSwitch(profileStore, profileName, 0, 100, 0); + if (callback != null) + callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run(); + } + + @Override + public void generateDialog(LinearLayout root) { + new LayoutBuilder() + .add(new LabelWithElement(MainApp.gs(R.string.profilename), "", inputProfileName)) + .build(root); + } + + @Override + public boolean hasDialog() { + return true; + } + + @Override + public String toJSON() { + JSONObject o = new JSONObject(); + try { + o.put("type", ActionProfileSwitch.class.getName()); + JSONObject data = new JSONObject(); + data.put("profileToSwitchTo", inputProfileName.getValue()); + o.put("data", data); + } catch (JSONException e) { + e.printStackTrace(); + } + return o.toString(); + } + + @Override + public Action fromJSON(String data) { + + try { + JSONObject d = new JSONObject(data); + profileName = JsonHelper.safeGetString(d, "profileToSwitchTo"); + inputProfileName.setValue(profileName); + } catch (JSONException e) { + e.printStackTrace(); + } + return this; + } + + @Override + public Optional icon() { + return Optional.of(R.drawable.icon_actions_profileswitch); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileName.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileName.java new file mode 100644 index 0000000000..5431f47ede --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileName.java @@ -0,0 +1,99 @@ +package info.nightscout.androidaps.plugins.general.automation.elements; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.LinearLayout; +import android.widget.Spinner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; + +public class InputProfileName extends Element { + private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); + ProfileStore profileStore; + + String profileName; + + public InputProfileName(String name) { + super(); + this.profileName = name; + } + + public InputProfileName(InputProfileName another) { + super(); + profileName = another.getValue(); + } + + + @Override + public void addToLayout(LinearLayout root) { + ArrayList profileList = new ArrayList<>(); + profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile(); + if (profileStore == null) { + log.error("ProfileStore is empty"); + } else { + profileList = profileStore.getProfileList(); + } + ArrayAdapter adapter = new ArrayAdapter<>(root.getContext(), + R.layout.spinner_centered, profileList); + Spinner spinner = new Spinner(root.getContext()); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(adapter); + LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4)); + spinner.setLayoutParams(spinnerParams); + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setValue(listNames().get(position).toString()); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + spinner.setSelection(0); + LinearLayout l = new LinearLayout(root.getContext()); + l.setOrientation(LinearLayout.VERTICAL); + l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + l.addView(spinner); + root.addView(l); + } + + public InputProfileName setValue(String name) { + this.profileName = name; + return this; + } + + public String getValue() { + return profileName; + } + + public ArrayList listNames(){ + ArrayList profileList = new ArrayList<>(); + // profile + profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile(); + if (profileStore == null) { + log.error("ProfileStore is empty"); + } else { + profileList = profileStore.getProfileList(); + } + return profileList; + } + + +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 005e24df0f..4981356a0f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1572,6 +1572,8 @@ Get Temporary Basal Set Temporary Basal Set Bolus + Change profile to + Change profile to %1$s %2$+.2fU]]> diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitchTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitchTest.java new file mode 100644 index 0000000000..2226aac3d6 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionProfileSwitchTest.java @@ -0,0 +1,119 @@ +package info.nightscout.androidaps.plugins.general.automation.actions; + +import com.google.common.base.Optional; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +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.ProfileSwitch; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.queue.Callback; +import info.nightscout.androidaps.utils.SP; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, SP.class, TreatmentsPlugin.class, ProfileFunctions.class, ConfigBuilderPlugin.class}) +public class ActionProfileSwitchTest { + TreatmentsPlugin treatmentsPlugin; + ProfileSwitch profileAdded; + private ActionProfileSwitch actionProfileSwitch = new ActionProfileSwitch(); + private String stringJson = "{\"data\":{\"profileToSwitchTo\":\"Test\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.actions.ActionProfileSwitch\"}"; + + @Before + public void setUp() { + AAPSMocker.mockMainApp(); + SPMocker.prepareMock(); + SP.putString("profile", AAPSMocker.getValidProfileStore().getData().toString()); + AAPSMocker.mockConfigBuilder(); + AAPSMocker.mockApplicationContext(); + AAPSMocker.mockStrings(); + AAPSMocker.mockTreatmentService(); + AAPSMocker.mockBus(); + AAPSMocker.mockDatabaseHelper(); + + treatmentsPlugin = AAPSMocker.mockTreatmentPlugin(); + NSProfilePlugin profilePlugin = NSProfilePlugin.getPlugin(); + when(ConfigBuilderPlugin.getPlugin().getActiveProfileInterface()) + .thenReturn(profilePlugin); + + Mockito.doAnswer(invocation -> { + profileAdded = invocation.getArgument(0); + return null; + }).when(treatmentsPlugin).addToHistoryProfileSwitch(any(ProfileSwitch.class)); + } + + @Test + public void friendlyName() { + Assert.assertEquals(R.string.profilename, actionProfileSwitch.friendlyName()); + } + + @Test + public void shortDescriptionTest() { + actionProfileSwitch = new ActionProfileSwitch(); + actionProfileSwitch.inputProfileName.setValue("Test"); + when(MainApp.gs(anyInt(), anyString())).thenReturn("Change profile to Test"); + Assert.assertEquals("Change profile to Test", actionProfileSwitch.shortDescription()); + } + + @Test + public void doAction() { +/* actionProfileSwitch = new ActionProfileSwitch(); + actionProfileSwitch.inputProfileName.setValue("Test"); + actionProfileSwitch.profileName = "Test"; + SP.putString("profile", AAPSMocker.getValidProfileStore().getData().toString()); + + when(NSProfilePlugin.getPlugin().getProfile()).thenReturn(AAPSMocker.getValidProfileStore()); +// Assert.assertEquals("", actionProfileSwitch.profileStoreName); + Assert.assertEquals("", actionProfileSwitch.profileInterfaceString); +// when(NSProfilePlugin.getPlugin().getProfile()).thenReturn(AAPSMocker.getValidProfileStore()); + actionProfileSwitch.doAction(new Callback() { + @Override + public void run() { + } + }); + Assert.assertNotEquals(null, profileAdded);*/ + } + + @Test + public void hasDialogTest() { + Assert.assertTrue(actionProfileSwitch.hasDialog()); + } + + @Test + public void toJSONTest() { + actionProfileSwitch = new ActionProfileSwitch(); + actionProfileSwitch.inputProfileName.setValue("Test"); + Assert.assertEquals(stringJson, actionProfileSwitch.toJSON()); + } + + @Test + public void fromJSONTest() { + String data = "{\"profileToSwitchTo\":\"Test\"}"; + actionProfileSwitch = new ActionProfileSwitch(); + actionProfileSwitch.fromJSON(data); + Assert.assertEquals("Test", actionProfileSwitch.profileName); + } + + @Test + public void iconTest() { + Assert.assertEquals(Optional.of(R.drawable.icon_actions_profileswitch), actionProfileSwitch.icon()); + } +} \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileNameTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileNameTest.java new file mode 100644 index 0000000000..7f257aa883 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/elements/InputProfileNameTest.java @@ -0,0 +1,29 @@ +package info.nightscout.androidaps.plugins.general.automation.elements; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.SP; + +import static org.junit.Assert.*; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, SP.class, TreatmentsPlugin.class, ProfileFunctions.class}) +public class InputProfileNameTest { + String profileName = "Test"; + InputProfileName inputProfileName = new InputProfileName(profileName); + + @Test + public void getSetValue() { + inputProfileName = new InputProfileName("Test"); + Assert.assertEquals("Test", inputProfileName.getValue()); + inputProfileName.setValue("Test2"); + Assert.assertEquals("Test2", inputProfileName.getValue()); + } +} \ No newline at end of file