diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java
index a857153c73..e464ec6418 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Notification.java
@@ -51,6 +51,8 @@ public class Notification {
public static final int TOAST_ALARM = 22;
public static final int WRONGBASALSTEP = 23;
public static final int BOLUS_DELIVERY_ERROR = 24;
+ public static final int PUMP_UNREACHABLE = 26;
+ public static final int BG_READINGS_MISSED = 27;
public int id;
public Date date;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java
index 8c70d3eea6..58978eeead 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/NotificationStore.java
@@ -1,6 +1,14 @@
package info.nightscout.androidaps.plugins.Overview;
+import android.app.NotificationManager;
+import android.content.Context;
import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.AudioAttributes;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.support.v4.app.NotificationCompat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -8,14 +16,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.AlarmSoundService;
import info.nightscout.androidaps.plugins.Wear.WearPlugin;
-//Added by Rumen for snooze time
+//Added by Rumen for snooze time
import info.nightscout.utils.SP;
/**
@@ -49,11 +56,16 @@ public class NotificationStore {
return;
}
}
- if (n.soundId != null) {
+
+ if (SP.getBoolean(MainApp.sResources.getString(R.string.key_raise_urgent_alarms_as_android_notification), false)
+ && n.level == Notification.URGENT) {
+ raiseSystemNotification(n);
+ } else if (n.soundId != null) {
Intent alarm = new Intent(MainApp.instance().getApplicationContext(), AlarmSoundService.class);
alarm.putExtra("soundid", n.soundId);
MainApp.instance().startService(alarm);
}
+
store.add(n);
WearPlugin wearPlugin = MainApp.getSpecificPlugin(WearPlugin.class);
@@ -64,6 +76,23 @@ public class NotificationStore {
Collections.sort(store, new NotificationComparator());
}
+ private void raiseSystemNotification(Notification n) {
+ Context context = MainApp.instance().getApplicationContext();
+ NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ Bitmap largeIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.blueowl);
+ Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
+ NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(context)
+ .setSmallIcon(R.drawable.ic_notification)
+ .setLargeIcon(largeIcon)
+ .setContentTitle("Urgent alarm")
+ .setContentText(n.text)
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setVibrate(new long[] { 1000, 1000, 1000, 1000})
+ .setSound(sound, AudioAttributes.USAGE_ALARM);
+ mgr.notify(n.id, notificationBuilder.build());
+ }
+
public boolean remove(int id) {
for (int i = 0; i < store.size(); i++) {
if (get(i).id == id) {
diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
index e3c77d0122..7e81b950c7 100644
--- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
+++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java
@@ -20,39 +20,76 @@ import java.util.Date;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
-import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.db.BgReading;
+import info.nightscout.androidaps.db.DatabaseHelper;
+import info.nightscout.androidaps.interfaces.PumpInterface;
+import info.nightscout.androidaps.plugins.Overview.Notification;
+import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.utils.SP;
public class KeepAliveReceiver extends BroadcastReceiver {
+ public static final long STATUS_UPDATE_FREQUENCY = 15 * 60 * 1000L;
private static Logger log = LoggerFactory.getLogger(KeepAliveReceiver.class);
+ // TODO consider moving this into an Alarms plugin that works offline and can be configured
+ // (e.g. override silent mode at night only)
+ public static final int ALARM_FREQUENCY = 25 * 60 * 1000;
+ private static long nextPumpDisconnectedAlarm = System.currentTimeMillis() + ALARM_FREQUENCY;
+ private static long nextMissedReadingsAlarm = System.currentTimeMillis() + ALARM_FREQUENCY;
+
@Override
public void onReceive(Context context, Intent rIntent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
+ checkBg();
+ checkPump();
+ log.debug("KeepAlive received");
+ wl.release();
+ }
+
+ private void checkBg() {
+ BgReading bgReading = DatabaseHelper.lastBg();
+ if (SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_missed_bg_readings_alert), false)
+ && bgReading != null && bgReading.date + ALARM_FREQUENCY < System.currentTimeMillis()
+ && nextMissedReadingsAlarm < System.currentTimeMillis()) {
+ Notification n = new Notification(Notification.BG_READINGS_MISSED, MainApp.sResources.getString(R.string.missed_bg_readings), Notification.URGENT);
+ n.soundId = R.raw.alarm;
+ nextMissedReadingsAlarm = System.currentTimeMillis() + ALARM_FREQUENCY;
+ MainApp.bus().post(new EventNewNotification(n));
+ }
+ }
+
+ private void checkPump() {
final PumpInterface pump = MainApp.getConfigBuilder();
final Profile profile = MainApp.getConfigBuilder().getProfile();
if (pump != null && profile != null && profile.getBasal() != null) {
- boolean isBasalOutdated = false;
- boolean isStatusOutdated = false;
-
Date lastConnection = pump.lastDataTime();
- if (lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis())
- isStatusOutdated = true;
- if (Math.abs(profile.getBasal() - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep)
- isBasalOutdated = true;
+
+ boolean isStatusOutdated = lastConnection.getTime() + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis();
+ boolean isBasalOutdated = Math.abs(profile.getBasal() - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep;
+
+ boolean alarmTimeoutExpired = lastConnection.getTime() + ALARM_FREQUENCY < System.currentTimeMillis();
+ boolean nextAlarmOccurrenceReached = nextPumpDisconnectedAlarm < System.currentTimeMillis();
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
- if (SP.getBoolean("syncprofiletopump", false) && !pump.isThisProfileSet(profile)) {
+ if (SP.getBoolean(MainApp.sResources.getString(R.string.key_enable_pump_unreachable_alert), false)
+ && isStatusOutdated && alarmTimeoutExpired && nextAlarmOccurrenceReached) {
+ Notification n = new Notification(Notification.PUMP_UNREACHABLE, MainApp.sResources.getString(R.string.pump_unreachable), Notification.URGENT);
+ n.soundId = R.raw.alarm;
+ nextPumpDisconnectedAlarm = System.currentTimeMillis() + ALARM_FREQUENCY;
+ MainApp.bus().post(new EventNewNotification(n));
+ } else if (SP.getBoolean("syncprofiletopump", false) && !pump.isThisProfileSet(profile)) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
pump.setNewBasalProfile(profile);
}
- });
+ }, "pump-update-basal-profile");
t.start();
} else if (isStatusOutdated && !pump.isBusy()) {
Thread t = new Thread(new Runnable() {
@@ -60,7 +97,7 @@ public class KeepAliveReceiver extends BroadcastReceiver {
public void run() {
pump.refreshDataFromPump("KeepAlive. Status outdated.");
}
- });
+ }, "pump-refresh");
t.start();
} else if (isBasalOutdated && !pump.isBusy()) {
Thread t = new Thread(new Runnable() {
@@ -68,13 +105,10 @@ public class KeepAliveReceiver extends BroadcastReceiver {
public void run() {
pump.refreshDataFromPump("KeepAlive. Basal outdated.");
}
- });
+ }, "pump-refresh");
t.start();
}
}
-
- log.debug("KeepAlive received");
- wl.release();
}
public void setAlarm(Context context) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c3041e9f7d..2dcc1663df 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -757,5 +757,14 @@
Waiting for estimated bolus end. Remaining %d sec.
Processing event
Starting bolus delivery
+ Pump unreachable
+ Missed BG readings
+ raise_urgent_alarms_as_android_notification
+ Use system notifications for alerts
+ enable_pump_unreachable_alert
+ enable_missed_bg_readings
+ Local alerts
+ Alert if no BGs received in 30 min
+ Alert if pump unreachable for 30 min
diff --git a/app/src/main/res/xml/pref_others.xml b/app/src/main/res/xml/pref_others.xml
index e0b5f02c5b..2053859b5e 100644
--- a/app/src/main/res/xml/pref_others.xml
+++ b/app/src/main/res/xml/pref_others.xml
@@ -72,4 +72,20 @@
android:key="short_tabtitles"
android:title="@string/short_tabtitles"/>
+
+
+
+
+