sms communicator: remote bolus, status
This commit is contained in:
parent
2ca75b52e5
commit
90fee59e8a
13 changed files with 359 additions and 9 deletions
|
@ -37,7 +37,7 @@
|
||||||
<ConfirmationsSetting value="0" id="Add" />
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
|
@ -65,6 +65,16 @@
|
||||||
<!-- Receiver keepalive, scheduled every 30 min -->
|
<!-- Receiver keepalive, scheduled every 30 min -->
|
||||||
<receiver android:name=".receivers.KeepAliveReceiver" />
|
<receiver android:name=".receivers.KeepAliveReceiver" />
|
||||||
|
|
||||||
|
<!-- Receive new SMS messages -->
|
||||||
|
<receiver
|
||||||
|
android:name=".plugins.SmsCommunicator.Receivers.SmsReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<!-- Service processing incomming data -->
|
<!-- Service processing incomming data -->
|
||||||
<service
|
<service
|
||||||
android:name=".Services.DataService"
|
android:name=".Services.DataService"
|
||||||
|
@ -83,7 +93,8 @@
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<activity android:name=".AgreementActivity"></activity>
|
<activity android:name=".AgreementActivity" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -31,6 +31,7 @@ public class Config {
|
||||||
public static final boolean logTempBasalsCut = true;
|
public static final boolean logTempBasalsCut = true;
|
||||||
public static final boolean logNSUpload = true;
|
public static final boolean logNSUpload = true;
|
||||||
public static final boolean logPumpActions = true;
|
public static final boolean logPumpActions = true;
|
||||||
|
public static final boolean logSMSComm = true;
|
||||||
|
|
||||||
// DanaR specific
|
// DanaR specific
|
||||||
public static final boolean logDanaBTComm = true;
|
public static final boolean logDanaBTComm = true;
|
||||||
|
|
|
@ -22,4 +22,6 @@ public class Constants {
|
||||||
public static final int hoursToKeepInDatabase = 24;
|
public static final int hoursToKeepInDatabase = 24;
|
||||||
|
|
||||||
public static final long keepAliveMsecs = 30 * 60 * 1000L;
|
public static final long keepAliveMsecs = 30 * 60 * 1000L;
|
||||||
|
|
||||||
|
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
if (pref.getTitle().toString().toLowerCase().contains("password"))
|
if (pref.getTitle().toString().toLowerCase().contains("password"))
|
||||||
{
|
{
|
||||||
pref.setSummary("******");
|
pref.setSummary("******");
|
||||||
} else {
|
} else if (editTextPref.getText() != null && !editTextPref.getText().equals("")){
|
||||||
pref.setSummary(editTextPref.getText());
|
pref.setSummary(editTextPref.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
public void onCreate(final Bundle savedInstanceState) {
|
public void onCreate(final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
addPreferencesFromResource(R.xml.pref_language);
|
addPreferencesFromResource(R.xml.pref_language);
|
||||||
|
if (Config.CAREPORTALENABLED)
|
||||||
|
addPreferencesFromResource(R.xml.pref_careportal);
|
||||||
addPreferencesFromResource(R.xml.pref_treatments);
|
addPreferencesFromResource(R.xml.pref_treatments);
|
||||||
if (Config.APS)
|
if (Config.APS)
|
||||||
addPreferencesFromResource(R.xml.pref_closedmode);
|
addPreferencesFromResource(R.xml.pref_closedmode);
|
||||||
|
@ -87,8 +89,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
||||||
addPreferencesFromResource(R.xml.pref_danar);
|
addPreferencesFromResource(R.xml.pref_danar);
|
||||||
if (Config.MM640G)
|
if (Config.MM640G)
|
||||||
addPreferencesFromResource(R.xml.pref_mm640g);
|
addPreferencesFromResource(R.xml.pref_mm640g);
|
||||||
if (Config.CAREPORTALENABLED)
|
if (Config.SMSCOMMUNICATORENABLED)
|
||||||
addPreferencesFromResource(R.xml.pref_careportal);
|
addPreferencesFromResource(R.xml.pref_smscommunicator);
|
||||||
initSummary(getPreferenceScreen());
|
initSummary(getPreferenceScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,9 @@ import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.provider.Telephony;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.telephony.SmsMessage;
|
||||||
|
|
||||||
import com.j256.ormlite.dao.Dao;
|
import com.j256.ormlite.dao.Dao;
|
||||||
import com.j256.ormlite.stmt.PreparedQuery;
|
import com.j256.ormlite.stmt.PreparedQuery;
|
||||||
|
@ -32,10 +34,13 @@ import info.nightscout.androidaps.events.EventNewBG;
|
||||||
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
import info.nightscout.androidaps.events.EventNewBasalProfile;
|
||||||
import info.nightscout.androidaps.events.EventTreatmentChange;
|
import info.nightscout.androidaps.events.EventTreatmentChange;
|
||||||
import info.nightscout.androidaps.Config;
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
|
||||||
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
import info.nightscout.androidaps.plugins.Objectives.ObjectivesFragment;
|
||||||
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
|
import info.nightscout.androidaps.plugins.Overview.OverviewFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.SmsCommunicator.Events.EventNewSMS;
|
||||||
|
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment;
|
||||||
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment;
|
import info.nightscout.androidaps.plugins.SourceNSClient.SourceNSClientFragment;
|
||||||
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment;
|
import info.nightscout.androidaps.plugins.SourceXdrip.SourceXdripFragment;
|
||||||
import info.nightscout.androidaps.receivers.NSClientDataReceiver;
|
import info.nightscout.androidaps.receivers.NSClientDataReceiver;
|
||||||
|
@ -50,6 +55,7 @@ public class DataService extends IntentService {
|
||||||
|
|
||||||
boolean xDripEnabled = false;
|
boolean xDripEnabled = false;
|
||||||
boolean nsClientEnabled = true;
|
boolean nsClientEnabled = true;
|
||||||
|
SmsCommunicatorFragment smsCommunicatorFragment = null;
|
||||||
|
|
||||||
public DataService() {
|
public DataService() {
|
||||||
super("DataService");
|
super("DataService");
|
||||||
|
@ -69,6 +75,10 @@ public class DataService extends IntentService {
|
||||||
xDripEnabled = false;
|
xDripEnabled = false;
|
||||||
nsClientEnabled = true;
|
nsClientEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MainActivity.getSpecificPlugin(SmsCommunicatorFragment.class) != null) {
|
||||||
|
smsCommunicatorFragment = (SmsCommunicatorFragment) MainActivity.getSpecificPlugin(SmsCommunicatorFragment.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
|
@ -89,6 +99,9 @@ public class DataService extends IntentService {
|
||||||
) {
|
) {
|
||||||
handleNewDataFromNSClient(intent);
|
handleNewDataFromNSClient(intent);
|
||||||
NSClientDataReceiver.completeWakefulIntent(intent);
|
NSClientDataReceiver.completeWakefulIntent(intent);
|
||||||
|
} else if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(action)) {
|
||||||
|
handleNewSMS(intent);
|
||||||
|
NSClientDataReceiver.completeWakefulIntent(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,4 +495,11 @@ public class DataService extends IntentService {
|
||||||
log.debug("REMOVE: Not stored treatment (ignoring): " + _id);
|
log.debug("REMOVE: Not stored treatment (ignoring): " + _id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleNewSMS(Intent intent) {
|
||||||
|
Bundle bundle = intent.getExtras();
|
||||||
|
if (bundle == null) return;
|
||||||
|
MainApp.bus().post(new EventNewSMS(bundle));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -746,7 +746,7 @@ public class DanaRFragment extends Fragment implements PluginBase, PumpInterface
|
||||||
}
|
}
|
||||||
if (getDanaRPump().lastBolusTime.getTime() != 0) {
|
if (getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||||
Long agoMsec = new Date().getTime() - getDanaRPump().lastBolusTime.getTime();
|
Long agoMsec = new Date().getTime() - getDanaRPump().lastBolusTime.getTime();
|
||||||
int agoHours = (int) (agoMsec / 60d / 60d / 1000d);
|
double agoHours = (int) (agoMsec / 60d / 60d / 1000d);
|
||||||
if (agoHours < 6) // max 6h back
|
if (agoHours < 6) // max 6h back
|
||||||
lastBolusView.setText(formatTime.format(getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + " U");
|
lastBolusView.setText(formatTime.format(getDanaRPump().lastBolusTime) + " (" + DecimalFormatter.to1Decimal(agoHours) + " " + getString(R.string.hoursago) + ") " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + " U");
|
||||||
else lastBolusView.setText("");
|
else lastBolusView.setText("");
|
||||||
|
@ -854,5 +854,30 @@ public class DanaRFragment extends Fragment implements PluginBase, PumpInterface
|
||||||
return pump.convertedProfile;
|
return pump.convertedProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reply for sms communicator
|
||||||
|
public String shortStatus() {
|
||||||
|
final DateFormat formatTime = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
String ret = "";
|
||||||
|
if (getDanaRPump().lastConnection.getTime() != 0) {
|
||||||
|
Long agoMsec = new Date().getTime() - getDanaRPump().lastConnection.getTime();
|
||||||
|
int agoMin = (int) (agoMsec / 60d / 1000d);
|
||||||
|
ret += "LastConn: " + agoMin + " minago\n";
|
||||||
|
}
|
||||||
|
if (getDanaRPump().lastBolusTime.getTime() != 0) {
|
||||||
|
Long agoMsec = new Date().getTime() - getDanaRPump().lastBolusTime.getTime();
|
||||||
|
long agoHours = (int) (agoMsec / 60d / 60d / 1000d);
|
||||||
|
ret += "LastBolus: " + DecimalFormatter.to2Decimal(getDanaRPump().lastBolusAmount) + "U @" + formatTime.format(getDanaRPump().lastBolusTime) + "\n";
|
||||||
|
}
|
||||||
|
if (isRealTempBasalInProgress()) {
|
||||||
|
ret += "Temp: " + getRealTempBasal().toString() + "\n";
|
||||||
|
}
|
||||||
|
if (isExtendedBoluslInProgress()) {
|
||||||
|
ret += "Extended: " + getExtendedBolus().toString() + "\n";
|
||||||
|
}
|
||||||
|
ret += "IOB: " + getDanaRPump().iob + "U\n";
|
||||||
|
ret += "Reserv: " + DecimalFormatter.to0Decimal(getDanaRPump().reservoirRemainingUnits) + "U\n";
|
||||||
|
ret += "Batt: " + getDanaRPump().batteryRemaining + "\n";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
// TODO: daily total constraint
|
// TODO: daily total constraint
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package info.nightscout.androidaps.plugins.SmsCommunicator.Events;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by mike on 13.07.2016.
|
||||||
|
*/
|
||||||
|
public class EventNewSMS {
|
||||||
|
public Bundle bundle;
|
||||||
|
public EventNewSMS(Bundle bundle) {
|
||||||
|
this.bundle = bundle;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package info.nightscout.androidaps.plugins.SmsCommunicator.Receivers;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||||
|
import android.telephony.SmsMessage;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Config;
|
||||||
|
import info.nightscout.androidaps.MainActivity;
|
||||||
|
import info.nightscout.androidaps.Services.DataService;
|
||||||
|
import info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment;
|
||||||
|
|
||||||
|
public class SmsReceiver extends WakefulBroadcastReceiver {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(SmsReceiver.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (Config.logFunctionCalls)
|
||||||
|
log.debug("onReceive " + intent);
|
||||||
|
startWakefulService(context, new Intent(context, DataService.class)
|
||||||
|
.setAction(intent.getAction())
|
||||||
|
.putExtras(intent));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,52 @@
|
||||||
package info.nightscout.androidaps.plugins.SmsCommunicator;
|
package info.nightscout.androidaps.plugins.SmsCommunicator;
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.telephony.SmsManager;
|
||||||
|
import android.telephony.SmsMessage;
|
||||||
|
import android.text.Html;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.Constants;
|
||||||
|
import info.nightscout.androidaps.MainActivity;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
|
import info.nightscout.androidaps.Services.Intents;
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||||
|
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
|
||||||
|
import info.nightscout.androidaps.plugins.SmsCommunicator.Events.EventNewSMS;
|
||||||
|
import info.nightscout.utils.SafeParse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple {@link Fragment} subclass.
|
* A simple {@link Fragment} subclass.
|
||||||
*/
|
*/
|
||||||
public class SmsCommunicatorFragment extends Fragment implements PluginBase {
|
public class SmsCommunicatorFragment extends Fragment implements PluginBase {
|
||||||
|
private static Logger log = LoggerFactory.getLogger(SmsCommunicatorFragment.class);
|
||||||
|
|
||||||
|
TextView logView;
|
||||||
|
|
||||||
boolean fragmentEnabled = false;
|
boolean fragmentEnabled = false;
|
||||||
boolean fragmentVisible = true;
|
boolean fragmentVisible = true;
|
||||||
|
@ -29,12 +61,50 @@ public class SmsCommunicatorFragment extends Fragment implements PluginBase {
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Sms {
|
||||||
|
String phoneNumber;
|
||||||
|
String text;
|
||||||
|
Date date;
|
||||||
|
boolean received = false;
|
||||||
|
boolean sent = false;
|
||||||
|
boolean processed = false;
|
||||||
|
|
||||||
|
String confirmCode;
|
||||||
|
double bolusRequested = 0d;
|
||||||
|
|
||||||
|
public Sms(SmsMessage message) {
|
||||||
|
phoneNumber = message.getOriginatingAddress();
|
||||||
|
text = message.getMessageBody();
|
||||||
|
date = new Date(message.getTimestampMillis());
|
||||||
|
received = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sms(String phoneNumber, String text, Date date) {
|
||||||
|
this.phoneNumber = phoneNumber;
|
||||||
|
this.text = text;
|
||||||
|
this.date = date;
|
||||||
|
sent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "SMS from " + phoneNumber + ": " + text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sms bolusWaitingForConfirmation = null;
|
||||||
|
Date lastRemoteBolusTime = new Date(0);
|
||||||
|
|
||||||
|
ArrayList<Sms> messages = new ArrayList<Sms>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
// Inflate the layout for this fragment
|
View view = inflater.inflate(R.layout.smscommunicator_fragment, container, false);
|
||||||
return inflater.inflate(R.layout.smscommunicator_fragment, container, false);
|
|
||||||
|
logView = (TextView) view.findViewById(R.id.smscommunicator_log);
|
||||||
|
|
||||||
|
updateGUI();
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerBus() {
|
private void registerBus() {
|
||||||
|
@ -80,4 +150,143 @@ public class SmsCommunicatorFragment extends Fragment implements PluginBase {
|
||||||
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
public void setFragmentVisible(int type, boolean fragmentVisible) {
|
||||||
this.fragmentVisible = fragmentVisible;
|
this.fragmentVisible = fragmentVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onStatusEvent(final EventNewSMS ev) {
|
||||||
|
|
||||||
|
Object[] pdus = (Object[]) ev.bundle.get("pdus");
|
||||||
|
// For every SMS message received
|
||||||
|
for (int i = 0; i < pdus.length; i++) {
|
||||||
|
SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]);
|
||||||
|
processSms(new Sms(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSms(Sms receivedSms) {
|
||||||
|
if (!isEnabled(PluginBase.GENERAL)) {
|
||||||
|
log.debug("Ignoring SMS. Plugin disabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
String allowedNumbers = sharedPreferences.getString("smscommunicator_allowednumbers", "");
|
||||||
|
|
||||||
|
if (allowedNumbers.indexOf(receivedSms.phoneNumber) < 0) {
|
||||||
|
log.debug("Ignoring SMS from: " + receivedSms.phoneNumber + ". Sender not allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String reply = "";
|
||||||
|
|
||||||
|
messages.add(receivedSms);
|
||||||
|
log.debug(receivedSms.toString());
|
||||||
|
|
||||||
|
String[] splited = receivedSms.text.split("\\s+");
|
||||||
|
double amount = 0d;
|
||||||
|
String passCode = "";
|
||||||
|
|
||||||
|
if (splited.length > 0) {
|
||||||
|
switch (splited[0].toUpperCase()) {
|
||||||
|
case "RNSC":
|
||||||
|
Intent restartNSClient = new Intent(Intents.ACTION_RESTART);
|
||||||
|
MainApp.instance().getApplicationContext().sendBroadcast(restartNSClient);
|
||||||
|
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(restartNSClient, 0);
|
||||||
|
reply = "RNSC " + q.size() + " receivers";
|
||||||
|
receivedSms.processed = true;
|
||||||
|
break;
|
||||||
|
case "DANAR":
|
||||||
|
DanaRFragment danaRFragment = (DanaRFragment) MainActivity.getSpecificPlugin(DanaRFragment.class);
|
||||||
|
if (danaRFragment != null) reply = danaRFragment.shortStatus();
|
||||||
|
receivedSms.processed = true;
|
||||||
|
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);
|
||||||
|
receivedSms.processed = true;
|
||||||
|
} else {
|
||||||
|
reply = MainApp.sResources.getString(R.string.remotebolusnotallowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.processed = true;
|
||||||
|
PumpInterface pumpInterface = MainApp.getConfigBuilder().getActivePump();
|
||||||
|
if (pumpInterface != null) {
|
||||||
|
danaRFragment = (DanaRFragment) MainActivity.getSpecificPlugin(DanaRFragment.class);
|
||||||
|
PumpEnactResult result = pumpInterface.deliverTreatment(bolusWaitingForConfirmation.bolusRequested, 0);
|
||||||
|
if (result.success) {
|
||||||
|
reply = String.format(MainApp.sResources.getString(R.string.bolusdelivered), bolusWaitingForConfirmation.bolusRequested);
|
||||||
|
if (danaRFragment != null) reply += "\n" + danaRFragment.shortStatus();
|
||||||
|
lastRemoteBolusTime = new Date();
|
||||||
|
} else {
|
||||||
|
reply = MainApp.sResources.getString(R.string.bolusfailed);
|
||||||
|
if (danaRFragment != null) reply += "\n" + danaRFragment.shortStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reply.equals("")) {
|
||||||
|
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, newSms.text, null, null);
|
||||||
|
messages.add(newSms);
|
||||||
|
}
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void updateGUI() {
|
||||||
|
Activity activity = getActivity();
|
||||||
|
if (activity != null)
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
class CustomComparator implements Comparator<Sms> {
|
||||||
|
public int compare(Sms object1, Sms object2) {
|
||||||
|
return (int) (object1.date.getTime() - object2.date.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(messages, new CustomComparator());
|
||||||
|
int messagesToShow = 40;
|
||||||
|
|
||||||
|
int start = Math.max(0, messages.size() - messagesToShow);
|
||||||
|
DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
|
||||||
|
|
||||||
|
String logText = "";
|
||||||
|
for (int x = start; x < messages.size(); x++) {
|
||||||
|
Sms sms = messages.get(x);
|
||||||
|
if (sms.received) {
|
||||||
|
logText += df.format(sms.date) + " <<< " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " <b>" + sms.text + "</b><br>";
|
||||||
|
} else if (sms.sent) {
|
||||||
|
logText += df.format(sms.date) + " >>> " + (sms.processed ? "● " : "○ ") + sms.phoneNumber + " <b>" + sms.text + "</b><br>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logView.setText(Html.fromHtml(logText));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,15 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context="info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment">
|
tools:context="info.nightscout.androidaps.plugins.SmsCommunicator.SmsCommunicatorFragment">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/smscommunicator_log"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:text=""/>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
|
@ -242,8 +242,15 @@
|
||||||
<string name="percent">Percent</string>
|
<string name="percent">Percent</string>
|
||||||
<string name="absolute">Absolute</string>
|
<string name="absolute">Absolute</string>
|
||||||
<string name="canceltemp">Cancel temp basal</string>
|
<string name="canceltemp">Cancel temp basal</string>
|
||||||
<string name="smscommunicator">Sms Communicator</string>
|
<string name="smscommunicator">SMS Communicator</string>
|
||||||
<string name="mm640g">MM 640g</string>
|
<string name="mm640g">MM 640g</string>
|
||||||
<string name="waitingforpumpresult">Waiting for result</string>
|
<string name="waitingforpumpresult">Waiting for result</string>
|
||||||
|
<string name="smscommunicator_allowednumbers">Allowed phone numbers</string>
|
||||||
|
<string name="smscommunicator_allowednumbers_summary">+XXXXXXXXXX;+YYYYYYYYYY</string>
|
||||||
|
<string formatted="false" name="replywithcode">To deliver bolus %.2fU reply with code %s</string>
|
||||||
|
<string name="bolusfailed">Bolus failed</string>
|
||||||
|
<string formatted="false" name="bolusdelivered">Bolus %.2fU delivered successfully</string>
|
||||||
|
<string name="smscommunicator_remotebolusingallowed">Allow remote bolusing via SMS</string>
|
||||||
|
<string name="remotebolusnotallowed">Remote bolus not allowed</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
20
app/src/main/res/xml/pref_smscommunicator.xml
Normal file
20
app/src/main/res/xml/pref_smscommunicator.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="smscommunicator"
|
||||||
|
android:title="@string/smscommunicator">
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:title="@string/smscommunicator_allowednumbers"
|
||||||
|
android:summary="@string/smscommunicator_allowednumbers_summary"
|
||||||
|
android:key="smscommunicator_allowednumbers"
|
||||||
|
android:defaultValue="">
|
||||||
|
</EditTextPreference>
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="smscommunicator_remotebolusingallowed"
|
||||||
|
android:title="@string/smscommunicator_remotebolusingallowed" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
Loading…
Reference in a new issue