From d227013496d866057bb870df6ab963aaa0aa58c2 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 22 Nov 2019 00:12:46 +0100 Subject: [PATCH 1/3] SmsCommunicatorPlugin -> kt --- .../general/smsCommunicator/AuthRequest.java | 2 +- .../plugins/general/smsCommunicator/Sms.java | 2 +- .../SmsCommunicatorFragment.java | 8 +- .../SmsCommunicatorPlugin.java | 1031 ----------------- .../smsCommunicator/SmsCommunicatorPlugin.kt | 812 +++++++++++++ app/src/main/res/values/strings.xml | 2 +- app/src/test/java/info/AAPSMocker.java | 3 + .../smsCommunicator/AuthRequestTest.java | 8 +- .../SmsCommunicatorPluginTest.java | 500 ++++---- 9 files changed, 1070 insertions(+), 1298 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.java index 4b05072eb1..45cd824743 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequest.java @@ -8,7 +8,7 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.utils.DateUtil; -class AuthRequest { +public class AuthRequest { private static Logger log = LoggerFactory.getLogger(L.SMS); Sms requester; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/Sms.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/Sms.java index 2eedfa0a51..8efeb909fc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/Sms.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/Sms.java @@ -5,7 +5,7 @@ import android.telephony.SmsMessage; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.utils.DateUtil; -class Sms { +public class Sms { String phoneNumber; String text; long date; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java index 31f335a7cf..7c147a2409 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java @@ -62,14 +62,14 @@ public class SmsCommunicatorFragment extends Fragment { return (int) (object1.date - object2.date); } } - Collections.sort(SmsCommunicatorPlugin.getPlugin().messages, new CustomComparator()); + Collections.sort(SmsCommunicatorPlugin.getPlugin().getMessages(), new CustomComparator()); int messagesToShow = 40; - int start = Math.max(0, SmsCommunicatorPlugin.getPlugin().messages.size() - messagesToShow); + int start = Math.max(0, SmsCommunicatorPlugin.getPlugin().getMessages().size() - messagesToShow); String logText = ""; - for (int x = start; x < SmsCommunicatorPlugin.getPlugin().messages.size(); x++) { - Sms sms = SmsCommunicatorPlugin.getPlugin().messages.get(x); + for (int x = start; x < SmsCommunicatorPlugin.getPlugin().getMessages().size(); x++) { + Sms sms = SmsCommunicatorPlugin.getPlugin().getMessages().get(x); if (sms.ignored) { logText += DateUtil.timeString(sms.date) + " <<< " + "░ " + sms.phoneNumber + " " + sms.text + "
"; } else if (sms.received) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java deleted file mode 100644 index 5fb583c760..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.java +++ /dev/null @@ -1,1031 +0,0 @@ -package info.nightscout.androidaps.plugins.general.smsCommunicator; - -import android.content.Intent; -import android.os.Bundle; -import android.preference.EditTextPreference; -import android.preference.Preference; -import android.preference.PreferenceFragment; -import android.telephony.SmsManager; -import android.telephony.SmsMessage; -import android.text.TextUtils; - -import com.andreabaccega.widget.ValidatingEditTextPreference; - -import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.Normalizer; -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; -import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; -import info.nightscout.androidaps.plugins.bus.RxBus; -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.general.nsclient.events.EventNSClientRestart; -import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.SP; -import info.nightscout.androidaps.utils.SafeParse; -import info.nightscout.androidaps.utils.XdripCalibrations; -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.schedulers.Schedulers; - -/** - * Created by mike on 05.08.2016. - */ -public class SmsCommunicatorPlugin extends PluginBase { - private static Logger log = LoggerFactory.getLogger(L.SMS); - private CompositeDisposable disposable = new CompositeDisposable(); - - private static SmsCommunicatorPlugin smsCommunicatorPlugin; - - public static SmsCommunicatorPlugin getPlugin() { - - if (smsCommunicatorPlugin == null) { - smsCommunicatorPlugin = new SmsCommunicatorPlugin(); - } - return smsCommunicatorPlugin; - } - - List allowedNumbers = new ArrayList<>(); - - AuthRequest messageToConfirm = null; - - long lastRemoteBolusTime = 0; - - ArrayList messages = new ArrayList<>(); - - SmsCommunicatorPlugin() { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(SmsCommunicatorFragment.class.getName()) - .pluginName(R.string.smscommunicator) - .shortName(R.string.smscommunicator_shortname) - .preferencesId(R.xml.pref_smscommunicator) - .description(R.string.description_sms_communicator) - ); - processSettings(null); - } - - @Override - protected void onStart() { - super.onStart(); - disposable.add(RxBus.INSTANCE - .toObservable(EventPreferenceChange.class) - .observeOn(Schedulers.io()) - .subscribe(event -> { - processSettings(event); - }, FabricPrivacy::logException) - ); - } - - @Override - protected void onStop() { - disposable.clear(); - super.onStop(); - } - - @Override - public void preprocessPreferences(@NotNull final PreferenceFragment preferenceFragment) { - super.preprocessPreferences(preferenceFragment); - - final ValidatingEditTextPreference distance = (ValidatingEditTextPreference) preferenceFragment.findPreference(MainApp.gs(R.string.key_smscommunicator_remotebolusmindistance)); - final EditTextPreference allowedNumbers = (EditTextPreference) preferenceFragment.findPreference(MainApp.gs(R.string.key_smscommunicator_allowednumbers)); - if (distance != null && allowedNumbers != null) { - if (!areMoreNumbers(allowedNumbers.getText())) { - distance.setTitle(MainApp.gs(R.string.smscommunicator_remotebolusmindistance) - + ".\n" - + MainApp.gs(R.string.smscommunicator_remotebolusmindistance_caveat)); - distance.setEnabled(false); - } else { - distance.setTitle(MainApp.gs(R.string.smscommunicator_remotebolusmindistance)); - distance.setEnabled(true); - } - - allowedNumbers.setOnPreferenceChangeListener((preference, newValue) -> { - if (!areMoreNumbers(((String) newValue))) { - distance.setText(String.valueOf(Constants.remoteBolusMinDistance / (60 * 1000L))); - distance.setTitle(MainApp.gs(R.string.smscommunicator_remotebolusmindistance) - + ".\n" - + MainApp.gs(R.string.smscommunicator_remotebolusmindistance_caveat)); - distance.setEnabled(false); - } else { - distance.setTitle(MainApp.gs(R.string.smscommunicator_remotebolusmindistance)); - distance.setEnabled(true); - } - return true; - }); - } - } - - @Override - public void updatePreferenceSummary(@NotNull final Preference pref) { - super.updatePreferenceSummary(pref); - - if (pref instanceof EditTextPreference) { - EditTextPreference editTextPref = (EditTextPreference) pref; - if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.getText() == null || TextUtils.isEmpty(editTextPref.getText().trim()))) { - pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary)); - } - } - } - - private void processSettings(final EventPreferenceChange ev) { - if (ev == null || ev.isChanged(R.string.key_smscommunicator_allowednumbers)) { - String settings = SP.getString(R.string.key_smscommunicator_allowednumbers, ""); - - allowedNumbers.clear(); - String[] substrings = settings.split(";"); - for (String number : substrings) { - String cleaned = number.replaceAll("\\s+", ""); - allowedNumbers.add(cleaned); - log.debug("Found allowed number: " + cleaned); - } - } - } - - boolean isCommand(String command, String number) { - switch (command.toUpperCase()) { - case "BG": - case "LOOP": - case "TREATMENTS": - case "NSCLIENT": - case "PUMP": - case "BASAL": - case "BOLUS": - case "EXTENDED": - case "CAL": - case "PROFILE": - case "TARGET": - case "SMS": - return true; - } - if (messageToConfirm != null && messageToConfirm.requester.phoneNumber.equals(number)) - return true; - return false; - } - - boolean isAllowedNumber(String number) { - for (String num : allowedNumbers) { - if (num.equals(number)) return true; - } - return false; - } - - public void handleNewData(Intent intent) { - Bundle bundle = intent.getExtras(); - if (bundle == null) return; - - Object[] pdus = (Object[]) bundle.get("pdus"); - if (pdus != null) { - // For every SMS message received - for (Object pdu : pdus) { - SmsMessage message = SmsMessage.createFromPdu((byte[]) pdu); - processSms(new Sms(message)); - } - } - } - - void processSms(final Sms receivedSms) { - if (!isEnabled(PluginType.GENERAL)) { - log.debug("Ignoring SMS. Plugin disabled."); - return; - } - if (!isAllowedNumber(receivedSms.phoneNumber)) { - log.debug("Ignoring SMS from: " + receivedSms.phoneNumber + ". Sender not allowed"); - receivedSms.ignored = true; - messages.add(receivedSms); - RxBus.INSTANCE.send(new EventSmsCommunicatorUpdateGui()); - return; - } - - messages.add(receivedSms); - log.debug(receivedSms.toString()); - - String[] splitted = receivedSms.text.split("\\s+"); - boolean remoteCommandsAllowed = SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false); - - if (splitted.length > 0 && isCommand(splitted[0].toUpperCase(), receivedSms.phoneNumber)) { - switch (splitted[0].toUpperCase()) { - case "BG": - processBG(splitted, receivedSms); - break; - case "LOOP": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2 || splitted.length == 3) - processLOOP(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "TREATMENTS": - if (splitted.length == 2) - processTREATMENTS(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "NSCLIENT": - if (splitted.length == 2) - processNSCLIENT(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "PUMP": - processPUMP(splitted, receivedSms); - break; - case "PROFILE": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2 || splitted.length == 3) - processPROFILE(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "BASAL": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2 || splitted.length == 3) - processBASAL(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "EXTENDED": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2 || splitted.length == 3) - processEXTENDED(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "BOLUS": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2 && DateUtil.now() - lastRemoteBolusTime < Constants.remoteBolusMinDistance) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotebolusnotallowed)); - else if (splitted.length == 2 && ConfigBuilderPlugin.getPlugin().getActivePump().isSuspended()) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.pumpsuspended)); - else if (splitted.length == 2 || splitted.length == 3) - processBOLUS(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - } - // splitted switch to fix bug in mockito - switch (splitted[0].toUpperCase()) { - case "CAL": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2) - processCAL(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "TARGET": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2) - processTARGET(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - case "SMS": - if (!remoteCommandsAllowed) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)); - else if (splitted.length == 2) - processSMS(splitted, receivedSms); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - default: // expect passCode here - if (messageToConfirm != null && messageToConfirm.requester.phoneNumber.equals(receivedSms.phoneNumber)) { - messageToConfirm.action(splitted[0]); - messageToConfirm = null; - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_unknowncommand)); - break; - } - } - - RxBus.INSTANCE.send(new EventSmsCommunicatorUpdateGui()); - } - - @SuppressWarnings("unused") - private void processBG(String[] splitted, Sms receivedSms) { - BgReading actualBG = DatabaseHelper.actualBg(); - BgReading lastBG = DatabaseHelper.lastBg(); - - String reply = ""; - - String units = ProfileFunctions.getInstance().getProfileUnits(); - - if (actualBG != null) { - reply = MainApp.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", "; - } else if (lastBG != null) { - Long agoMsec = System.currentTimeMillis() - lastBG.date; - int agoMin = (int) (agoMsec / 60d / 1000d); - reply = MainApp.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.gs(R.string.sms_minago), agoMin) + ", "; - } - GlucoseStatus glucoseStatus = GlucoseStatus.getGlucoseStatusData(); - if (glucoseStatus != null) - reply += MainApp.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "; - - TreatmentsPlugin.getPlugin().updateTotalIOBTreatments(); - IobTotal bolusIob = TreatmentsPlugin.getPlugin().getLastCalculationTreatments().round(); - TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals(); - IobTotal basalIob = TreatmentsPlugin.getPlugin().getLastCalculationTempBasals().round(); - - String cobText = MainApp.gs(R.string.value_unavailable_short); - CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "SMS COB"); - - reply += MainApp.gs(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" - + MainApp.gs(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " - + MainApp.gs(R.string.sms_basal) + " " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U), " - + MainApp.gs(R.string.cob) + ": " + cobInfo.generateCOBString(); - - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - receivedSms.processed = true; - } - - private void processLOOP(String[] splitted, Sms receivedSms) { - String reply; - switch (splitted[1].toUpperCase()) { - case "DISABLE": - case "STOP": - LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.setPluginEnabled(PluginType.LOOP, false); - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_STOP")); - String reply = MainApp.gs(R.string.smscommunicator_loophasbeendisabled) + " " + - MainApp.gs(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - }); - } else { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisdisabled)); - } - receivedSms.processed = true; - break; - case "ENABLE": - case "START": - loopPlugin = LoopPlugin.getPlugin(); - if (!loopPlugin.isEnabled(PluginType.LOOP)) { - loopPlugin.setPluginEnabled(PluginType.LOOP, true); - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loophasbeenenabled)); - RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_START")); - } else { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisenabled)); - } - receivedSms.processed = true; - break; - case "STATUS": - loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(PluginType.LOOP)) { - if (loopPlugin.isSuspended()) - reply = String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()); - else - reply = MainApp.gs(R.string.smscommunicator_loopisenabled); - } else { - reply = MainApp.gs(R.string.smscommunicator_loopisdisabled); - } - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - receivedSms.processed = true; - break; - case "RESUME": - LoopPlugin.getPlugin().suspendTo(0); - RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_RESUME")); - NSUpload.uploadOpenAPSOffline(0); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopresumed)); - break; - case "SUSPEND": - int duration = 0; - if (splitted.length == 3) - duration = SafeParse.stringToInt(splitted[2]); - duration = Math.max(0, duration); - duration = Math.min(180, duration); - if (duration == 0) { - receivedSms.processed = true; - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_wrongduration)); - return; - } else { - String passCode = generatePasscode(); - reply = String.format(MainApp.gs(R.string.smscommunicator_suspendreplywithcode), duration, passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction(duration) { - @Override - public void run() { - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - if (result.success) { - LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + anInteger * 60L * 1000); - NSUpload.uploadOpenAPSOffline(anInteger * 60); - RxBus.INSTANCE.send(new EventRefreshOverview("SMS_LOOP_SUSPENDED")); - String reply = MainApp.gs(R.string.smscommunicator_loopsuspended) + " " + - MainApp.gs(result.success ? R.string.smscommunicator_tempbasalcanceled : R.string.smscommunicator_tempbasalcancelfailed); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalcancelfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - - } - }); - } - break; - default: - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - break; - } - } - - private void processTREATMENTS(String[] splitted, Sms receivedSms) { - if (splitted[1].toUpperCase().equals("REFRESH")) { - TreatmentsPlugin.getPlugin().getService().resetTreatments(); - RxBus.INSTANCE.send(new EventNSClientRestart()); - sendSMS(new Sms(receivedSms.phoneNumber, "TREATMENTS REFRESH SENT")); - receivedSms.processed = true; - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } - - private void processNSCLIENT(String[] splitted, Sms receivedSms) { - if (splitted[1].toUpperCase().equals("RESTART")) { - RxBus.INSTANCE.send(new EventNSClientRestart()); - sendSMS(new Sms(receivedSms.phoneNumber, "NSCLIENT RESTART SENT")); - receivedSms.processed = true; - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } - - @SuppressWarnings("unused") - private void processPUMP(String[] splitted, Sms receivedSms) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("SMS", new Callback() { - @Override - public void run() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (result.success) { - if (pump != null) { - String reply = pump.shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } else { - String reply = MainApp.gs(R.string.readstatusfailed); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - receivedSms.processed = true; - } - - private void processPROFILE(String[] splitted, Sms receivedSms) { - // load profiles - ProfileInterface anInterface = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface(); - if (anInterface == null) { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.notconfigured)); - receivedSms.processed = true; - return; - } - ProfileStore store = anInterface.getProfile(); - if (store == null) { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.notconfigured)); - receivedSms.processed = true; - return; - } - final ArrayList list = store.getProfileList(); - - if (splitted[1].toUpperCase().equals("STATUS")) { - sendSMS(new Sms(receivedSms.phoneNumber, ProfileFunctions.getInstance().getProfileName())); - } else if (splitted[1].toUpperCase().equals("LIST")) { - if (list.isEmpty()) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.invalidprofile)); - else { - String reply = ""; - for (int i = 0; i < list.size(); i++) { - if (i > 0) - reply += "\n"; - reply += (i + 1) + ". "; - reply += list.get(i); - } - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } else { - - int pindex = SafeParse.stringToInt(splitted[1]); - int percentage = 100; - if (splitted.length > 2) - percentage = SafeParse.stringToInt(splitted[2]); - - if (pindex > list.size()) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else if (percentage == 0) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else if (pindex == 0) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else { - final Profile profile = store.getSpecificProfile((String) list.get(pindex - 1)); - if (profile == null) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.noprofile)); - else { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_profilereplywithcode), list.get(pindex - 1), percentage, passCode); - receivedSms.processed = true; - int finalPercentage = percentage; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction((String) list.get(pindex - 1), finalPercentage) { - @Override - public void run() { - ProfileFunctions.doProfileSwitch(store, (String) list.get(pindex - 1), 0, finalPercentage, 0); - sendSMS(new Sms(receivedSms.phoneNumber, R.string.profileswitchcreated)); - } - }); - } - } - } - receivedSms.processed = true; - } - - private void processBASAL(String[] splitted, Sms receivedSms) { - if (splitted[1].toUpperCase().equals("CANCEL") || splitted[1].toUpperCase().equals("STOP")) { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_basalstopreplywithcode), passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction() { - @Override - public void run() { - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelTempBasal(true, new Callback() { - @Override - public void run() { - if (result.success) { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalcanceled); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalcancelfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - } - }); - } else if (splitted[1].endsWith("%")) { - int tempBasalPct = SafeParse.stringToInt(StringUtils.removeEnd(splitted[1], "%")); - int duration = 30; - if (splitted.length > 2) - duration = SafeParse.stringToInt(splitted[2]); - final Profile profile = ProfileFunctions.getInstance().getProfile(); - - if (profile == null) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.noprofile)); - else if (tempBasalPct == 0 && !splitted[1].equals("0%")) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else if (duration == 0) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else { - tempBasalPct = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(tempBasalPct), profile).value(); - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_basalpctreplywithcode), tempBasalPct, duration, passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction(tempBasalPct, duration) { - @Override - public void run() { - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(anInteger, secondInteger, true, profile, new Callback() { - @Override - public void run() { - if (result.success) { - String reply; - if (result.isPercent) - reply = String.format(MainApp.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration); - else - reply = String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - } - }); - } - } else { - Double tempBasal = SafeParse.stringToDouble(splitted[1]); - int duration = 30; - if (splitted.length > 2) - duration = SafeParse.stringToInt(splitted[2]); - final Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile == null) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.noprofile)); - else if (tempBasal == 0 && !splitted[1].equals("0")) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else if (duration == 0) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else { - tempBasal = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(tempBasal), profile).value(); - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, duration, passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction(tempBasal, duration) { - @Override - public void run() { - ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(aDouble, secondInteger, true, profile, new Callback() { - @Override - public void run() { - if (result.success) { - String reply; - if (result.isPercent) - reply = String.format(MainApp.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration); - else - reply = String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_tempbasalfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - } - }); - } - } - } - - private void processEXTENDED(String[] splitted, Sms receivedSms) { - if (splitted[1].toUpperCase().equals("CANCEL") || splitted[1].toUpperCase().equals("STOP")) { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_extendedstopreplywithcode), passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction() { - @Override - public void run() { - ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelExtended(new Callback() { - @Override - public void run() { - if (result.success) { - String reply = MainApp.gs(R.string.smscommunicator_extendedcanceled); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_extendedcancelfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - } - }); - } else if (splitted.length != 3) { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } else { - Double extended = SafeParse.stringToDouble(splitted[1]); - int duration = SafeParse.stringToInt(splitted[2]); - extended = MainApp.getConstraintChecker().applyExtendedBolusConstraints(new Constraint<>(extended)).value(); - if (extended == 0 || duration == 0) - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - else { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_extendedreplywithcode), extended, duration, passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction(extended, duration) { - @Override - public void run() { - ConfigBuilderPlugin.getPlugin().getCommandQueue().extendedBolus(aDouble, secondInteger, new Callback() { - @Override - public void run() { - if (result.success) { - String reply = String.format(MainApp.gs(R.string.smscommunicator_extendedset), aDouble, duration); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_extendedfailed); - reply += "\n" + ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - } - }); - } - } - } - - - private void processBOLUS(String[] splitted, Sms receivedSms) { - Double bolus = SafeParse.stringToDouble(splitted[1]); - final boolean isMeal = splitted.length > 2 && splitted[2].equalsIgnoreCase("MEAL"); - bolus = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(bolus)).value(); - - if (splitted.length == 3 && !isMeal) { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } else if (bolus > 0d) { - String passCode = generatePasscode(); - String reply = ""; - if (isMeal) { - reply = String.format(MainApp.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode); - } else { - reply = String.format(MainApp.gs(R.string.smscommunicator_bolusreplywithcode), bolus, passCode); - } - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction(bolus) { - @Override - public void run() { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = aDouble; - detailedBolusInfo.source = Source.USER; - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - final boolean resultSuccess = result.success; - final double resultBolusDelivered = result.bolusDelivered; - ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("SMS", new Callback() { - @Override - public void run() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (resultSuccess) { - String reply = ""; - if (isMeal) { - reply = String.format(MainApp.gs(R.string.smscommunicator_mealbolusdelivered), resultBolusDelivered); - } else { - reply = String.format(MainApp.gs(R.string.smscommunicator_bolusdelivered), resultBolusDelivered); - } - if (pump != null) - reply += "\n" + pump.shortStatus(true); - lastRemoteBolusTime = DateUtil.now(); - if (isMeal) { - Profile currentProfile = ProfileFunctions.getInstance().getProfile(); - 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; - - TempTarget tempTarget = new TempTarget() - .date(System.currentTimeMillis()) - .duration(eatingSoonTTDuration) - .reason(MainApp.gs(R.string.eatingsoon)) - .source(Source.USER) - .low(Profile.toMgdl(eatingSoonTT, currentProfile.getUnits())) - .high(Profile.toMgdl(eatingSoonTT, currentProfile.getUnits())); - TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); - String tt = ""; - if (currentProfile.getUnits().equals(Constants.MMOL)) { - tt = DecimalFormatter.to1Decimal(eatingSoonTT); - } else - tt = DecimalFormatter.to0Decimal(eatingSoonTT); - - reply += String.format(MainApp.gs(R.string.smscommunicator_mealbolusdelivered_tt), tt, eatingSoonTTDuration); - - - } - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - String reply = MainApp.gs(R.string.smscommunicator_bolusfailed); - if (pump != null) - reply += "\n" + pump.shortStatus(true); - sendSMS(new Sms(receivedSms.phoneNumber, reply)); - } - } - }); - } - }); - } - }); - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } - - private void processTARGET(String[] splitted, Sms receivedSms) { - boolean isMeal = splitted[1].equalsIgnoreCase("MEAL"); - boolean isActivity = splitted[1].equalsIgnoreCase("ACTIVITY"); - boolean isHypo = splitted[1].equalsIgnoreCase("HYPO"); - - if (isMeal || isActivity || isHypo) { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_temptargetwithcode), splitted[1].toUpperCase(), passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction() { - @Override - public void run() { - Profile currentProfile = ProfileFunctions.getInstance().getProfile(); - if (currentProfile != null) { - int keyDuration = 0; - Integer defaultTargetDuration = 0; - int keyTarget = 0; - double defaultTargetMMOL = 0d; - double defaultTargetMGDL = 0d; - - if (isMeal) { - keyDuration = R.string.key_eatingsoon_duration; - defaultTargetDuration = Constants.defaultEatingSoonTTDuration; - keyTarget = R.string.key_eatingsoon_target; - defaultTargetMMOL = Constants.defaultEatingSoonTTmmol; - defaultTargetMGDL = Constants.defaultEatingSoonTTmgdl; - } else if (isActivity) { - keyDuration = R.string.key_activity_duration; - defaultTargetDuration = Constants.defaultActivityTTDuration; - keyTarget = R.string.key_activity_target; - defaultTargetMMOL = Constants.defaultActivityTTmmol; - defaultTargetMGDL = Constants.defaultActivityTTmgdl; - - } else if (isHypo) { - keyDuration = R.string.key_hypo_duration; - defaultTargetDuration = Constants.defaultHypoTTDuration; - keyTarget = R.string.key_hypo_target; - defaultTargetMMOL = Constants.defaultHypoTTmmol; - defaultTargetMGDL = Constants.defaultHypoTTmgdl; - } - - int ttDuration = SP.getInt(keyDuration, defaultTargetDuration); - ttDuration = ttDuration > 0 ? ttDuration : defaultTargetDuration; - double tt = SP.getDouble(keyTarget, currentProfile.getUnits().equals(Constants.MMOL) ? defaultTargetMMOL : defaultTargetMGDL); - tt = tt > 0 ? tt : currentProfile.getUnits().equals(Constants.MMOL) ? defaultTargetMMOL : defaultTargetMGDL; - - TempTarget tempTarget = new TempTarget() - .date(System.currentTimeMillis()) - .duration(ttDuration) - .reason(MainApp.gs(R.string.eatingsoon)) - .source(Source.USER) - .low(Profile.toMgdl(tt, currentProfile.getUnits())) - .high(Profile.toMgdl(tt, currentProfile.getUnits())); - TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); - String ttString = ""; - if (currentProfile.getUnits().equals(Constants.MMOL)) - ttString = DecimalFormatter.to1Decimal(tt); - else - ttString = DecimalFormatter.to0Decimal(tt); - - String reply = String.format(MainApp.gs(R.string.smscommunicator_tt_set), ttString, ttDuration); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } else { - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_unknowncommand)); - } - } - }); - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } - - private void processSMS(String[] splitted, Sms receivedSms) { - boolean isStop = splitted[1].equalsIgnoreCase("STOP") - || splitted[1].equalsIgnoreCase("DISABLE"); - - if (isStop) { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_stopsmswithcode), passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction() { - @Override - public void run() { - SP.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false); - String reply = String.format(MainApp.gs(R.string.smscommunicator_stoppedsms)); - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply)); - } - }); - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } - - private void processCAL(String[] splitted, Sms receivedSms) { - Double cal = SafeParse.stringToDouble(splitted[1]); - if (cal > 0d) { - String passCode = generatePasscode(); - String reply = String.format(MainApp.gs(R.string.smscommunicator_calibrationreplywithcode), cal, passCode); - receivedSms.processed = true; - messageToConfirm = new AuthRequest(this, receivedSms, reply, passCode, new SmsAction(cal) { - @Override - public void run() { - boolean result = XdripCalibrations.sendIntent(aDouble); - if (result) - sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_calibrationsent)); - else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.smscommunicator_calibrationfailed)); - } - }); - } else - sendSMS(new Sms(receivedSms.phoneNumber, R.string.wrongformat)); - } - - public boolean sendNotificationToAllNumbers(String text) { - boolean result = true; - for (int i = 0; i < allowedNumbers.size(); i++) { - Sms sms = new Sms(allowedNumbers.get(i), text); - result = result && sendSMS(sms); - } - return result; - } - - private void sendSMSToAllNumbers(Sms sms) { - for (String number : allowedNumbers) { - sms.phoneNumber = number; - sendSMS(sms); - } - } - - boolean sendSMS(Sms sms) { - SmsManager smsManager = SmsManager.getDefault(); - sms.text = stripAccents(sms.text); - - try { - if (L.isEnabled(L.SMS)) - log.debug("Sending SMS to " + sms.phoneNumber + ": " + sms.text); - if (sms.text.getBytes().length <= 140) - smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null); - else { - ArrayList parts = smsManager.divideMessage(sms.text); - smsManager.sendMultipartTextMessage(sms.phoneNumber, null, parts, - null, null); - } - - messages.add(sms); - } catch (IllegalArgumentException e) { - if (e.getMessage().equals("Invalid message body")) { - Notification notification = new Notification(Notification.INVALID_MESSAGE_BODY, MainApp.gs(R.string.smscommunicator_messagebody), Notification.NORMAL); - RxBus.INSTANCE.send(new EventNewNotification(notification)); - return false; - } else { - Notification notification = new Notification(Notification.INVALID_PHONE_NUMBER, MainApp.gs(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL); - RxBus.INSTANCE.send(new EventNewNotification(notification)); - return false; - } - } catch (java.lang.SecurityException e) { - Notification notification = new Notification(Notification.MISSING_SMS_PERMISSION, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.NORMAL); - RxBus.INSTANCE.send(new EventNewNotification(notification)); - return false; - } - RxBus.INSTANCE.send(new EventSmsCommunicatorUpdateGui()); - return true; - } - - private String generatePasscode() { - int startChar1 = 'A'; // on iphone 1st char is uppercase :) - String passCode = Character.toString((char) (startChar1 + Math.random() * ('z' - 'a' + 1))); - int startChar2 = Math.random() > 0.5 ? 'a' : 'A'; - passCode += Character.toString((char) (startChar2 + Math.random() * ('z' - 'a' + 1))); - int startChar3 = Math.random() > 0.5 ? 'a' : 'A'; - passCode += Character.toString((char) (startChar3 + Math.random() * ('z' - 'a' + 1))); - passCode = passCode.replace('l', 'k').replace('I', 'J'); - return passCode; - } - - private static String stripAccents(String s) { - s = Normalizer.normalize(s, Normalizer.Form.NFD); - s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); - return s; - } - - public static boolean areMoreNumbers(String allowednumbers) { - int countNumbers = 0; - String[] substrings = allowednumbers.split(";"); - - for (String number : substrings) { - String cleaned = number.replaceAll("\\s+", ""); - if (cleaned.length() < 4) continue; - if (cleaned.substring(0, 1).compareTo("+") != 0) continue; - cleaned = cleaned.replace("+", ""); - if (!cleaned.matches("[0-9]+")) continue; - countNumbers++; - } - return countNumbers > 1; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt new file mode 100644 index 0000000000..037f17d0bb --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -0,0 +1,812 @@ +package info.nightscout.androidaps.plugins.general.smsCommunicator + +import android.content.Intent +import android.preference.EditTextPreference +import android.preference.Preference +import android.preference.Preference.OnPreferenceChangeListener +import android.preference.PreferenceFragment +import android.telephony.SmsManager +import android.telephony.SmsMessage +import android.text.TextUtils +import com.andreabaccega.widget.ValidatingEditTextPreference +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.db.DatabaseHelper +import info.nightscout.androidaps.db.Source +import info.nightscout.androidaps.db.TempTarget +import info.nightscout.androidaps.events.EventPreferenceChange +import info.nightscout.androidaps.events.EventRefreshOverview +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.logging.L +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.bus.RxBus.send +import info.nightscout.androidaps.plugins.bus.RxBus.toObservable +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.general.nsclient.events.EventNSClientRestart +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.utils.* +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers +import org.apache.commons.lang3.StringUtils +import org.slf4j.LoggerFactory +import java.text.Normalizer +import java.util.* + +/** + * Created by mike on 05.08.2016. + */ +class SmsCommunicatorPlugin internal constructor() : PluginBase(PluginDescription() + .mainType(PluginType.GENERAL) + .fragmentClass(SmsCommunicatorFragment::class.java.name) + .pluginName(R.string.smscommunicator) + .shortName(R.string.smscommunicator_shortname) + .preferencesId(R.xml.pref_smscommunicator) + .description(R.string.description_sms_communicator) +) { + private val disposable = CompositeDisposable() + var allowedNumbers: MutableList = ArrayList() + var messageToConfirm: AuthRequest? = null + var lastRemoteBolusTime: Long = 0 + var messages = ArrayList() + + override fun onStart() { + super.onStart() + disposable.add(toObservable(EventPreferenceChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventPreferenceChange? -> processSettings(event) }) { throwable: Throwable? -> FabricPrivacy.logException(throwable) } + ) + } + + override fun onStop() { + disposable.clear() + super.onStop() + } + + override fun preprocessPreferences(preferenceFragment: PreferenceFragment) { + super.preprocessPreferences(preferenceFragment) + val distance = preferenceFragment.findPreference(MainApp.gs(R.string.key_smscommunicator_remotebolusmindistance)) as ValidatingEditTextPreference + val allowedNumbers = preferenceFragment.findPreference(MainApp.gs(R.string.key_smscommunicator_allowednumbers)) as EditTextPreference + if (distance != null && allowedNumbers != null) { + if (!areMoreNumbers(allowedNumbers.text)) { + distance.title = (MainApp.gs(R.string.smscommunicator_remotebolusmindistance) + + ".\n" + + MainApp.gs(R.string.smscommunicator_remotebolusmindistance_caveat)) + distance.isEnabled = false + } else { + distance.title = MainApp.gs(R.string.smscommunicator_remotebolusmindistance) + distance.isEnabled = true + } + allowedNumbers.onPreferenceChangeListener = OnPreferenceChangeListener { preference: Preference?, newValue: Any -> + if (!areMoreNumbers(newValue as String)) { + distance.text = (Constants.remoteBolusMinDistance / (60 * 1000L)).toString() + distance.title = (MainApp.gs(R.string.smscommunicator_remotebolusmindistance) + + ".\n" + + MainApp.gs(R.string.smscommunicator_remotebolusmindistance_caveat)) + distance.isEnabled = false + } else { + distance.title = MainApp.gs(R.string.smscommunicator_remotebolusmindistance) + distance.isEnabled = true + } + true + } + } + } + + override fun updatePreferenceSummary(pref: Preference) { + super.updatePreferenceSummary(pref) + if (pref is EditTextPreference) { + val editTextPref = pref + if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.text == null || TextUtils.isEmpty(editTextPref.text.trim { it <= ' ' }))) { + pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary)) + } + } + } + + private fun processSettings(ev: EventPreferenceChange?) { + if (ev == null || ev.isChanged(R.string.key_smscommunicator_allowednumbers)) { + val settings = SP.getString(R.string.key_smscommunicator_allowednumbers, "") + allowedNumbers.clear() + val substrings = settings.split(";").toTypedArray() + for (number in substrings) { + val cleaned = number.replace("\\s+".toRegex(), "") + allowedNumbers.add(cleaned) + log.debug("Found allowed number: $cleaned") + } + } + } + + fun isCommand(command: String, number: String): Boolean { + when (command.toUpperCase(Locale.getDefault())) { + "BG", "LOOP", "TREATMENTS", "NSCLIENT", "PUMP", "BASAL", "BOLUS", "EXTENDED", "CAL", "PROFILE", "TARGET", "SMS" -> return true + } + return messageToConfirm?.requester?.phoneNumber == number + } + + fun isAllowedNumber(number: String): Boolean { + for (num in allowedNumbers) { + if (num == number) return true + } + return false + } + + fun handleNewData(intent: Intent) { + val bundle = intent.extras ?: return + val pdus = bundle["pdus"] as Array<*> + for (pdu in pdus) { + val message = SmsMessage.createFromPdu(pdu as ByteArray) + processSms(Sms(message)) + } + } + + fun processSms(receivedSms: Sms) { + if (!isEnabled(PluginType.GENERAL)) { + log.debug("Ignoring SMS. Plugin disabled.") + return + } + if (!isAllowedNumber(receivedSms.phoneNumber)) { + log.debug("Ignoring SMS from: " + receivedSms.phoneNumber + ". Sender not allowed") + receivedSms.ignored = true + messages.add(receivedSms) + send(EventSmsCommunicatorUpdateGui()) + return + } + val pump = ConfigBuilderPlugin.getPlugin().activePump ?: return + messages.add(receivedSms) + log.debug(receivedSms.toString()) + val splitted = receivedSms.text.split(Regex("\\s+")).toTypedArray() + val remoteCommandsAllowed = SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false) + if (splitted.isNotEmpty() && isCommand(splitted[0].toUpperCase(Locale.getDefault()), receivedSms.phoneNumber)) { + when (splitted[0].toUpperCase(Locale.getDefault())) { + "BG" -> + if (splitted.size == 1) processBG(receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "LOOP" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2 || splitted.size == 3) processLOOP(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "TREATMENTS" -> + if (splitted.size == 2) processTREATMENTS(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "NSCLIENT" -> + if (splitted.size == 2) processNSCLIENT(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "PUMP" -> + if (splitted.size == 1) processPUMP(receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "PROFILE" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2 || splitted.size == 3) processPROFILE(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "BASAL" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2 || splitted.size == 3) processBASAL(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "EXTENDED" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2 || splitted.size == 3) processEXTENDED(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "BOLUS" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2 && DateUtil.now() - lastRemoteBolusTime < Constants.remoteBolusMinDistance) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotebolusnotallowed)) + else if (splitted.size == 2 && pump.isSuspended) sendSMS(Sms(receivedSms.phoneNumber, R.string.pumpsuspended)) + else if (splitted.size == 2 || splitted.size == 3) processBOLUS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "CAL" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2) processCAL(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "TARGET" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2) processTARGET(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "SMS" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2) processSMS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else -> + if (messageToConfirm?.requester?.phoneNumber == receivedSms.phoneNumber) { + messageToConfirm?.action(splitted[0]) + messageToConfirm = null + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_unknowncommand)) + } + } + send(EventSmsCommunicatorUpdateGui()) + } + + private fun processBG(receivedSms: Sms) { + val actualBG = DatabaseHelper.actualBg() + val lastBG = DatabaseHelper.lastBg() + var reply = "" + val units = ProfileFunctions.getInstance().profileUnits + if (actualBG != null) { + reply = MainApp.gs(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", " + } else if (lastBG != null) { + val agoMsec = System.currentTimeMillis() - lastBG.date + val agoMin = (agoMsec / 60.0 / 1000.0).toInt() + reply = MainApp.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.gs(R.string.sms_minago), agoMin) + ", " + } + val glucoseStatus = GlucoseStatus.getGlucoseStatusData() + if (glucoseStatus != null) reply += MainApp.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", " + TreatmentsPlugin.getPlugin().updateTotalIOBTreatments() + val bolusIob = TreatmentsPlugin.getPlugin().lastCalculationTreatments.round() + TreatmentsPlugin.getPlugin().updateTotalIOBTempBasals() + val basalIob = TreatmentsPlugin.getPlugin().lastCalculationTempBasals.round() + val cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "SMS COB") + reply += (MainApp.gs(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U (" + + MainApp.gs(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U " + + MainApp.gs(R.string.sms_basal) + " " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U), " + + MainApp.gs(R.string.cob) + ": " + cobInfo.generateCOBString()) + sendSMS(Sms(receivedSms.phoneNumber, reply)) + receivedSms.processed = true + } + + private fun processLOOP(splitted: Array, receivedSms: Sms) { + when (splitted[1].toUpperCase(Locale.getDefault())) { + "DISABLE", "STOP" -> { + val loopPlugin = LoopPlugin.getPlugin() + if (loopPlugin.isEnabled(PluginType.LOOP)) { + loopPlugin.setPluginEnabled(PluginType.LOOP, false) + ConfigBuilderPlugin.getPlugin().commandQueue.cancelTempBasal(true, object : Callback() { + override fun run() { + send(EventRefreshOverview("SMS_LOOP_STOP")) + val replyText = MainApp.gs(R.string.smscommunicator_loophasbeendisabled) + " " + + MainApp.gs(if (result.success) R.string.smscommunicator_tempbasalcanceled else R.string.smscommunicator_tempbasalcancelfailed) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + }) + } else { + sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisdisabled)) + } + receivedSms.processed = true + } + "ENABLE", "START" -> { + val loopPlugin = LoopPlugin.getPlugin() + if (!loopPlugin.isEnabled(PluginType.LOOP)) { + loopPlugin.setPluginEnabled(PluginType.LOOP, true) + sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loophasbeenenabled)) + send(EventRefreshOverview("SMS_LOOP_START")) + } else { + sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisenabled)) + } + receivedSms.processed = true + } + "STATUS" -> { + val loopPlugin = LoopPlugin.getPlugin() + val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) { + if (loopPlugin.isSuspended()) String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) else MainApp.gs(R.string.smscommunicator_loopisenabled) + } else { + MainApp.gs(R.string.smscommunicator_loopisdisabled) + } + sendSMS(Sms(receivedSms.phoneNumber, reply)) + receivedSms.processed = true + } + "RESUME" -> { + LoopPlugin.getPlugin().suspendTo(0) + send(EventRefreshOverview("SMS_LOOP_RESUME")) + NSUpload.uploadOpenAPSOffline(0.0) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopresumed)) + } + "SUSPEND" -> { + var duration = 0 + if (splitted.size == 3) duration = SafeParse.stringToInt(splitted[2]) + duration = Math.max(0, duration) + duration = Math.min(180, duration) + if (duration == 0) { + receivedSms.processed = true + sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_wrongduration)) + return + } else { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_suspendreplywithcode), duration, passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(duration) { + override fun run() { + ConfigBuilderPlugin.getPlugin().commandQueue.cancelTempBasal(true, object : Callback() { + override fun run() { + if (result.success) { + LoopPlugin.getPlugin().suspendTo(System.currentTimeMillis() + anInteger * 60L * 1000) + NSUpload.uploadOpenAPSOffline(anInteger * 60.toDouble()) + send(EventRefreshOverview("SMS_LOOP_SUSPENDED")) + val replyText = MainApp.gs(R.string.smscommunicator_loopsuspended) + " " + + MainApp.gs(if (result.success) R.string.smscommunicator_tempbasalcanceled else R.string.smscommunicator_tempbasalcancelfailed) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_tempbasalcancelfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } + } + else -> sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + } + + private fun processTREATMENTS(splitted: Array, receivedSms: Sms) { + if (splitted[1].toUpperCase(Locale.getDefault()) == "REFRESH") { + TreatmentsPlugin.getPlugin().service.resetTreatments() + send(EventNSClientRestart()) + sendSMS(Sms(receivedSms.phoneNumber, "TREATMENTS REFRESH SENT")) + receivedSms.processed = true + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + + private fun processNSCLIENT(splitted: Array, receivedSms: Sms) { + if (splitted[1].toUpperCase(Locale.getDefault()) == "RESTART") { + send(EventNSClientRestart()) + sendSMS(Sms(receivedSms.phoneNumber, "NSCLIENT RESTART SENT")) + receivedSms.processed = true + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + + private fun processPUMP(receivedSms: Sms) { + ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("SMS", object : Callback() { + override fun run() { + val pump = ConfigBuilderPlugin.getPlugin().activePump + if (result.success) { + if (pump != null) { + val reply = pump.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, reply)) + } + } else { + val reply = MainApp.gs(R.string.readstatusfailed) + sendSMS(Sms(receivedSms.phoneNumber, reply)) + } + } + }) + receivedSms.processed = true + } + + private fun processPROFILE(splitted: Array, receivedSms: Sms) { // load profiles + val anInterface = ConfigBuilderPlugin.getPlugin().activeProfileInterface + if (anInterface == null) { + sendSMS(Sms(receivedSms.phoneNumber, R.string.notconfigured)) + receivedSms.processed = true + return + } + val store = anInterface.profile + if (store == null) { + sendSMS(Sms(receivedSms.phoneNumber, R.string.notconfigured)) + receivedSms.processed = true + return + } + val list = store.profileList + if (splitted[1].toUpperCase(Locale.getDefault()) == "STATUS") { + sendSMS(Sms(receivedSms.phoneNumber, ProfileFunctions.getInstance().profileName)) + } else if (splitted[1].toUpperCase(Locale.getDefault()) == "LIST") { + if (list.isEmpty()) sendSMS(Sms(receivedSms.phoneNumber, R.string.invalidprofile)) else { + var reply = "" + for (i in list.indices) { + if (i > 0) reply += "\n" + reply += (i + 1).toString() + ". " + reply += list[i] + } + sendSMS(Sms(receivedSms.phoneNumber, reply)) + } + } else { + val pindex = SafeParse.stringToInt(splitted[1]) + var percentage = 100 + if (splitted.size > 2) percentage = SafeParse.stringToInt(splitted[2]) + if (pindex > list.size) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (percentage == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (pindex == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + val profile = store.getSpecificProfile(list[pindex - 1] as String) + if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) else { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_profilereplywithcode), list[pindex - 1], percentage, passCode) + receivedSms.processed = true + val finalPercentage = percentage + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(list[pindex - 1] as String, finalPercentage) { + override fun run() { + ProfileFunctions.doProfileSwitch(store, list[pindex - 1] as String, 0, finalPercentage, 0) + sendSMS(Sms(receivedSms.phoneNumber, R.string.profileswitchcreated)) + } + }) + } + } + } + receivedSms.processed = true + } + + private fun processBASAL(splitted: Array, receivedSms: Sms) { + if (splitted[1].toUpperCase(Locale.getDefault()) == "CANCEL" || splitted[1].toUpperCase(Locale.getDefault()) == "STOP") { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_basalstopreplywithcode), passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction() { + override fun run() { + ConfigBuilderPlugin.getPlugin().commandQueue.cancelTempBasal(true, object : Callback() { + override fun run() { + if (result.success) { + var replyText = MainApp.gs(R.string.smscommunicator_tempbasalcanceled) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_tempbasalcancelfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } else if (splitted[1].endsWith("%")) { + var tempBasalPct = SafeParse.stringToInt(StringUtils.removeEnd(splitted[1], "%")) + var duration = 30 + if (splitted.size > 2) duration = SafeParse.stringToInt(splitted[2]) + val profile = ProfileFunctions.getInstance().profile + if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) else if (tempBasalPct == 0 && splitted[1] != "0%") sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + tempBasalPct = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value() + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_basalpctreplywithcode), tempBasalPct, duration, passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(tempBasalPct, duration) { + override fun run() { + ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(anInteger, secondInteger, true, profile, object : Callback() { + override fun run() { + if (result.success) { + var replyText: String + replyText = if (result.isPercent) String.format(MainApp.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_tempbasalfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } + } else { + var tempBasal = SafeParse.stringToDouble(splitted[1]) + var duration = 30 + if (splitted.size > 2) duration = SafeParse.stringToInt(splitted[2]) + val profile = ProfileFunctions.getInstance().profile + if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) else if (tempBasal == 0.0 && splitted[1] != "0") sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + tempBasal = MainApp.getConstraintChecker().applyBasalConstraints(Constraint(tempBasal), profile).value() + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, duration, passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(tempBasal, duration) { + override fun run() { + ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(aDouble, secondInteger, true, profile, object : Callback() { + override fun run() { + if (result.success) { + var replyText = if (result.isPercent) String.format(MainApp.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_tempbasalfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } + } + } + + private fun processEXTENDED(splitted: Array, receivedSms: Sms) { + if (splitted[1].toUpperCase(Locale.getDefault()) == "CANCEL" || splitted[1].toUpperCase(Locale.getDefault()) == "STOP") { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_extendedstopreplywithcode), passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction() { + override fun run() { + ConfigBuilderPlugin.getPlugin().commandQueue.cancelExtended(object : Callback() { + override fun run() { + if (result.success) { + var replyText = MainApp.gs(R.string.smscommunicator_extendedcanceled) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_extendedcancelfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } else if (splitted.size != 3) { + sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } else { + var extended = SafeParse.stringToDouble(splitted[1]) + val duration = SafeParse.stringToInt(splitted[2]) + extended = MainApp.getConstraintChecker().applyExtendedBolusConstraints(Constraint(extended)).value() + if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_extendedreplywithcode), extended, duration, passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(extended, duration) { + override fun run() { + ConfigBuilderPlugin.getPlugin().commandQueue.extendedBolus(aDouble, secondInteger, object : Callback() { + override fun run() { + if (result.success) { + var replyText = String.format(MainApp.gs(R.string.smscommunicator_extendedset), aDouble, duration) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_extendedfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } + } + } + + private fun processBOLUS(splitted: Array, receivedSms: Sms) { + var bolus = SafeParse.stringToDouble(splitted[1]) + val isMeal = splitted.size > 2 && splitted[2].equals("MEAL", ignoreCase = true) + bolus = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(bolus)).value() + if (splitted.size == 3 && !isMeal) { + sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } else if (bolus > 0.0) { + val passCode = generatePasscode() + val reply = if (isMeal) { + String.format(MainApp.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode) + } else { + String.format(MainApp.gs(R.string.smscommunicator_bolusreplywithcode), bolus, passCode) + } + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(bolus) { + override fun run() { + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.insulin = aDouble + detailedBolusInfo.source = Source.USER + ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + val resultSuccess = result.success + val resultBolusDelivered = result.bolusDelivered + ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("SMS", object : Callback() { + override fun run() { + if (resultSuccess) { + var replyText = if (isMeal) { + String.format(MainApp.gs(R.string.smscommunicator_mealbolusdelivered), resultBolusDelivered) + } else { + String.format(MainApp.gs(R.string.smscommunicator_bolusdelivered), resultBolusDelivered) + } + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + lastRemoteBolusTime = DateUtil.now() + if (isMeal) { + ProfileFunctions.getInstance().profile?.let { currentProfile -> + var eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration) + eatingSoonTTDuration = if (eatingSoonTTDuration > 0) eatingSoonTTDuration else Constants.defaultEatingSoonTTDuration + var eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl) + eatingSoonTT = if (eatingSoonTT > 0) eatingSoonTT else if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl + val tempTarget = TempTarget() + .date(System.currentTimeMillis()) + .duration(eatingSoonTTDuration) + .reason(MainApp.gs(R.string.eatingsoon)) + .source(Source.USER) + .low(Profile.toMgdl(eatingSoonTT, currentProfile.units)) + .high(Profile.toMgdl(eatingSoonTT, currentProfile.units)) + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) + val tt = if (currentProfile.units == Constants.MMOL) { + DecimalFormatter.to1Decimal(eatingSoonTT) + } else DecimalFormatter.to0Decimal(eatingSoonTT) + replyText += "\n" + String.format(MainApp.gs(R.string.smscommunicator_mealbolusdelivered_tt), tt, eatingSoonTTDuration) + } + } + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_bolusfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } + }) + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + + private fun processTARGET(splitted: Array, receivedSms: Sms) { + val isMeal = splitted[1].equals("MEAL", ignoreCase = true) + val isActivity = splitted[1].equals("ACTIVITY", ignoreCase = true) + val isHypo = splitted[1].equals("HYPO", ignoreCase = true) + if (isMeal || isActivity || isHypo) { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_temptargetwithcode), splitted[1].toUpperCase(Locale.getDefault()), passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction() { + override fun run() { + val currentProfile = ProfileFunctions.getInstance().profile + if (currentProfile != null) { + var keyDuration = 0 + var defaultTargetDuration = 0 + var keyTarget = 0 + var defaultTargetMMOL = 0.0 + var defaultTargetMGDL = 0.0 + if (isMeal) { + keyDuration = R.string.key_eatingsoon_duration + defaultTargetDuration = Constants.defaultEatingSoonTTDuration + keyTarget = R.string.key_eatingsoon_target + defaultTargetMMOL = Constants.defaultEatingSoonTTmmol + defaultTargetMGDL = Constants.defaultEatingSoonTTmgdl + } else if (isActivity) { + keyDuration = R.string.key_activity_duration + defaultTargetDuration = Constants.defaultActivityTTDuration + keyTarget = R.string.key_activity_target + defaultTargetMMOL = Constants.defaultActivityTTmmol + defaultTargetMGDL = Constants.defaultActivityTTmgdl + } else if (isHypo) { + keyDuration = R.string.key_hypo_duration + defaultTargetDuration = Constants.defaultHypoTTDuration + keyTarget = R.string.key_hypo_target + defaultTargetMMOL = Constants.defaultHypoTTmmol + defaultTargetMGDL = Constants.defaultHypoTTmgdl + } + var ttDuration = SP.getInt(keyDuration, defaultTargetDuration) + ttDuration = if (ttDuration > 0) ttDuration else defaultTargetDuration + var tt = SP.getDouble(keyTarget, if (currentProfile.units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL) + tt = if (tt > 0) tt else if (currentProfile.units == Constants.MMOL) defaultTargetMMOL else defaultTargetMGDL + val tempTarget = TempTarget() + .date(System.currentTimeMillis()) + .duration(ttDuration) + .reason(MainApp.gs(R.string.eatingsoon)) + .source(Source.USER) + .low(Profile.toMgdl(tt, currentProfile.units)) + .high(Profile.toMgdl(tt, currentProfile.units)) + TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget) + val ttString = if (currentProfile.units == Constants.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt) + val replyText = String.format(MainApp.gs(R.string.smscommunicator_tt_set), ttString, ttDuration) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_unknowncommand)) + } + } + }) + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + + private fun processSMS(splitted: Array, receivedSms: Sms) { + val isStop = (splitted[1].equals("STOP", ignoreCase = true) + || splitted[1].equals("DISABLE", ignoreCase = true)) + if (isStop) { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_stopsmswithcode), passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction() { + override fun run() { + SP.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false) + val replyText = String.format(MainApp.gs(R.string.smscommunicator_stoppedsms)) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } + }) + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + + private fun processCAL(splitted: Array, receivedSms: Sms) { + val cal = SafeParse.stringToDouble(splitted[1]) + if (cal > 0.0) { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_calibrationreplywithcode), cal, passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(cal) { + override fun run() { + val result = XdripCalibrations.sendIntent(aDouble) + if (result) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, R.string.smscommunicator_calibrationsent)) else sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_calibrationfailed)) + } + }) + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } + + fun sendNotificationToAllNumbers(text: String?): Boolean { + var result = true + for (i in allowedNumbers.indices) { + val sms = Sms(allowedNumbers[i], text) + result = result && sendSMS(sms) + } + return result + } + + private fun sendSMSToAllNumbers(sms: Sms) { + for (number in allowedNumbers) { + sms.phoneNumber = number + sendSMS(sms) + } + } + + fun sendSMS(sms: Sms): Boolean { + val smsManager = SmsManager.getDefault() + sms.text = stripAccents(sms.text) + try { + if (L.isEnabled(L.SMS)) log.debug("Sending SMS to " + sms.phoneNumber + ": " + sms.text) + if (sms.text.toByteArray().size <= 140) smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null) else { + val parts = smsManager.divideMessage(sms.text) + smsManager.sendMultipartTextMessage(sms.phoneNumber, null, parts, + null, null) + } + messages.add(sms) + } catch (e: IllegalArgumentException) { + return if (e.message == "Invalid message body") { + val notification = Notification(Notification.INVALID_MESSAGE_BODY, MainApp.gs(R.string.smscommunicator_messagebody), Notification.NORMAL) + send(EventNewNotification(notification)) + false + } else { + val notification = Notification(Notification.INVALID_PHONE_NUMBER, MainApp.gs(R.string.smscommunicator_invalidphonennumber), Notification.NORMAL) + send(EventNewNotification(notification)) + false + } + } catch (e: SecurityException) { + val notification = Notification(Notification.MISSING_SMS_PERMISSION, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.NORMAL) + send(EventNewNotification(notification)) + return false + } + send(EventSmsCommunicatorUpdateGui()) + return true + } + + private fun generatePasscode(): String { + val startChar1 = 'A'.toInt() // on iphone 1st char is uppercase :) + var passCode = Character.toString((startChar1 + Math.random() * ('z' - 'a' + 1)).toChar()) + val startChar2: Int = if (Math.random() > 0.5) 'a'.toInt() else 'A'.toInt() + passCode += Character.toString((startChar2 + Math.random() * ('z' - 'a' + 1)).toChar()) + val startChar3: Int = if (Math.random() > 0.5) 'a'.toInt() else 'A'.toInt() + passCode += Character.toString((startChar3 + Math.random() * ('z' - 'a' + 1)).toChar()) + passCode = passCode.replace('l', 'k').replace('I', 'J') + return passCode + } + + companion object { + private val log = LoggerFactory.getLogger(L.SMS) + private var smsCommunicatorPlugin: SmsCommunicatorPlugin? = null + @JvmStatic + val plugin: SmsCommunicatorPlugin? + get() { + if (smsCommunicatorPlugin == null) { + smsCommunicatorPlugin = SmsCommunicatorPlugin() + } + return smsCommunicatorPlugin + } + + private fun stripAccents(str: String): String { + var s = str + s = Normalizer.normalize(s, Normalizer.Form.NFD) + s = s.replace("[\\p{InCombiningDiacriticalMarks}]".toRegex(), "") + return s + } + + fun areMoreNumbers(allowednumbers: String): Boolean { + var countNumbers = 0 + val substrings = allowednumbers.split(";").toTypedArray() + for (number in substrings) { + var cleaned = number.replace(Regex("\\s+"), "") + if (cleaned.length < 4) continue + if (cleaned.substring(0, 1).compareTo("+") != 0) continue + cleaned = cleaned.replace("+", "") + if (!cleaned.matches(Regex("[0-9]+"))) continue + countNumbers++ + } + return countNumbers > 1 + } + } + + init { + processSettings(null) + } +} \ 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 9f37cc9a85..2fba2a59fe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -307,7 +307,7 @@ Bolus %1$.2fU delivered successfully Meal Bolus %1$.2fU delivered successfully Target %1$s for %2$d minutes - Target %1$s for %2$d minutes set succesfully + Target %1$s for %2$d minutes set successfully Delivering %1$.2fU Allow remote commands via SMS Finger diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java index a36c989b11..bd01e6b89b 100644 --- a/app/src/test/java/info/AAPSMocker.java +++ b/app/src/test/java/info/AAPSMocker.java @@ -155,6 +155,9 @@ public class AAPSMocker { when(MainApp.gs(R.string.pumpNotInitialized)).thenReturn("Pump not initialized!"); when(MainApp.gs(R.string.increasingmaxbasal)).thenReturn("Increasing max basal value because setting is lower than your max basal in profile"); when(MainApp.gs(R.string.overview_bolusprogress_delivered)).thenReturn("Delivered"); + when(MainApp.gs(R.string.smscommunicator_mealbolusreplywithcode)).thenReturn("To deliver meal bolus %1$.2fU reply with code %2$s"); + when(MainApp.gs(R.string.smscommunicator_mealbolusdelivered)).thenReturn("Meal Bolus %1$.2fU delivered successfully"); + when(MainApp.gs(R.string.smscommunicator_mealbolusdelivered_tt)).thenReturn("Target %1$s for %2$d minutes"); } public static MainApp mockMainApp() { diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java index dd41f9873a..7b53e214a8 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java @@ -8,8 +8,6 @@ import org.mockito.stubbing.Answer; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.util.Date; - import info.AAPSMocker; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; @@ -28,9 +26,9 @@ import static org.powermock.api.mockito.PowerMockito.when; @PrepareForTest({SmsCommunicatorPlugin.class, L.class, SP.class, MainApp.class, DateUtil.class}) public class AuthRequestTest { - SmsCommunicatorPlugin smsCommunicatorPlugin; - Sms sentSms; - boolean actionCalled = false; + private SmsCommunicatorPlugin smsCommunicatorPlugin; + private Sms sentSms; + private boolean actionCalled = false; @Test public void doTests() { diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java index 6e83032504..77324d9627 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java @@ -25,7 +25,6 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.interfaces.Constraint; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.ProfileInterface; -import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; @@ -67,27 +66,29 @@ public class SmsCommunicatorPluginTest { private boolean hasBeenRun = false; + private VirtualPumpPlugin virtualPumpPlugin; + @Test public void processSettingsTest() { // called from constructor - Assert.assertEquals("1234", smsCommunicatorPlugin.allowedNumbers.get(0)); - Assert.assertEquals("5678", smsCommunicatorPlugin.allowedNumbers.get(1)); - Assert.assertEquals(2, smsCommunicatorPlugin.allowedNumbers.size()); + Assert.assertEquals("1234", smsCommunicatorPlugin.getAllowedNumbers().get(0)); + Assert.assertEquals("5678", smsCommunicatorPlugin.getAllowedNumbers().get(1)); + Assert.assertEquals(2, smsCommunicatorPlugin.getAllowedNumbers().size()); } @Test public void isCommandTest() { Assert.assertTrue(smsCommunicatorPlugin.isCommand("BOLUS", "")); - smsCommunicatorPlugin.messageToConfirm = null; + smsCommunicatorPlugin.setMessageToConfirm(null); Assert.assertFalse(smsCommunicatorPlugin.isCommand("BLB", "")); - smsCommunicatorPlugin.messageToConfirm = new AuthRequest(smsCommunicatorPlugin, new Sms("1234", "ddd"), "RequestText", "ccode", new SmsAction() { + smsCommunicatorPlugin.setMessageToConfirm(new AuthRequest(smsCommunicatorPlugin, new Sms("1234", "ddd"), "RequestText", "ccode", new SmsAction() { @Override public void run() { } - }); + })); Assert.assertTrue(smsCommunicatorPlugin.isCommand("BLB", "1234")); Assert.assertFalse(smsCommunicatorPlugin.isCommand("BLB", "2345")); - smsCommunicatorPlugin.messageToConfirm = null; + smsCommunicatorPlugin.setMessageToConfirm(null); } @Test @@ -101,82 +102,82 @@ public class SmsCommunicatorPluginTest { Sms sms; // SMS from not allowed number should be ignored - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("12", "aText"); smsCommunicatorPlugin.processSms(sms); Assert.assertTrue(sms.ignored); - Assert.assertEquals("aText", smsCommunicatorPlugin.messages.get(0).text); + Assert.assertEquals("aText", smsCommunicatorPlugin.getMessages().get(0).text); //UNKNOWN - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "UNKNOWN"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("UNKNOWN", smsCommunicatorPlugin.messages.get(0).text); + Assert.assertEquals("UNKNOWN", smsCommunicatorPlugin.getMessages().get(0).text); //BG - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BG"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BG", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("IOB:")); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("Last BG: 100")); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("COB: 10(2)g")); + Assert.assertEquals("BG", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("IOB:")); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("Last BG: 100")); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("COB: 10(2)g")); // LOOP : test remote control disabled when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP STATUS"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("Remote command is not allowed")); + Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("Remote command is not allowed")); when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); //LOOP STATUS : disabled when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP STATUS"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop is disabled", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop is disabled", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP STATUS : suspended when(loopPlugin.minutesToEndOfSuspend()).thenReturn(10); when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(true); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP STATUS"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Suspended (10 m)", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Suspended (10 m)", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP STATUS : enabled when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP STATUS"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop is enabled", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP STATUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop is enabled", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP : wrong format when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP DISABLE : already disabled when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP DISABLE"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP DISABLE", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop is disabled", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP DISABLE", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop is disabled", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP DISABLE : from enabled hasBeenRun = false; @@ -185,22 +186,22 @@ public class SmsCommunicatorPluginTest { hasBeenRun = true; return null; }).when(loopPlugin).setPluginEnabled(PluginType.LOOP, false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP DISABLE"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP DISABLE", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop has been disabled Temp basal canceled", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP DISABLE", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop has been disabled Temp basal canceled", smsCommunicatorPlugin.getMessages().get(1).text); Assert.assertTrue(hasBeenRun); //LOOP ENABLE : already enabled when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP ENABLE"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP ENABLE", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop is enabled", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP ENABLE", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop is enabled", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP ENABLE : from disabled hasBeenRun = false; @@ -209,142 +210,142 @@ public class SmsCommunicatorPluginTest { hasBeenRun = true; return null; }).when(loopPlugin).setPluginEnabled(PluginType.LOOP, true); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP ENABLE"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP ENABLE", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop has been enabled", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP ENABLE", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop has been enabled", smsCommunicatorPlugin.getMessages().get(1).text); Assert.assertTrue(hasBeenRun); //LOOP RESUME : already enabled - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP RESUME"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP RESUME", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Loop resumed", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP RESUME", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Loop resumed", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP SUSPEND 1 2: wrong format - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP SUSPEND 1 2"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP SUSPEND 1 2", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP SUSPEND 1 2", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP SUSPEND 0 : wrong duration - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP SUSPEND 0"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP SUSPEND 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong duration", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP SUSPEND 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong duration", smsCommunicatorPlugin.getMessages().get(1).text); //LOOP SUSPEND 100 : suspend for 100 min + correct answer - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP SUSPEND 100"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP SUSPEND 100", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To suspend loop for 100 minutes reply with code ")); - String passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("LOOP SUSPEND 100", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To suspend loop for 100 minutes reply with code ")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Loop suspended Temp basal canceled", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Loop suspended Temp basal canceled", smsCommunicatorPlugin.getMessages().get(3).text); //LOOP SUSPEND 200 : limit to 180 min + wrong answer - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP SUSPEND 200"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP SUSPEND 200", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To suspend loop for 180 minutes reply with code ")); - passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("LOOP SUSPEND 200", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To suspend loop for 180 minutes reply with code ")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; // ignore from other number smsCommunicatorPlugin.processSms(new Sms("5678", passCode)); smsCommunicatorPlugin.processSms(new Sms("1234", "XXXX")); - Assert.assertEquals("XXXX", smsCommunicatorPlugin.messages.get(3).text); - Assert.assertEquals("Wrong code. Command cancelled.", smsCommunicatorPlugin.messages.get(4).text); + Assert.assertEquals("XXXX", smsCommunicatorPlugin.getMessages().get(3).text); + Assert.assertEquals("Wrong code. Command cancelled.", smsCommunicatorPlugin.getMessages().get(4).text); //then correct code should not work smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(5).text); - Assert.assertEquals(6, smsCommunicatorPlugin.messages.size()); // processed as common message + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(5).text); + Assert.assertEquals(6, smsCommunicatorPlugin.getMessages().size()); // processed as common message //LOOP BLABLA - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "LOOP BLABLA"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("LOOP BLABLA", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("LOOP BLABLA", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //TREATMENTS REFRESH when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "TREATMENTS REFRESH"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("TREATMENTS REFRESH", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("TREATMENTS REFRESH")); + Assert.assertEquals("TREATMENTS REFRESH", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("TREATMENTS REFRESH")); //TREATMENTS BLA BLA when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "TREATMENTS BLA BLA"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("TREATMENTS BLA BLA", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("TREATMENTS BLA BLA", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //TREATMENTS BLABLA when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "TREATMENTS BLABLA"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("TREATMENTS BLABLA", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("TREATMENTS BLABLA", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //NSCLIENT RESTART when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "NSCLIENT RESTART"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("NSCLIENT RESTART", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("NSCLIENT RESTART")); + Assert.assertEquals("NSCLIENT RESTART", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("NSCLIENT RESTART")); //NSCLIENT BLA BLA when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "NSCLIENT BLA BLA"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("NSCLIENT BLA BLA", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("NSCLIENT BLA BLA", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //NSCLIENT BLABLA when(loopPlugin.isEnabled(PluginType.LOOP)).thenReturn(true); when(loopPlugin.isSuspended()).thenReturn(false); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "NSCLIENT BLABLA"); smsCommunicatorPlugin.processSms(sms); Assert.assertFalse(sms.ignored); - Assert.assertEquals("NSCLIENT BLABLA", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("NSCLIENT BLABLA", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //PUMP - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PUMP"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PUMP", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Virtual Pump", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PUMP", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Virtual Pump", smsCommunicatorPlugin.getMessages().get(1).text); } @@ -353,92 +354,92 @@ public class SmsCommunicatorPluginTest { Sms sms; //PROFILE - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.getMessages().get(1).text); when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); //PROFILE - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //PROFILE LIST (no profile interface) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE LIST"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE LIST", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Not configured", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE LIST", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Not configured", smsCommunicatorPlugin.getMessages().get(1).text); ProfileInterface profileInterface = mock(SimpleProfilePlugin.class); when(ConfigBuilderPlugin.getPlugin().getActiveProfileInterface()).thenReturn(profileInterface); //PROFILE LIST (no profile defined) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE LIST"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE LIST", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Not configured", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE LIST", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Not configured", smsCommunicatorPlugin.getMessages().get(1).text); when(profileInterface.getProfile()).thenReturn(AAPSMocker.getValidProfileStore()); //PROFILE STATUS - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE STATUS"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE STATUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals(AAPSMocker.TESTPROFILENAME, smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE STATUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals(AAPSMocker.TESTPROFILENAME, smsCommunicatorPlugin.getMessages().get(1).text); //PROFILE LIST - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE LIST"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE LIST", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("1. " + AAPSMocker.TESTPROFILENAME, smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE LIST", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("1. " + AAPSMocker.TESTPROFILENAME, smsCommunicatorPlugin.getMessages().get(1).text); //PROFILE 2 (non existing) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE 2"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE 2", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE 2", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //PROFILE 1 0(wrong percentage) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE 1 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE 1 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE 1 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //PROFILE 0(wrong index) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("PROFILE 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //PROFILE 1(OK) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE 1"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE 1", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To switch profile to someProfile 100% reply with code")); + Assert.assertEquals("PROFILE 1", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To switch profile to someProfile 100% reply with code")); //PROFILE 1 90(OK) - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "PROFILE 1 90"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("PROFILE 1 90", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To switch profile to someProfile 90% reply with code")); - String passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("PROFILE 1 90", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To switch profile to someProfile 90% reply with code")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Profile switch created", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Profile switch created", smsCommunicatorPlugin.getMessages().get(3).text); } @Test @@ -446,85 +447,85 @@ public class SmsCommunicatorPluginTest { Sms sms; //BASAL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BASAL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.getMessages().get(1).text); when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); //BASAL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BASAL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //BASAL CANCEL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL CANCEL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL CANCEL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To stop temp basal reply with code")); - String passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("BASAL CANCEL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To stop temp basal reply with code")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Temp basal canceled\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(3).text.contains("Temp basal canceled")); //BASAL a% - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL a%"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL a%", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BASAL a%", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //BASAL 10% 0 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL 10% 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL 10% 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BASAL 10% 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); when(MainApp.getConstraintChecker().applyBasalPercentConstraints(any(), any())).thenReturn(new Constraint<>(20)); //BASAL 20% 20 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL 20% 20"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL 20% 20", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To start basal 20% for 20 min reply with code")); - passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("BASAL 20% 20", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To start basal 20% for 20 min reply with code")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Temp basal 20% for 20 min started successfully\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Temp basal 20% for 20 min started successfully\nVirtual Pump", smsCommunicatorPlugin.getMessages().get(3).text); //BASAL a - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL a"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL a", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BASAL a", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //BASAL 1 0 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL 1 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL 1 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BASAL 1 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); when(MainApp.getConstraintChecker().applyBasalConstraints(any(), any())).thenReturn(new Constraint<>(1d)); //BASAL 1 20 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BASAL 1 20"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BASAL 1 20", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To start basal 1.00U/h for 20 min reply with code")); - passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("BASAL 1 20", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To start basal 1.00U/h for 20 min reply with code")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Temp basal 1.00U/h for 20 min started successfully\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Temp basal 1.00U/h for 20 min started successfully\nVirtual Pump", smsCommunicatorPlugin.getMessages().get(3).text); } @@ -533,58 +534,58 @@ public class SmsCommunicatorPluginTest { Sms sms; //EXTENDED - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "EXTENDED"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("EXTENDED", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("EXTENDED", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.getMessages().get(1).text); when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); //EXTENDED - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "EXTENDED"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("EXTENDED", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("EXTENDED", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //EXTENDED CANCEL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "EXTENDED CANCEL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("EXTENDED CANCEL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To stop extended bolus reply with code")); - String passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("EXTENDED CANCEL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To stop extended bolus reply with code")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Extended bolus canceled\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(3).text.contains("Extended bolus canceled")); //EXTENDED a% - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "EXTENDED a%"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("EXTENDED a%", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("EXTENDED a%", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); when(MainApp.getConstraintChecker().applyExtendedBolusConstraints(any())).thenReturn(new Constraint<>(1d)); //EXTENDED 1 0 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "EXTENDED 1 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("EXTENDED 1 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("EXTENDED 1 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //EXTENDED 1 20 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "EXTENDED 1 20"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("EXTENDED 1 20", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To start extended bolus 1.00U for 20 min reply with code")); - passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("EXTENDED 1 20", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To start extended bolus 1.00U for 20 min reply with code")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Extended bolus 1.00U for 20 min started successfully\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Extended bolus 1.00U for 20 min started successfully\nVirtual Pump", smsCommunicatorPlugin.getMessages().get(3).text); } @Test @@ -592,104 +593,91 @@ public class SmsCommunicatorPluginTest { Sms sms; //BOLUS - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BOLUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.getMessages().get(1).text); when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); //BOLUS - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BOLUS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); when(MainApp.getConstraintChecker().applyBolusConstraints(any())).thenReturn(new Constraint<>(1d)); when(DateUtil.now()).thenReturn(1000L); //BOLUS 1 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS 1"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 1", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Remote bolus not available. Try again later.", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BOLUS 1", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote bolus not available. Try again later.", smsCommunicatorPlugin.getMessages().get(1).text); when(MainApp.getConstraintChecker().applyBolusConstraints(any())).thenReturn(new Constraint<>(0d)); when(DateUtil.now()).thenReturn(Constants.remoteBolusMinDistance + 1002L); //BOLUS 0 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BOLUS 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //BOLUS a - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS a"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS a", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BOLUS a", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); when(MainApp.getConstraintChecker().applyExtendedBolusConstraints(any())).thenReturn(new Constraint<>(1d)); when(MainApp.getConstraintChecker().applyBolusConstraints(any())).thenReturn(new Constraint<>(1d)); //BOLUS 1 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS 1"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 1", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To deliver bolus 1.00U reply with code")); - String passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("BOLUS 1", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To deliver bolus 1.00U reply with code")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Bolus 1.00U delivered successfully\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(3).text.contains("Bolus 1.00U delivered successfully")); //BOLUS 1 (Suspended pump) - smsCommunicatorPlugin.lastRemoteBolusTime = 0; - PumpInterface pump = mock(VirtualPumpPlugin.class); - when(ConfigBuilderPlugin.getPlugin().getActivePump()).thenReturn(pump); - when(pump.isSuspended()).thenReturn(true); - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setLastRemoteBolusTime(0); + when(virtualPumpPlugin.isSuspended()).thenReturn(true); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS 1"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 1", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Pump suspended", smsCommunicatorPlugin.messages.get(1).text); - when(pump.isSuspended()).thenReturn(false); + Assert.assertEquals("BOLUS 1", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Pump suspended", smsCommunicatorPlugin.getMessages().get(1).text); + when(virtualPumpPlugin.isSuspended()).thenReturn(false); //BOLUS 1 a - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS 1 a"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 1 a", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("BOLUS 1 a", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //BOLUS 1 MEAL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "BOLUS 1 MEAL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 1 MEAL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To deliver meal bolus 1.00U reply with code")); - passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("BOLUS 1 MEAL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To deliver meal bolus 1.00U reply with code")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Meal Bolus 1.00U delivered successfully\nVirtual Pump", smsCommunicatorPlugin.messages.get(3).text); - - //BOLUS 1 MEAL (Suspended pump) - smsCommunicatorPlugin.lastRemoteBolusTime = 0; - when(ConfigBuilderPlugin.getPlugin().getActivePump()).thenReturn(pump); - when(pump.isSuspended()).thenReturn(true); - smsCommunicatorPlugin.messages = new ArrayList<>(); - sms = new Sms("1234", "BOLUS 1 MEAL"); - smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("BOLUS 1 MEAL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Pump suspended", smsCommunicatorPlugin.messages.get(1).text); - when(pump.isSuspended()).thenReturn(false); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Meal Bolus 1.00U delivered successfully\nVirtual Pump\nTarget 5.0 for 45 minutes", smsCommunicatorPlugin.getMessages().get(3).text); } @Test @@ -697,47 +685,47 @@ public class SmsCommunicatorPluginTest { Sms sms; //CAL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "CAL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("CAL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("CAL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.getMessages().get(1).text); when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); //CAL - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "CAL"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("CAL", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("CAL", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); //CAL 0 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "CAL 0"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("CAL 0", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("Wrong format", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("CAL 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); when(XdripCalibrations.sendIntent(any())).thenReturn(true); //CAL 1 - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); sms = new Sms("1234", "CAL 1"); smsCommunicatorPlugin.processSms(sms); - Assert.assertEquals("CAL 1", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertTrue(smsCommunicatorPlugin.messages.get(1).text.contains("To send calibration 1.00 reply with code")); - String passCode = smsCommunicatorPlugin.messageToConfirm.confirmCode; + Assert.assertEquals("CAL 1", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To send calibration 1.00 reply with code")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); - Assert.assertEquals(passCode, smsCommunicatorPlugin.messages.get(2).text); - Assert.assertEquals("Calibration sent. Receiving must be enabled in xDrip.", smsCommunicatorPlugin.messages.get(3).text); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertEquals("Calibration sent. Receiving must be enabled in xDrip.", smsCommunicatorPlugin.getMessages().get(3).text); } @Test public void sendNotificationToAllNumbers() { - smsCommunicatorPlugin.messages = new ArrayList<>(); + smsCommunicatorPlugin.setMessages(new ArrayList<>()); smsCommunicatorPlugin.sendNotificationToAllNumbers("abc"); - Assert.assertEquals("abc", smsCommunicatorPlugin.messages.get(0).text); - Assert.assertEquals("abc", smsCommunicatorPlugin.messages.get(1).text); + Assert.assertEquals("abc", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("abc", smsCommunicatorPlugin.getMessages().get(1).text); } @Before @@ -826,8 +814,10 @@ public class SmsCommunicatorPluginTest { return null; }).when(AAPSMocker.queue).extendedBolus(anyDouble(), anyInt(), any(Callback.class)); - VirtualPumpPlugin virtualPumpPlugin = VirtualPumpPlugin.getPlugin(); + virtualPumpPlugin = mock(VirtualPumpPlugin.class); when(ConfigBuilderPlugin.getPlugin().getActivePump()).thenReturn(virtualPumpPlugin); + when(virtualPumpPlugin.shortStatus(anyBoolean())).thenReturn("Virtual Pump"); + when(virtualPumpPlugin.isSuspended()).thenReturn(false); } } From a62750c3a32dd5b6692d38fc9a21aa16346af335 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 22 Nov 2019 00:33:13 +0100 Subject: [PATCH 2/3] SmsCommunicatorFragment -> kt --- .../info/nightscout/androidaps/MainApp.java | 2 +- .../activities/PreferencesActivity.java | 2 +- .../automation/actions/ActionSendSMS.java | 2 +- .../SmsCommunicatorFragment.java | 83 ------------------- .../SmsCommunicatorFragment.kt | 70 ++++++++++++++++ .../smsCommunicator/SmsCommunicatorPlugin.kt | 60 ++++++-------- .../queue/commands/CommandSetProfile.java | 2 +- .../androidaps/services/DataService.java | 2 +- .../SmsCommunicatorPluginTest.java | 2 +- 9 files changed, 100 insertions(+), 125 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 379afabddf..0cf275145d 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -204,7 +204,7 @@ public class MainApp extends Application { pluginsList.add(SourcePoctechPlugin.getPlugin()); pluginsList.add(SourceTomatoPlugin.getPlugin()); pluginsList.add(SourceEversensePlugin.getPlugin()); - if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.getPlugin()); + if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.INSTANCE); pluginsList.add(FoodPlugin.getPlugin()); pluginsList.add(WearPlugin.initPlugin(this)); diff --git a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java index f29d2af429..0e93a47151 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/PreferencesActivity.java @@ -184,7 +184,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL); addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL); - addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.getPlugin(), PluginType.GENERAL); + addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.INSTANCE, PluginType.GENERAL); addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL); addPreferencesFromResource(R.xml.pref_others); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java index f8afafca75..6e49287863 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionSendSMS.java @@ -36,7 +36,7 @@ public class ActionSendSMS extends Action { @Override public void doAction(Callback callback) { - boolean result = SmsCommunicatorPlugin.getPlugin().sendNotificationToAllNumbers(text.getValue()); + boolean result = SmsCommunicatorPlugin.INSTANCE.sendNotificationToAllNumbers(text.getValue()); if (callback != null) callback.result(new PumpEnactResult().success(result).comment(result ? R.string.ok : R.string.danar_error)).run(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java deleted file mode 100644 index 7c147a2409..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.java +++ /dev/null @@ -1,83 +0,0 @@ -package info.nightscout.androidaps.plugins.general.smsCommunicator; - - -import android.os.Bundle; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.fragment.app.Fragment; - -import java.util.Collections; -import java.util.Comparator; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.bus.RxBus; -import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.FabricPrivacy; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.CompositeDisposable; - -public class SmsCommunicatorFragment extends Fragment { - private CompositeDisposable disposable = new CompositeDisposable(); - TextView logView; - - public SmsCommunicatorFragment() { - super(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.smscommunicator_fragment, container, false); - - logView = (TextView) view.findViewById(R.id.smscommunicator_log); - - return view; - } - - @Override - public synchronized void onResume() { - super.onResume(); - disposable.add(RxBus.INSTANCE - .toObservable(EventSmsCommunicatorUpdateGui.class) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(event -> updateGui(), FabricPrivacy::logException) - ); - updateGui(); - } - - @Override - public synchronized void onPause() { - super.onPause(); - disposable.clear(); - } - - protected void updateGui() { - class CustomComparator implements Comparator { - public int compare(Sms object1, Sms object2) { - return (int) (object1.date - object2.date); - } - } - Collections.sort(SmsCommunicatorPlugin.getPlugin().getMessages(), new CustomComparator()); - int messagesToShow = 40; - - int start = Math.max(0, SmsCommunicatorPlugin.getPlugin().getMessages().size() - messagesToShow); - - String logText = ""; - for (int x = start; x < SmsCommunicatorPlugin.getPlugin().getMessages().size(); x++) { - Sms sms = SmsCommunicatorPlugin.getPlugin().getMessages().get(x); - if (sms.ignored) { - logText += DateUtil.timeString(sms.date) + " <<< " + "░ " + sms.phoneNumber + " " + sms.text + "
"; - } else if (sms.received) { - logText += DateUtil.timeString(sms.date) + " <<< " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + "
"; - } else if (sms.sent) { - logText += DateUtil.timeString(sms.date) + " >>> " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " " + sms.text + "
"; - } - } - logView.setText(Html.fromHtml(logText)); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt new file mode 100644 index 0000000000..90ec078931 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorFragment.kt @@ -0,0 +1,70 @@ +package info.nightscout.androidaps.plugins.general.smsCommunicator + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus.toObservable +import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HtmlHelper +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.smscommunicator_fragment.* +import java.util.* +import kotlin.math.max + +class SmsCommunicatorFragment : Fragment() { + private val disposable = CompositeDisposable() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.smscommunicator_fragment, container, false) + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable.add(toObservable(EventSmsCommunicatorUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ updateGui() }) { FabricPrivacy.logException(it) } + ) + updateGui() + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + fun updateGui() { + class CustomComparator : Comparator { + override fun compare(object1: Sms, object2: Sms): Int { + return (object1.date - object2.date).toInt() + } + } + Collections.sort(SmsCommunicatorPlugin.messages, CustomComparator()) + val messagesToShow = 40 + val start = max(0, SmsCommunicatorPlugin.messages.size - messagesToShow) + var logText = "" + for (x in start until SmsCommunicatorPlugin.messages.size) { + val sms = SmsCommunicatorPlugin.messages[x] + when { + sms.ignored -> { + logText += DateUtil.timeString(sms.date) + " <<< " + "░ " + sms.phoneNumber + " " + sms.text + "
" + } + sms.received -> { + logText += DateUtil.timeString(sms.date) + " <<< " + (if (sms.processed) "● " else "○ ") + sms.phoneNumber + " " + sms.text + "
" + } + sms.sent -> { + logText += DateUtil.timeString(sms.date) + " >>> " + (if (sms.processed) "● " else "○ ") + sms.phoneNumber + " " + sms.text + "
" + } + } + } + smscommunicator_log?.text = HtmlHelper.fromHtml(logText) + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt index 037f17d0bb..9361216aa0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -49,7 +49,7 @@ import java.util.* /** * Created by mike on 05.08.2016. */ -class SmsCommunicatorPlugin internal constructor() : PluginBase(PluginDescription() +object SmsCommunicatorPlugin : PluginBase(PluginDescription() .mainType(PluginType.GENERAL) .fragmentClass(SmsCommunicatorFragment::class.java.name) .pluginName(R.string.smscommunicator) @@ -57,12 +57,17 @@ class SmsCommunicatorPlugin internal constructor() : PluginBase(PluginDescriptio .preferencesId(R.xml.pref_smscommunicator) .description(R.string.description_sms_communicator) ) { + private val log = LoggerFactory.getLogger(L.SMS) private val disposable = CompositeDisposable() var allowedNumbers: MutableList = ArrayList() var messageToConfirm: AuthRequest? = null var lastRemoteBolusTime: Long = 0 var messages = ArrayList() + init { + processSettings(null) + } + override fun onStart() { super.onStart() disposable.add(toObservable(EventPreferenceChange::class.java) @@ -772,41 +777,24 @@ class SmsCommunicatorPlugin internal constructor() : PluginBase(PluginDescriptio return passCode } - companion object { - private val log = LoggerFactory.getLogger(L.SMS) - private var smsCommunicatorPlugin: SmsCommunicatorPlugin? = null - @JvmStatic - val plugin: SmsCommunicatorPlugin? - get() { - if (smsCommunicatorPlugin == null) { - smsCommunicatorPlugin = SmsCommunicatorPlugin() - } - return smsCommunicatorPlugin - } - - private fun stripAccents(str: String): String { - var s = str - s = Normalizer.normalize(s, Normalizer.Form.NFD) - s = s.replace("[\\p{InCombiningDiacriticalMarks}]".toRegex(), "") - return s - } - - fun areMoreNumbers(allowednumbers: String): Boolean { - var countNumbers = 0 - val substrings = allowednumbers.split(";").toTypedArray() - for (number in substrings) { - var cleaned = number.replace(Regex("\\s+"), "") - if (cleaned.length < 4) continue - if (cleaned.substring(0, 1).compareTo("+") != 0) continue - cleaned = cleaned.replace("+", "") - if (!cleaned.matches(Regex("[0-9]+"))) continue - countNumbers++ - } - return countNumbers > 1 - } + private fun stripAccents(str: String): String { + var s = str + s = Normalizer.normalize(s, Normalizer.Form.NFD) + s = s.replace("[\\p{InCombiningDiacriticalMarks}]".toRegex(), "") + return s } - init { - processSettings(null) + fun areMoreNumbers(allowednumbers: String): Boolean { + var countNumbers = 0 + val substrings = allowednumbers.split(";").toTypedArray() + for (number in substrings) { + var cleaned = number.replace(Regex("\\s+"), "") + if (cleaned.length < 4) continue + if (cleaned.substring(0, 1).compareTo("+") != 0) continue + cleaned = cleaned.replace("+", "") + if (!cleaned.matches(Regex("[0-9]+"))) continue + countNumbers++ + } + return countNumbers > 1 } -} \ No newline at end of file + } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java index 62e14285eb..b69f3f4dc7 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.java @@ -50,7 +50,7 @@ public class CommandSetProfile extends Command { // Send SMS notification if ProfileSwitch is comming from NS ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis()); if (profileSwitch != null && r.enacted && profileSwitch.source == Source.NIGHTSCOUT) { - SmsCommunicatorPlugin smsCommunicatorPlugin = SmsCommunicatorPlugin.getPlugin(); + SmsCommunicatorPlugin smsCommunicatorPlugin = SmsCommunicatorPlugin.INSTANCE; if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) { smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.gs(R.string.profile_set_ok)); } diff --git a/app/src/main/java/info/nightscout/androidaps/services/DataService.java b/app/src/main/java/info/nightscout/androidaps/services/DataService.java index 80a42e145a..44050ece35 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/services/DataService.java @@ -103,7 +103,7 @@ public class DataService extends IntentService { ) { handleNewDataFromNSClient(intent); } else if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action)) { - SmsCommunicatorPlugin.getPlugin().handleNewData(intent); + SmsCommunicatorPlugin.INSTANCE.handleNewData(intent); } if (L.isEnabled(L.DATASERVICE)) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java index 77324d9627..606bde7c80 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java @@ -758,7 +758,7 @@ public class SmsCommunicatorPluginTest { when(SmsManager.getDefault()).thenReturn(smsManager); when(SP.getString(R.string.key_smscommunicator_allowednumbers, "")).thenReturn("1234;5678"); - smsCommunicatorPlugin = SmsCommunicatorPlugin.getPlugin(); + smsCommunicatorPlugin = SmsCommunicatorPlugin.INSTANCE; smsCommunicatorPlugin.setPluginEnabled(PluginType.GENERAL, true); mockStatic(LoopPlugin.class); From e9aa4835edee209265c5b6d0b2388ca9ab141eae Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 22 Nov 2019 10:40:48 +0100 Subject: [PATCH 3/3] SBS CARBS command --- .../general/smsCommunicator/SmsAction.java | 5 + .../smsCommunicator/SmsCommunicatorPlugin.kt | 122 +++++++++++++----- .../nightscout/androidaps/utils/DateUtil.java | 6 +- app/src/main/res/values/strings.xml | 3 + app/src/test/java/info/AAPSMocker.java | 4 + .../smsCommunicator/AuthRequestTest.java | 13 +- .../SmsCommunicatorPluginTest.java | 84 +++++++++++- 7 files changed, 198 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsAction.java index 6b5d5b8747..7785b33c7c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsAction.java @@ -4,6 +4,7 @@ abstract class SmsAction implements Runnable { Double aDouble; Integer anInteger; Integer secondInteger; + Long secondLong; String aString; SmsAction() {} @@ -30,4 +31,8 @@ abstract class SmsAction implements Runnable { this.anInteger = anInteger; this.secondInteger = secondInteger; } + SmsAction(Integer anInteger, Long secondLong) { + this.anInteger = anInteger; + this.secondLong = secondLong; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt index 9361216aa0..e1df17fd82 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPlugin.kt @@ -136,7 +136,7 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() fun isCommand(command: String, number: String): Boolean { when (command.toUpperCase(Locale.getDefault())) { - "BG", "LOOP", "TREATMENTS", "NSCLIENT", "PUMP", "BASAL", "BOLUS", "EXTENDED", "CAL", "PROFILE", "TARGET", "SMS" -> return true + "BG", "LOOP", "TREATMENTS", "NSCLIENT", "PUMP", "BASAL", "BOLUS", "EXTENDED", "CAL", "PROFILE", "TARGET", "SMS", "CARBS" -> return true } return messageToConfirm?.requester?.phoneNumber == number } @@ -208,7 +208,12 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) else if (splitted.size == 2 && DateUtil.now() - lastRemoteBolusTime < Constants.remoteBolusMinDistance) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotebolusnotallowed)) else if (splitted.size == 2 && pump.isSuspended) sendSMS(Sms(receivedSms.phoneNumber, R.string.pumpsuspended)) - else if (splitted.size == 2 || splitted.size == 3) processBOLUS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else if (splitted.size == 2 || splitted.size == 3) processBOLUS(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + "CARBS" -> + if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) + else if (splitted.size == 2 || splitted.size == 3) processCARBS(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) "CAL" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) else if (splitted.size == 2) processCAL(splitted, receivedSms) @@ -219,7 +224,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) "SMS" -> if (!remoteCommandsAllowed) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_remotecommandnotallowed)) - else if (splitted.size == 2) processSMS(splitted, receivedSms) else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else if (splitted.size == 2) processSMS(splitted, receivedSms) + else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else -> if (messageToConfirm?.requester?.phoneNumber == receivedSms.phoneNumber) { messageToConfirm?.action(splitted[0]) @@ -271,9 +277,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() sendSMS(Sms(receivedSms.phoneNumber, replyText)) } }) - } else { + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisdisabled)) - } receivedSms.processed = true } "ENABLE", "START" -> { @@ -282,18 +287,17 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() loopPlugin.setPluginEnabled(PluginType.LOOP, true) sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loophasbeenenabled)) send(EventRefreshOverview("SMS_LOOP_START")) - } else { + } else sendSMS(Sms(receivedSms.phoneNumber, R.string.smscommunicator_loopisenabled)) - } receivedSms.processed = true } "STATUS" -> { val loopPlugin = LoopPlugin.getPlugin() val reply = if (loopPlugin.isEnabled(PluginType.LOOP)) { - if (loopPlugin.isSuspended()) String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) else MainApp.gs(R.string.smscommunicator_loopisenabled) - } else { + if (loopPlugin.isSuspended()) String.format(MainApp.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) + else MainApp.gs(R.string.smscommunicator_loopisenabled) + } else MainApp.gs(R.string.smscommunicator_loopisdisabled) - } sendSMS(Sms(receivedSms.phoneNumber, reply)) receivedSms.processed = true } @@ -348,7 +352,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() send(EventNSClientRestart()) sendSMS(Sms(receivedSms.phoneNumber, "TREATMENTS REFRESH SENT")) receivedSms.processed = true - } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } else + sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) } private fun processNSCLIENT(splitted: Array, receivedSms: Sms) { @@ -356,7 +361,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() send(EventNSClientRestart()) sendSMS(Sms(receivedSms.phoneNumber, "NSCLIENT RESTART SENT")) receivedSms.processed = true - } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + } else + sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) } private fun processPUMP(receivedSms: Sms) { @@ -394,7 +400,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() if (splitted[1].toUpperCase(Locale.getDefault()) == "STATUS") { sendSMS(Sms(receivedSms.phoneNumber, ProfileFunctions.getInstance().profileName)) } else if (splitted[1].toUpperCase(Locale.getDefault()) == "LIST") { - if (list.isEmpty()) sendSMS(Sms(receivedSms.phoneNumber, R.string.invalidprofile)) else { + if (list.isEmpty()) sendSMS(Sms(receivedSms.phoneNumber, R.string.invalidprofile)) + else { var reply = "" for (i in list.indices) { if (i > 0) reply += "\n" @@ -407,9 +414,13 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() val pindex = SafeParse.stringToInt(splitted[1]) var percentage = 100 if (splitted.size > 2) percentage = SafeParse.stringToInt(splitted[2]) - if (pindex > list.size) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (percentage == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (pindex == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + if (pindex > list.size) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else if (percentage == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else if (pindex == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else { val profile = store.getSpecificProfile(list[pindex - 1] as String) - if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) else { + if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) + else { val passCode = generatePasscode() val reply = String.format(MainApp.gs(R.string.smscommunicator_profilereplywithcode), list[pindex - 1], percentage, passCode) receivedSms.processed = true @@ -453,7 +464,10 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() var duration = 30 if (splitted.size > 2) duration = SafeParse.stringToInt(splitted[2]) val profile = ProfileFunctions.getInstance().profile - if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) else if (tempBasalPct == 0 && splitted[1] != "0%") sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) + else if (tempBasalPct == 0 && splitted[1] != "0%") sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else if (duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else { tempBasalPct = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value() val passCode = generatePasscode() val reply = String.format(MainApp.gs(R.string.smscommunicator_basalpctreplywithcode), tempBasalPct, duration, passCode) @@ -482,7 +496,10 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() var duration = 30 if (splitted.size > 2) duration = SafeParse.stringToInt(splitted[2]) val profile = ProfileFunctions.getInstance().profile - if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) else if (tempBasal == 0.0 && splitted[1] != "0") sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else if (duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, R.string.noprofile)) + else if (tempBasal == 0.0 && splitted[1] != "0") sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else if (duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else { tempBasal = MainApp.getConstraintChecker().applyBasalConstraints(Constraint(tempBasal), profile).value() val passCode = generatePasscode() val reply = String.format(MainApp.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, duration, passCode) @@ -492,7 +509,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(aDouble, secondInteger, true, profile, object : Callback() { override fun run() { if (result.success) { - var replyText = if (result.isPercent) String.format(MainApp.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) + var replyText = if (result.isPercent) String.format(MainApp.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) + else String.format(MainApp.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration) replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) } else { @@ -536,7 +554,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() var extended = SafeParse.stringToDouble(splitted[1]) val duration = SafeParse.stringToInt(splitted[2]) extended = MainApp.getConstraintChecker().applyExtendedBolusConstraints(Constraint(extended)).value() - if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) else { + if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else { val passCode = generatePasscode() val reply = String.format(MainApp.gs(R.string.smscommunicator_extendedreplywithcode), extended, duration, passCode) receivedSms.processed = true @@ -569,11 +588,10 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) } else if (bolus > 0.0) { val passCode = generatePasscode() - val reply = if (isMeal) { + val reply = if (isMeal) String.format(MainApp.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode) - } else { + else String.format(MainApp.gs(R.string.smscommunicator_bolusreplywithcode), bolus, passCode) - } receivedSms.processed = true messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(bolus) { override fun run() { @@ -587,19 +605,23 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("SMS", object : Callback() { override fun run() { if (resultSuccess) { - var replyText = if (isMeal) { + var replyText = if (isMeal) String.format(MainApp.gs(R.string.smscommunicator_mealbolusdelivered), resultBolusDelivered) - } else { + else String.format(MainApp.gs(R.string.smscommunicator_bolusdelivered), resultBolusDelivered) - } replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) lastRemoteBolusTime = DateUtil.now() if (isMeal) { ProfileFunctions.getInstance().profile?.let { currentProfile -> var eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration) - eatingSoonTTDuration = if (eatingSoonTTDuration > 0) eatingSoonTTDuration else Constants.defaultEatingSoonTTDuration + eatingSoonTTDuration = + if (eatingSoonTTDuration > 0) eatingSoonTTDuration + else Constants.defaultEatingSoonTTDuration var eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl) - eatingSoonTT = if (eatingSoonTT > 0) eatingSoonTT else if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol else Constants.defaultEatingSoonTTmgdl + eatingSoonTT = + if (eatingSoonTT > 0) eatingSoonTT + else if (currentProfile.units == Constants.MMOL) Constants.defaultEatingSoonTTmmol + else Constants.defaultEatingSoonTTmgdl val tempTarget = TempTarget() .date(System.currentTimeMillis()) .duration(eatingSoonTTDuration) @@ -629,6 +651,47 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() } else sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) } + private fun processCARBS(splitted: Array, receivedSms: Sms) { + var grams = SafeParse.stringToInt(splitted[1]) + var time = DateUtil.now() + if (splitted.size > 2) { + val seconds = DateUtil.toSeconds(splitted[2].toUpperCase(Locale.getDefault())) + val midnight = MidnightTime.calc() + if (seconds == 0 && (!splitted[2].startsWith("00:00") || !splitted[2].startsWith("12:00"))) { + sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + return + } + time = midnight + T.secs(seconds.toLong()).msecs() + } + grams = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(grams)).value() + if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, R.string.wrongformat)) + else { + val passCode = generatePasscode() + val reply = String.format(MainApp.gs(R.string.smscommunicator_carbsreplywithcode), grams, DateUtil.timeString(time), passCode) + receivedSms.processed = true + messageToConfirm = AuthRequest(this, receivedSms, reply, passCode, object : SmsAction(grams, time) { + override fun run() { + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.carbs = anInteger.toDouble() + detailedBolusInfo.date = secondLong + ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + if (result.success) { + var replyText = String.format(MainApp.gs(R.string.smscommunicator_carbsset), anInteger) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText)) + } else { + var replyText = MainApp.gs(R.string.smscommunicator_carbsfailed) + replyText += "\n" + ConfigBuilderPlugin.getPlugin().activePump?.shortStatus(true) + sendSMS(Sms(receivedSms.phoneNumber, replyText)) + } + } + }) + } + }) + } + } + private fun processTARGET(splitted: Array, receivedSms: Sms) { val isMeal = splitted[1].equals("MEAL", ignoreCase = true) val isActivity = splitted[1].equals("ACTIVITY", ignoreCase = true) @@ -741,7 +804,8 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() sms.text = stripAccents(sms.text) try { if (L.isEnabled(L.SMS)) log.debug("Sending SMS to " + sms.phoneNumber + ": " + sms.text) - if (sms.text.toByteArray().size <= 140) smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null) else { + if (sms.text.toByteArray().size <= 140) smsManager.sendTextMessage(sms.phoneNumber, null, sms.text, null, null) + else { val parts = smsManager.divideMessage(sms.text) smsManager.sendMultipartTextMessage(sms.phoneNumber, null, parts, null, null) @@ -797,4 +861,4 @@ object SmsCommunicatorPlugin : PluginBase(PluginDescription() } return countNumbers > 1 } - } \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java b/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java index d592347d1b..4ac49d745b 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/DateUtil.java @@ -93,15 +93,15 @@ public class DateUtil { } public static int toSeconds(String hh_colon_mm) { - Pattern p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM | PM|)"); + Pattern p = Pattern.compile("(\\d+):(\\d+)( a.m.| p.m.| AM| PM|AM|PM|)"); Matcher m = p.matcher(hh_colon_mm); int retval = 0; if (m.find()) { retval = SafeParse.stringToInt(m.group(1)) * 60 * 60 + SafeParse.stringToInt(m.group(2)) * 60; - if ((m.group(3).equals(" a.m.") || m.group(3).equals(" AM")) && m.group(1).equals("12")) + if ((m.group(3).equals(" a.m.") || m.group(3).equals(" AM") || m.group(3).equals("AM")) && m.group(1).equals("12")) retval -= 12 * 60 * 60; - if ((m.group(3).equals(" p.m.") || m.group(3).equals(" PM")) && !(m.group(1).equals("12"))) + if ((m.group(3).equals(" p.m.") || m.group(3).equals(" PM") || m.group(3).equals("PM")) && !(m.group(1).equals("12"))) retval += 12 * 60 * 60; } return retval; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2fba2a59fe..e0b9170631 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -367,10 +367,13 @@ To start basal %1$.2fU/h for %2$d min reply with code %3$s To switch profile to %1$s %2$d%% reply with code %3$s To start extended bolus %1$.2fU for %2$d min reply with code %3$s + To enter %1$dg at %2$s reply with code %3$s To start basal %1$d%% for %2$d min reply with code %3$s To suspend loop for %1$d minutes reply with code %2$s Temp basal %1$.2fU/h for %2$d min started successfully Extended bolus %1$.2fU for %2$d min started successfully + Carbs %1$dg entered successfully + Entering %1$dg of carbs failed Temp basal %1$d%% for %2$d min started successfully Temp basal start failed Extended bolus start failed diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java index bd01e6b89b..510ff09c2b 100644 --- a/app/src/test/java/info/AAPSMocker.java +++ b/app/src/test/java/info/AAPSMocker.java @@ -37,6 +37,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -158,6 +159,8 @@ public class AAPSMocker { when(MainApp.gs(R.string.smscommunicator_mealbolusreplywithcode)).thenReturn("To deliver meal bolus %1$.2fU reply with code %2$s"); when(MainApp.gs(R.string.smscommunicator_mealbolusdelivered)).thenReturn("Meal Bolus %1$.2fU delivered successfully"); when(MainApp.gs(R.string.smscommunicator_mealbolusdelivered_tt)).thenReturn("Target %1$s for %2$d minutes"); + when(MainApp.gs(R.string.smscommunicator_carbsreplywithcode)).thenReturn("To enter %1$dg at %2$s reply with code %3$s"); + when(MainApp.gs(R.string.smscommunicator_carbsset)).thenReturn("Carbs %1$dg entered successfully"); } public static MainApp mockMainApp() { @@ -186,6 +189,7 @@ public class AAPSMocker { when(SP.getLong(anyInt(), anyLong())).thenReturn(0L); when(SP.getBoolean(anyInt(), anyBoolean())).thenReturn(false); when(SP.getInt(anyInt(), anyInt())).thenReturn(0); + when(SP.getString(anyInt(), anyString())).thenReturn(""); } public static void mockL() { diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java index 7b53e214a8..5bd3cae874 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/AuthRequestTest.java @@ -75,12 +75,6 @@ public class AuthRequestTest { @Before public void prepareTests() { - smsCommunicatorPlugin = mock(SmsCommunicatorPlugin.class); - doAnswer((Answer) invocation -> { - sentSms = invocation.getArgument(0); - return null; - }).when(smsCommunicatorPlugin).sendSMS(any(Sms.class)); - AAPSMocker.mockMainApp(); AAPSMocker.mockApplicationContext(); AAPSMocker.mockSP(); @@ -88,5 +82,12 @@ public class AuthRequestTest { AAPSMocker.mockStrings(); mockStatic(DateUtil.class); + + smsCommunicatorPlugin = mock(SmsCommunicatorPlugin.class); + doAnswer((Answer) invocation -> { + sentSms = invocation.getArgument(0); + return null; + }).when(smsCommunicatorPlugin).sendSMS(any(Sms.class)); + } } diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java index 606bde7c80..76d8e5dda3 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/smsCommunicator/SmsCommunicatorPluginTest.java @@ -49,6 +49,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.powermock.api.mockito.PowerMockito.doAnswer; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.spy; import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) @@ -720,6 +721,87 @@ public class SmsCommunicatorPluginTest { Assert.assertEquals("Calibration sent. Receiving must be enabled in xDrip.", smsCommunicatorPlugin.getMessages().get(3).text); } + @Test + public void processCarbsTest() { + Sms sms; + + when(DateUtil.now()).thenReturn(1000000L); + when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(false); + //CAL + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Remote command is not allowed", smsCommunicatorPlugin.getMessages().get(1).text); + + when(SP.getBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)).thenReturn(true); + + //CARBS + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); + + when(MainApp.getConstraintChecker().applyCarbsConstraints(any())).thenReturn(new Constraint<>(0)); + + //CARBS 0 + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS 0"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS 0", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertEquals("Wrong format", smsCommunicatorPlugin.getMessages().get(1).text); + + when(MainApp.getConstraintChecker().applyCarbsConstraints(any())).thenReturn(new Constraint<>(1)); + + //CARBS 1 + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS 1"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS 1", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To enter 1g at 01:16AM reply with code")); + String passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; + smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(3).text.startsWith("Carbs 1g entered successfully")); + + //CARBS 1 a + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS 1 a"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS 1 a", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("Wrong format")); + + //CARBS 1 00 + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS 1 00"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS 1 00", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("Wrong format")); + + //CARBS 1 12:01 + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS 1 12:01"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS 1 12:01", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To enter 1g at 12:01PM reply with code")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; + smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(3).text.startsWith("Carbs 1g entered successfully")); + + //CARBS 1 3:01AM + smsCommunicatorPlugin.setMessages(new ArrayList<>()); + sms = new Sms("1234", "CARBS 1 3:01AM"); + smsCommunicatorPlugin.processSms(sms); + Assert.assertEquals("CARBS 1 3:01AM", smsCommunicatorPlugin.getMessages().get(0).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(1).text.contains("To enter 1g at 03:01AM reply with code")); + passCode = smsCommunicatorPlugin.getMessageToConfirm().confirmCode; + smsCommunicatorPlugin.processSms(new Sms("1234", passCode)); + Assert.assertEquals(passCode, smsCommunicatorPlugin.getMessages().get(2).text); + Assert.assertTrue(smsCommunicatorPlugin.getMessages().get(3).text.startsWith("Carbs 1g entered successfully")); + } + @Test public void sendNotificationToAllNumbers() { smsCommunicatorPlugin.setMessages(new ArrayList<>()); @@ -752,7 +834,7 @@ public class SmsCommunicatorPluginTest { PowerMockito.when(IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "SMS COB")).thenReturn(new CobInfo(10d, 2d)); mockStatic(XdripCalibrations.class); - mockStatic(DateUtil.class); + spy(DateUtil.class); mockStatic(SmsManager.class); SmsManager smsManager = mock(SmsManager.class); when(SmsManager.getDefault()).thenReturn(smsManager);