diff --git a/.idea/misc.xml b/.idea/misc.xml index fbb68289f4..5d19981032 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java index e7512db331..1a8e66125b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java @@ -39,6 +39,8 @@ public class SmsCommunicatorPlugin implements PluginBase { private static boolean fragmentEnabled = false; private static boolean fragmentVisible = true; + final long CONFIRM_TIMEOUT = 5 * 60 * 1000L; + public class Sms { String phoneNumber; String text; @@ -49,6 +51,7 @@ public class SmsCommunicatorPlugin implements PluginBase { String confirmCode; double bolusRequested = 0d; + double tempBasal = 0d; public Sms(SmsMessage message) { phoneNumber = message.getOriginatingAddress(); @@ -69,6 +72,8 @@ public class SmsCommunicatorPlugin implements PluginBase { } } + Sms cancelTempBasalWaitingForConfirmation = null; + Sms tempBasalWaitingForConfirmation = null; Sms bolusWaitingForConfirmation = null; Date lastRemoteBolusTime = new Date(0); @@ -148,8 +153,10 @@ public class SmsCommunicatorPlugin implements PluginBase { log.debug(receivedSms.toString()); String[] splited = receivedSms.text.split("\\s+"); - double amount = 0d; + Double amount = 0d; + Double tempBasal = 0d; String passCode = ""; + Sms newSms = null; if (splited.length > 0) { switch (splited[0].toUpperCase()) { @@ -201,7 +208,7 @@ public class SmsCommunicatorPlugin implements PluginBase { case "RESTART": Intent restartNSClient = new Intent(Intents.ACTION_RESTART); MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient); - Listq = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); + List q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0); reply = "NSCLIENT RESTART " + q.size() + " receivers"; receivedSms.processed = true; break; @@ -213,66 +220,147 @@ public class SmsCommunicatorPlugin implements PluginBase { reply = danaRPlugin.shortStatus(); receivedSms.processed = true; break; + case "BASAL": + if (splited.length > 1) { + boolean remoteCommandsAllowed = sharedPreferences.getBoolean("smscommunicator_remotecommandsallowed", false); + if (splited[1].toUpperCase().equals("CANCEL") || splited[1].toUpperCase().equals("STOP")) { + if (remoteCommandsAllowed) { + passCode = generatePasscode(); + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_basalstopreplywithcode), passCode); + receivedSms.processed = true; + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + newSms.confirmCode = passCode; + resetWaitingMessages(); + cancelTempBasalWaitingForConfirmation = newSms; + } else { + reply = MainApp.sResources.getString(R.string.remotebasalnotallowed); + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + } + } else { + tempBasal = SafeParse.stringToDouble(splited[1]); + tempBasal = MainApp.getConfigBuilder().applyBasalConstraints(tempBasal); + if (remoteCommandsAllowed) { + passCode = generatePasscode(); + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_basalreplywithcode), tempBasal, passCode); + receivedSms.processed = true; + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + newSms.tempBasal = tempBasal; + newSms.confirmCode = passCode; + resetWaitingMessages(); + tempBasalWaitingForConfirmation = newSms; + } else { + reply = MainApp.sResources.getString(R.string.remotebasalnotallowed); + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + } + } + } + break; case "BOLUS": if (new Date().getTime() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) { reply = MainApp.sResources.getString(R.string.remotebolusnotallowed); } else if (splited.length > 1) { amount = SafeParse.stringToDouble(splited[1]); amount = MainApp.getConfigBuilder().applyBolusConstraints(amount); - boolean remoteBolusingAllowed = sharedPreferences.getBoolean("smscommunicator_remotebolusingallowed", false); - if (amount > 0d && remoteBolusingAllowed) { - int startChar1 = 'A'; // on iphone 1st char is uppercase :) - 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))); - reply = String.format(MainApp.sResources.getString(R.string.replywithcode), amount, passCode); + boolean remoteCommandsAllowed = sharedPreferences.getBoolean("smscommunicator_remotecommandsallowed", false); + if (amount > 0d && remoteCommandsAllowed) { + passCode = generatePasscode(); + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusreplywithcode), amount, passCode); receivedSms.processed = true; + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + newSms.bolusRequested = amount; + newSms.confirmCode = passCode; + resetWaitingMessages(); + bolusWaitingForConfirmation = newSms; } else { reply = MainApp.sResources.getString(R.string.remotebolusnotallowed); + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); } } break; default: // expect passCode here if (bolusWaitingForConfirmation != null && !bolusWaitingForConfirmation.processed && - bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - bolusWaitingForConfirmation.date.getTime() < 5 * 60 * 1000L) { + bolusWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - bolusWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { bolusWaitingForConfirmation.processed = true; PumpInterface pumpInterface = MainApp.getConfigBuilder(); if (pumpInterface != null) { danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); PumpEnactResult result = pumpInterface.deliverTreatment(bolusWaitingForConfirmation.bolusRequested, 0, null); if (result.success) { - reply = String.format(MainApp.sResources.getString(R.string.bolusdelivered), bolusWaitingForConfirmation.bolusRequested); + reply = String.format(MainApp.sResources.getString(R.string.bolusdelivered), result.bolusDelivered); if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(); lastRemoteBolusTime = new Date(); } else { reply = MainApp.sResources.getString(R.string.bolusfailed); if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(); } + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); } + } else if (tempBasalWaitingForConfirmation != null && !tempBasalWaitingForConfirmation.processed && + tempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - tempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + tempBasalWaitingForConfirmation.processed = true; + PumpInterface pumpInterface = MainApp.getConfigBuilder(); + if (pumpInterface != null) { + danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); + PumpEnactResult result = pumpInterface.setTempBasalAbsolute(tempBasalWaitingForConfirmation.tempBasal, 30); + if (result.success) { + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalset), result.absolute, result.duration); + if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalfailed); + if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(); + } + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + } + } else if (cancelTempBasalWaitingForConfirmation != null && !cancelTempBasalWaitingForConfirmation.processed && + cancelTempBasalWaitingForConfirmation.confirmCode.equals(splited[0]) && new Date().getTime() - cancelTempBasalWaitingForConfirmation.date.getTime() < CONFIRM_TIMEOUT) { + cancelTempBasalWaitingForConfirmation.processed = true; + PumpInterface pumpInterface = MainApp.getConfigBuilder(); + if (pumpInterface != null) { + danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class); + PumpEnactResult result = pumpInterface.cancelTempBasal(); + if (result.success) { + reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_tempbasalcanceled)); + if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(); + } else { + reply = MainApp.sResources.getString(R.string.smscommunicator_tempbasalcancelfailed); + if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus(); + } + newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); + } + } else { + newSms = new Sms(receivedSms.phoneNumber, MainApp.sResources.getString(R.string.smscommunicator_unknowncommand), new Date()); } + resetWaitingMessages(); break; } } - if (!reply.equals("")) { + if (newSms != null) { SmsManager smsManager = SmsManager.getDefault(); - Sms newSms = new Sms(receivedSms.phoneNumber, reply, new Date()); - if (amount > 0d) { - newSms.bolusRequested = amount; - newSms.confirmCode = passCode; - bolusWaitingForConfirmation = newSms; - } else { - bolusWaitingForConfirmation = null; - newSms.processed = true; - } - smsManager.sendTextMessage(newSms.phoneNumber, null, stripAccents(newSms.text), null, null); + newSms.text = stripAccents(newSms.text); + if (newSms.text.length() > 140) newSms.text = newSms.text.substring(0, 139); + smsManager.sendTextMessage(newSms.phoneNumber, null, newSms.text, null, null); messages.add(newSms); } MainApp.bus().post(new EventSmsCommunicatorUpdateGui()); } + 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))); + return passCode; + } + + private void resetWaitingMessages() { + tempBasalWaitingForConfirmation = null; + cancelTempBasalWaitingForConfirmation = null; + bolusWaitingForConfirmation = null; + } + public static String stripAccents(String s) { s = Normalizer.normalize(s, Normalizer.Form.NFD); s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index e18582eabe..7dbaaba137 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -227,9 +227,8 @@ Изчаква резултат SMS комуникатор Позволени телефонни номера - Разреши болус чрез SMS Успех - За да доставите болус %.2fU отговорете с код %s + За да доставите болус %.2fU отговорете с код %s Отдалечен болус не е разрешен Обнови профила Процент diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 7472ce357b..3b7058563d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -236,11 +236,11 @@ Bolus %.2fU aplikován úspěšně Chyba při aplikování bolusu Vzdálený bolus není momentálně povolen - K potvzení bolusu %.2fU odpověz SMS s kódem %s + K potvzení bolusu %.2fU odpověz SMS s kódem %s SMS komunikátor Povolená tel. čísla +XXXXXXXXXX;+YYYYYYYYYY - Povolit posílání bolusu přes SMS + Povolit posílání příkazů přes SMS Čekání na výsledek Dočasný cíl Dočasný cíl konec @@ -306,4 +306,15 @@ Smyčka byla povolena Smyčka je zakázána Smyčka je povolena + Español + Není vybrán žádný profil + Hodnota %s je mimo přednastavený rozsah + Vzdálené posílání příkazů není povoleno + Na spuštění bazálu %.2fU/h odpověz SMS s kódem %s + Na ukončení bazálu odpověz SMS s kódem %s + Dočaný bazál zastaven + Rušení dočasného bazálu selhalo + Spuštění dočasného bazálu selhalo + Dočasný bazál %.2fU/h na %d minut spuštěn + Neznámý příkaz nebo chybná odpověď \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b05751b0c3..06b6362f3e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -246,10 +246,9 @@ vor h SMS Kommunikator erlaubte TElefonnummern - Fernboli via SMS zulassen Nightscout Profil zur Pumpe synchronisieren auf Pumpenergebnis warten Kein Bluetoothadapter gefunden Remote Bolus nicht erlaubt - Um Bolus %.2fU bitte mit %s antworten + Um Bolus %.2fU bitte mit %s antworten diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9e122e7cd1..6218d8c98a 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -240,11 +240,10 @@ Esperando resultado Números de teléfono permitidos XXXXXXXXXX +; + YYYYYYYYYY - Para entregar bolo% .2fU responder con código% s + Para entregar bolo% .2fU responder con código% s bolo falló Bolo% .2fU entregado con éxito Entregando% .2fU - Permitir bolos remotos por SMS Bolo remoto no permitido Dedo Sensor diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a5a468ffff..7b4d4bbc2f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -241,11 +241,11 @@ Waiting for result Allowed phone numbers +XXXXXXXXXX;+YYYYYYYYYY - To deliver bolus %.2fU reply with code %s + To deliver bolus %.2fU reply with code %s Bolus failed Bolus %.2fU delivered successfully Delivering %.2fU - Allow remote bolusing via SMS + Allow remote commands via SMS Remote bolus not allowed Finger Sensor @@ -311,5 +311,13 @@ Loop is disabled Loop is enabled Value %s is out of hard limits + Remote basal setting is not allowed + To start basal %.2fU/h reply with code %s + Temp basal %.2fU/h for %d min started successfully + Temp basal start failed + To stop temp basal reply with code %s + Temp basal canceled + Canceling temp basal failed + Uknonwn command or wrong reply diff --git a/app/src/main/res/xml/pref_smscommunicator.xml b/app/src/main/res/xml/pref_smscommunicator.xml index f4c6b75043..23816e8e29 100644 --- a/app/src/main/res/xml/pref_smscommunicator.xml +++ b/app/src/main/res/xml/pref_smscommunicator.xml @@ -12,8 +12,8 @@ + android:key="smscommunicator_remotecommandsallowed" + android:title="@string/smscommunicator_remotecommandsallowed" />