- Make Low Reservoir Alert & Expiration Advisory Alert optional and configurable

- Organize Omnipod settings
- Various small improvements
This commit is contained in:
Bart Sopers 2020-09-03 22:04:01 +02:00
parent 808927ee55
commit 4f6e31a784
28 changed files with 476 additions and 175 deletions

View file

@ -73,6 +73,7 @@ public class Notification {
public static final int CARBS_REQUIRED = 60;
public static final int IMPORTANCE_HIGH = 2;
public static final int OMNIPOD_POD_SUSPENDED = 61;
public static final int OMNIPOD_POD_ALERTS_UPDATED = 62;
public static final String CATEGORY_ALARM = "alarm";

View file

@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import javax.inject.Inject;
@ -73,7 +75,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodCommand
import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodCustomActionType;
import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodStatusRequestType;
import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodStorageKeys;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.ExpirationReminderBuilder;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged;
@ -82,6 +86,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManage
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.service.RileyLinkOmnipodService;
import info.nightscout.androidaps.plugins.pump.omnipod.ui.OmnipodFragment;
import info.nightscout.androidaps.plugins.pump.omnipod.util.AapsOmnipodUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodAlertUtil;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy;
@ -108,6 +113,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
private final AapsOmnipodManager aapsOmnipodManager;
private final AapsOmnipodUtil aapsOmnipodUtil;
private final RileyLinkUtil rileyLinkUtil;
private final OmnipodAlertUtil omnipodAlertUtil;
private final AAPSLogger aapsLogger;
private final RxBusWrapper rxBus;
private final ActivePluginProvider activePlugin;
@ -155,7 +161,8 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
ServiceTaskExecutor serviceTaskExecutor,
DateUtil dateUtil,
AapsOmnipodUtil aapsOmnipodUtil,
RileyLinkUtil rileyLinkUtil
RileyLinkUtil rileyLinkUtil,
OmnipodAlertUtil omnipodAlertUtil
) {
super(new PluginDescription() //
.mainType(PluginType.PUMP) //
@ -179,6 +186,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
this.aapsOmnipodManager = aapsOmnipodManager;
this.aapsOmnipodUtil = aapsOmnipodUtil;
this.rileyLinkUtil = rileyLinkUtil;
this.omnipodAlertUtil = omnipodAlertUtil;
pumpDescription = new PumpDescription(pumpType);
@ -221,9 +229,13 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
aapsOmnipodManager.createSuspendedFakeTbrIfNotExists();
}
if (!OmnipodPumpPlugin.this.statusRequestList.isEmpty() || OmnipodPumpPlugin.this.hasTimeDateOrTimeZoneChanged) {
if (!getCommandQueue().statusInQueue()) {
getCommandQueue().readStatus(statusRequestList.isEmpty() ? "Date or Time Zone Changed" : "Status Refresh Requested", null);
if (!getCommandQueue().statusInQueue()) {
if (!OmnipodPumpPlugin.this.statusRequestList.isEmpty()) {
getCommandQueue().readStatus("Status Refresh Requested", null);
} else if (OmnipodPumpPlugin.this.hasTimeDateOrTimeZoneChanged) {
getCommandQueue().readStatus("Date or Time Zone Changed", null);
} else if (!OmnipodPumpPlugin.this.verifyPodAlertConfiguration()) {
getCommandQueue().readStatus("Expiration Alerts Changed", null);
}
}
@ -270,8 +282,16 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
(event.isChanged(getResourceHelper(), R.string.key_omnipod_smb_beeps_enabled)) ||
(event.isChanged(getResourceHelper(), R.string.key_omnipod_suspend_delivery_button_enabled)) ||
(event.isChanged(getResourceHelper(), R.string.key_omnipod_pulse_log_button_enabled)) ||
(event.isChanged(getResourceHelper(), R.string.key_omnipod_time_change_event_enabled)))
(event.isChanged(getResourceHelper(), R.string.key_omnipod_time_change_event_enabled))) {
aapsOmnipodManager.reloadSettings();
} else if (event.isChanged(getResourceHelper(), R.string.key_omnipod_expiration_reminder_enabled) ||
event.isChanged(getResourceHelper(), R.string.key_omnipod_expiration_reminder_hours_before_shutdown) ||
event.isChanged(getResourceHelper(), R.string.key_omnipod_low_reservoir_alert_enabled) ||
event.isChanged(getResourceHelper(), R.string.key_omnipod_low_reservoir_alert_units)) {
if (!verifyPodAlertConfiguration() && !getCommandQueue().statusInQueue()) {
getCommandQueue().readStatus("Expiration Alerts Changed", null);
}
}
}, fabricPrivacy::logException)
);
disposables.add(rxBus
@ -490,6 +510,32 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
timeChangeRetries = 0;
}
}
} else if (!verifyPodAlertConfiguration()) {
Duration expirationReminderTimeBeforeShutdown = omnipodAlertUtil.getExpirationReminderTimeBeforeShutdown();
Integer lowReservoirAlertUnits = omnipodAlertUtil.getLowReservoirAlertUnits();
List<AlertConfiguration> alertConfigurations = new ExpirationReminderBuilder(podStateManager) //
.expirationAdvisory(expirationReminderTimeBeforeShutdown != null,
Optional.ofNullable(expirationReminderTimeBeforeShutdown).orElse(Duration.ZERO)) //
.lowReservoir(lowReservoirAlertUnits != null, Optional.ofNullable(lowReservoirAlertUnits).orElse(0)) //
.build();
PumpEnactResult result = executeCommand(OmnipodCommandType.CONFIGURE_ALERTS, () -> aapsOmnipodManager.configureAlerts(alertConfigurations));
if (result.success) {
aapsLogger.info(LTag.PUMP, "Successfully configured alerts in Pod");
podStateManager.setExpirationAlertTimeBeforeShutdown(expirationReminderTimeBeforeShutdown);
podStateManager.setLowReservoirAlertUnits(lowReservoirAlertUnits);
Notification notification = new Notification(
Notification.OMNIPOD_POD_ALERTS_UPDATED,
resourceHelper.gs(R.string.omnipod_expiration_alerts_updated),
Notification.INFO, 60);
rxBus.send(new EventNewNotification(notification));
} else {
aapsLogger.warn(LTag.PUMP, "Failed to configure alerts in Pod");
}
}
}
@ -500,19 +546,6 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
aapsLogger.info(LTag.PUMP, "Basal Profile was set: " + result.success);
if (result.success) {
rxBus.send(new EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED));
Notification notification = new Notification(Notification.PROFILE_SET_OK,
resourceHelper.gs(R.string.profile_set_ok),
Notification.INFO, 60);
rxBus.send(new EventNewNotification(notification));
} else {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE,
resourceHelper.gs(R.string.failedupdatebasalprofile),
Notification.URGENT);
rxBus.send(new EventNewNotification(notification));
}
return result;
}
@ -907,7 +940,6 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
T pumpEnactResult = supplier.get();
// TODO maybe only do this for specific commands
rxBus.send(new EventRefreshOverview("Omnipod command: " + commandType.name(), false));
rxBus.send(new EventOmnipodPumpValuesChanged());
@ -915,6 +947,22 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface,
return pumpEnactResult;
}
private boolean verifyPodAlertConfiguration() {
if (podStateManager.isPodRunning()) {
Duration expirationReminderHoursBeforeShutdown = omnipodAlertUtil.getExpirationReminderTimeBeforeShutdown();
Integer lowReservoirAlertUnits = omnipodAlertUtil.getLowReservoirAlertUnits();
if (!Objects.equals(expirationReminderHoursBeforeShutdown, podStateManager.getExpirationAlertTimeBeforeShutdown())
|| !Objects.equals(lowReservoirAlertUnits, podStateManager.getLowReservoirAlertUnits())) {
aapsLogger.warn(LTag.PUMP, "Configured alerts in Pod don't match AAPS settings: expirationReminderHoursBeforeShutdown = {} (AAPS) vs {} Pod, " +
"lowReservoirAlertUnits = {} (AAPS) vs {} (Pod)", expirationReminderHoursBeforeShutdown, podStateManager.getExpirationAlertTimeBeforeShutdown(),
lowReservoirAlertUnits, podStateManager.getLowReservoirAlertUnits());
return false;
}
}
return true;
}
private void incrementStatistics(String statsKey) {
long currentCount = sp.getLong(statsKey, 0L);
currentCount++;

View file

@ -17,6 +17,7 @@ public enum OmnipodCommandType {
DISCARD_POD(R.string.omnipod_cmd_discard_pod), //
GET_POD_STATUS(R.string.omnipod_cmd_get_pod_status), //
SET_TIME(R.string.omnipod_cmd_set_time), //
CONFIGURE_ALERTS(R.string.omnipod_cmd_configure_alerts), //
ACKNOWLEDGE_ALERTS(R.string.omnipod_cmd_acknowledge_alerts), //
GET_POD_PULSE_LOG(R.string.omnipod_cmd_get_pulse_log), //
SUSPEND_DELIVERY(R.string.omnipod_cmd_suspend_delivery);

View file

@ -15,6 +15,10 @@ public class OmnipodStorageKeys {
public static final int SUSPEND_DELIVERY_BUTTON_ENABLED = R.string.key_omnipod_pulse_log_button_enabled;
public static final int PULSE_LOG_BUTTON_ENABLED = R.string.key_omnipod_pulse_log_button_enabled;
public static final int TIME_CHANGE_EVENT_ENABLED = R.string.key_omnipod_time_change_event_enabled;
public static final int EXPIRATION_REMINDER_ENABLED = R.string.key_omnipod_expiration_reminder_enabled;
public static final int EXPIRATION_REMINDER_HOURS_BEFORE_SHUTDOWN = R.string.key_omnipod_expiration_reminder_hours_before_shutdown;
public static final int LOW_RESERVOIR_ALERT_ENABLED = R.string.key_omnipod_low_reservoir_alert_enabled;
public static final int LOW_RESERVOIR_ALERT_UNITS = R.string.key_omnipod_low_reservoir_alert_units;
}
public static class Statistics {

View file

@ -28,9 +28,17 @@ public class ConfigureAlertsAction implements OmnipodAction<StatusResponse> {
public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) {
ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand(podStateManager.getCurrentNonce(), alertConfigurations);
StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podStateManager, configureAlertsCommand);
for (AlertConfiguration alertConfiguration : alertConfigurations) {
podStateManager.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType());
}
updateConfiguredAlerts(podStateManager, alertConfigurations);
return statusResponse;
}
public static void updateConfiguredAlerts(PodStateManager podStateManager, List<AlertConfiguration> alertConfigurations) {
for (AlertConfiguration alertConfiguration : alertConfigurations) {
if (alertConfiguration.isActive()) {
podStateManager.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType());
} else {
podStateManager.removeConfiguredAlert(alertConfiguration.getAlertSlot());
}
}
}
}

View file

@ -1,7 +1,14 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.InsertCannulaService;
import org.joda.time.Duration;
import java.util.List;
import java.util.Optional;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.ExpirationReminderBuilder;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActionInitializationException;
@ -12,22 +19,22 @@ import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.Omnipod
public class InsertCannulaAction implements OmnipodAction<StatusResponse> {
private final PodStateManager podStateManager;
private final InsertCannulaService service;
private final BasalSchedule initialBasalSchedule;
private final Duration expirationReminderTimeBeforeShutdown;
private final Integer lowReservoirAlertUnits;
public InsertCannulaAction(InsertCannulaService insertCannulaService, PodStateManager podStateManager, BasalSchedule initialBasalSchedule) {
if (insertCannulaService == null) {
throw new ActionInitializationException("Insert cannula service cannot be null");
}
public InsertCannulaAction(PodStateManager podStateManager, BasalSchedule initialBasalSchedule,
Duration expirationReminderTimeBeforeShutdown, Integer lowReservoirAlertUnits) {
if (podStateManager == null) {
throw new ActionInitializationException("Pod state manager cannot be null");
}
if (initialBasalSchedule == null) {
throw new ActionInitializationException("Initial basal schedule cannot be null");
}
this.service = insertCannulaService;
this.podStateManager = podStateManager;
this.initialBasalSchedule = initialBasalSchedule;
this.expirationReminderTimeBeforeShutdown = expirationReminderTimeBeforeShutdown;
this.lowReservoirAlertUnits = lowReservoirAlertUnits;
}
@Override
@ -38,12 +45,18 @@ public class InsertCannulaAction implements OmnipodAction<StatusResponse> {
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.BASAL_INITIALIZED)) {
podStateManager.setBasalSchedule(initialBasalSchedule);
service.programInitialBasalSchedule(communicationService, podStateManager, initialBasalSchedule);
communicationService.executeAction(new SetBasalScheduleAction(podStateManager, initialBasalSchedule,
true, podStateManager.getScheduleOffset(), false));
}
if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.INSERTING_CANNULA)) {
service.executeExpirationRemindersAlertCommand(communicationService, podStateManager);
return service.executeInsertionBolusCommand(communicationService, podStateManager);
communicationService.executeAction(new ConfigureAlertsAction(podStateManager, buildAlertConfigurations()));
podStateManager.setExpirationAlertTimeBeforeShutdown(expirationReminderTimeBeforeShutdown);
podStateManager.setLowReservoirAlertUnits(lowReservoirAlertUnits);
return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS,
Duration.standardSeconds(1), false, false));
} else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.INSERTING_CANNULA)) {
// Check status
return communicationService.executeAction(new GetStatusAction(podStateManager));
@ -51,4 +64,12 @@ public class InsertCannulaAction implements OmnipodAction<StatusResponse> {
throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus());
}
}
private List<AlertConfiguration> buildAlertConfigurations() {
ExpirationReminderBuilder builder = new ExpirationReminderBuilder(podStateManager).defaults();
builder.expirationAdvisory(expirationReminderTimeBeforeShutdown != null,
Optional.ofNullable(expirationReminderTimeBeforeShutdown).orElse(Duration.ZERO));
builder.lowReservoir(lowReservoirAlertUnits != null, Optional.ofNullable(lowReservoirAlertUnits).orElse(0));
return builder.build();
}
}

View file

@ -0,0 +1,69 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.util.AlertConfigurationUtil;
public final class ExpirationReminderBuilder {
private final Map<AlertSlot, AlertConfiguration> alerts = new HashMap<>();
private final DateTime endOfServiceTime;
private final PodStateManager podStateManager;
public ExpirationReminderBuilder(PodStateManager podStateManager) {
this.endOfServiceTime = podStateManager.getActivatedAt().plus(OmnipodConstants.SERVICE_DURATION);
this.podStateManager = podStateManager;
}
public ExpirationReminderBuilder defaults() {
DateTime shutdownImminentAlarmTime = endOfServiceTime.minus(OmnipodConstants.END_OF_SERVICE_IMMINENT_WINDOW);
if (DateTime.now().isBefore(shutdownImminentAlarmTime)) {
Duration timeUntilShutdownImminentAlarm = new Duration(DateTime.now(),
shutdownImminentAlarmTime);
AlertConfiguration shutdownImminentAlertConfiguration = AlertConfigurationUtil.createShutdownImminentAlertConfiguration(
timeUntilShutdownImminentAlarm);
alerts.put(shutdownImminentAlertConfiguration.getAlertSlot(), shutdownImminentAlertConfiguration);
}
AlertConfiguration autoOffAlertConfiguration = AlertConfigurationUtil.createAutoOffAlertConfiguration(
false, Duration.ZERO);
alerts.put(autoOffAlertConfiguration.getAlertSlot(), autoOffAlertConfiguration);
return this;
}
public ExpirationReminderBuilder expirationAdvisory(boolean active, Duration timeBeforeShutdown) {
DateTime expirationAdvisoryAlarmTime = endOfServiceTime.minus(timeBeforeShutdown);
if (DateTime.now().isBefore(expirationAdvisoryAlarmTime)) {
Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(),
expirationAdvisoryAlarmTime);
AlertConfiguration expirationAdvisoryAlertConfiguration = AlertConfigurationUtil.createExpirationAdvisoryAlertConfiguration(active,
timeUntilExpirationAdvisoryAlarm, timeBeforeShutdown);
alerts.put(expirationAdvisoryAlertConfiguration.getAlertSlot(), expirationAdvisoryAlertConfiguration);
}
return this;
}
public ExpirationReminderBuilder lowReservoir(boolean active, int units) {
if (podStateManager.getReservoirLevel() == null || podStateManager.getReservoirLevel().intValue() > units) {
AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationUtil.createLowReservoirAlertConfiguration(active, (double) units);
alerts.put(lowReservoirAlertConfiguration.getAlertSlot(), lowReservoirAlertConfiguration);
}
return this;
}
public List<AlertConfiguration> build() {
return new ArrayList<>(alerts.values());
}
}

View file

@ -1,59 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.util.Arrays;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.BolusAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.ConfigureAlertsAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.SetBasalScheduleAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.util.AlertConfigurationUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
public class InsertCannulaService {
public StatusResponse programInitialBasalSchedule(OmnipodRileyLinkCommunicationManager communicationService,
PodStateManager podStateManager, BasalSchedule basalSchedule) {
return communicationService.executeAction(new SetBasalScheduleAction(podStateManager, basalSchedule,
true, podStateManager.getScheduleOffset(), false));
}
public StatusResponse executeExpirationRemindersAlertCommand(OmnipodRileyLinkCommunicationManager communicationService,
PodStateManager podStateManager) {
AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationUtil.createLowReservoirAlertConfiguration(OmnipodConstants.LOW_RESERVOIR_ALERT);
DateTime endOfServiceTime = podStateManager.getActivatedAt().plus(OmnipodConstants.SERVICE_DURATION);
Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(),
endOfServiceTime.minus(OmnipodConstants.EXPIRATION_ADVISORY_WINDOW));
Duration timeUntilShutdownImminentAlarm = new Duration(DateTime.now(),
endOfServiceTime.minus(OmnipodConstants.END_OF_SERVICE_IMMINENT_WINDOW));
AlertConfiguration expirationAdvisoryAlertConfiguration = AlertConfigurationUtil.createExpirationAdvisoryAlertConfiguration(
timeUntilExpirationAdvisoryAlarm, OmnipodConstants.EXPIRATION_ADVISORY_WINDOW);
AlertConfiguration shutdownImminentAlertConfiguration = AlertConfigurationUtil.createShutdownImminentAlertConfiguration(
timeUntilShutdownImminentAlarm);
AlertConfiguration autoOffAlertConfiguration = AlertConfigurationUtil.createAutoOffAlertConfiguration(
false, Duration.ZERO);
List<AlertConfiguration> alertConfigurations = Arrays.asList( //
lowReservoirAlertConfiguration, //
expirationAdvisoryAlertConfiguration, //
shutdownImminentAlertConfiguration, //
autoOffAlertConfiguration //
);
return communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations));
}
public StatusResponse executeInsertionBolusCommand(OmnipodRileyLinkCommunicationManager communicationService, PodStateManager podStateManager) {
return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS,
Duration.standardSeconds(1), false, false));
}
}

View file

@ -15,8 +15,7 @@ public class AlertConfiguration {
private final BeepType beepType;
public AlertConfiguration(AlertType alertType, AlertSlot alertSlot, boolean active, boolean autoOffModifier,
Duration duration, AlertTrigger alertTrigger,
BeepType beepType, BeepRepeat beepRepeat) {
Duration duration, AlertTrigger<?> alertTrigger, BeepType beepType, BeepRepeat beepRepeat) {
this.alertType = alertType;
this.alertSlot = alertSlot;
this.active = active;
@ -35,6 +34,14 @@ public class AlertConfiguration {
return alertSlot;
}
public AlertTrigger<?> getAlertTrigger() {
return alertTrigger;
}
public boolean isActive() {
return active;
}
public byte[] getRawData() {
int firstByte = (alertSlot.getValue() << 4);
firstByte += active ? (1 << 3) : 0;
@ -67,4 +74,17 @@ public class AlertConfiguration {
return encodedData;
}
@Override public String toString() {
return "AlertConfiguration{" +
"alertType=" + alertType +
", alertSlot=" + alertSlot +
", active=" + active +
", autoOffModifier=" + autoOffModifier +
", duration=" + duration +
", alertTrigger=" + alertTrigger +
", beepRepeat=" + beepRepeat +
", beepType=" + beepType +
'}';
}
}

View file

@ -1,6 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition;
abstract class AlertTrigger<T> {
public abstract class AlertTrigger<T> {
private final T value;
AlertTrigger(T value) {
@ -10,4 +10,10 @@ abstract class AlertTrigger<T> {
public T getValue() {
return value;
}
@Override public String toString() {
return "AlertTrigger{" +
"value=" + value +
'}';
}
}

View file

@ -5,6 +5,7 @@ import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
import java.util.EnumSet;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
@ -16,6 +17,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.acti
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.AssignAddressAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.BolusAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.CancelDeliveryAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.ConfigureAlertsAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.DeactivatePodAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.GetPodInfoAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.GetStatusAction;
@ -24,12 +26,12 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.acti
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.SetBasalScheduleAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.SetTempBasalAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.SetupPodAction;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.InsertCannulaService;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.PrimeService;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.CancelDeliveryCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType;
@ -131,7 +133,8 @@ public class OmnipodManager {
.observeOn(Schedulers.io());
}
public synchronized Single<SetupActionResult> insertCannula(BasalSchedule basalSchedule) {
public synchronized Single<SetupActionResult> insertCannula(
BasalSchedule basalSchedule, Duration expirationReminderTimeBeforeShutdown, Integer lowReservoirAlertUnits) {
if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) {
throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, !podStateManager.isPodInitialized() ? null : podStateManager.getPodProgressStatus());
}
@ -146,7 +149,7 @@ public class OmnipodManager {
logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]");
try {
communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podStateManager, basalSchedule));
communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits));
} finally {
logCommandExecutionFinished("insertCannula");
}
@ -184,6 +187,18 @@ public class OmnipodManager {
}
}
public synchronized StatusResponse configureAlerts(List<AlertConfiguration> alertConfigurations) {
assertReadyForDelivery();
logStartingCommandExecution("configureAlerts");
try {
StatusResponse statusResponse = executeAndVerify(() -> communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations)));
ConfigureAlertsAction.updateConfiguredAlerts(podStateManager, alertConfigurations);
return statusResponse;
} finally {
logCommandExecutionFinished("configureAlerts");
}
}
public synchronized StatusResponse acknowledgeAlerts() {
assertReadyForDelivery();

View file

@ -441,6 +441,22 @@ public abstract class PodStateManager {
return getSafe(() -> podState.getLastDeliveryStatus());
}
public final Duration getExpirationAlertTimeBeforeShutdown() {
return getSafe(() -> podState.getExpirationAlertTimeBeforeShutdown());
}
public final void setExpirationAlertTimeBeforeShutdown(Duration duration) {
setAndStore(() -> podState.setExpirationAlertTimeBeforeShutdown(duration));
}
public final Integer getLowReservoirAlertUnits() {
return getSafe(() -> podState.getLowReservoirAlertUnits());
}
public final void setLowReservoirAlertUnits(Integer units) {
setAndStore(() -> podState.setLowReservoirAlertUnits(units));
}
/**
* Does not automatically store pod state in order to decrease I/O load
*/
@ -579,6 +595,8 @@ public abstract class PodStateManager {
private DateTime tempBasalStartTime;
private Duration tempBasalDuration;
private Boolean tempBasalCertain;
private Duration expirationAlertTimeBeforeShutdown;
private Integer lowReservoirAlertUnits;
private final Map<AlertSlot, AlertType> configuredAlerts = new HashMap<>();
private PodState(int address) {
@ -833,6 +851,22 @@ public abstract class PodStateManager {
return configuredAlerts;
}
Duration getExpirationAlertTimeBeforeShutdown() {
return expirationAlertTimeBeforeShutdown;
}
void setExpirationAlertTimeBeforeShutdown(Duration duration) {
expirationAlertTimeBeforeShutdown = duration;
}
Integer getLowReservoirAlertUnits() {
return lowReservoirAlertUnits;
}
void setLowReservoirAlertUnits(Integer units) {
lowReservoirAlertUnits = units;
}
@Override public String toString() {
return "PodState{" +
"address=" + address +
@ -860,9 +894,13 @@ public abstract class PodStateManager {
", lastBolusStartTime=" + lastBolusStartTime +
", lastBolusAmount=" + lastBolusAmount +
", lastBolusDuration=" + lastBolusDuration +
", lastBolusCertain=" + lastBolusCertain +
", tempBasalAmount=" + tempBasalAmount +
", tempBasalStartTime=" + tempBasalStartTime +
", tempBasalDuration=" + tempBasalDuration +
", tempBasalCertain=" + tempBasalCertain +
", expirationAlertHoursBeforeShutdown=" + expirationAlertTimeBeforeShutdown +
", lowReservoirAlertUnits=" + lowReservoirAlertUnits +
", configuredAlerts=" + configuredAlerts +
'}';
}

View file

@ -11,19 +11,19 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.TimerAl
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.UnitsRemainingAlertTrigger;
public class AlertConfigurationUtil {
public static AlertConfiguration createLowReservoirAlertConfiguration(Double units) {
return new AlertConfiguration(AlertType.LOW_RESERVOIR_ALERT, AlertSlot.SLOT4, true, false, Duration.ZERO,
public static AlertConfiguration createLowReservoirAlertConfiguration(boolean active, Double units) {
return new AlertConfiguration(AlertType.LOW_RESERVOIR_ALERT, AlertSlot.SLOT4, active, false, Duration.ZERO,
new UnitsRemainingAlertTrigger(units), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_MINUTE_FOR_3_MINUTES_REPEAT_EVERY_60_MINUTES);
}
public static AlertConfiguration createExpirationAdvisoryAlertConfiguration(Duration timeUntilAlert, Duration duration) {
return new AlertConfiguration(AlertType.EXPIRATION_ADVISORY_ALERT, AlertSlot.SLOT7, true, false, duration,
new TimerAlertTrigger(timeUntilAlert), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_MINUTE_FOR_3_MINUTES_REPEAT_EVERY_15_MINUTES);
public static AlertConfiguration createExpirationAdvisoryAlertConfiguration(boolean active, Duration timeUntilAlert, Duration duration) {
return new AlertConfiguration(AlertType.EXPIRATION_ADVISORY_ALERT, AlertSlot.SLOT7, active, false, duration,
new TimerAlertTrigger(timeUntilAlert), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_15_MINUTES);
}
public static AlertConfiguration createShutdownImminentAlertConfiguration(Duration timeUntilAlert) {
return new AlertConfiguration(AlertType.SHUTDOWN_IMMINENT_ALARM, AlertSlot.SLOT2, true, false, Duration.ZERO,
new TimerAlertTrigger(timeUntilAlert), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_15_MINUTES);
new TimerAlertTrigger(timeUntilAlert), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_MINUTE_FOR_3_MINUTES_REPEAT_EVERY_15_MINUTES);
}
public static AlertConfiguration createAutoOffAlertConfiguration(boolean active, Duration countdownDuration) {

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.manager;
import android.content.Context;
import android.content.Intent;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@ -14,7 +13,6 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
@ -43,6 +41,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.definition.PodInitReceive
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants;
@ -75,6 +74,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.SetupActio
import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged;
import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager;
import info.nightscout.androidaps.plugins.pump.omnipod.util.AapsOmnipodUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodAlertUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.Disposable;
@ -94,6 +94,7 @@ public class AapsOmnipodManager {
private final SP sp;
private final OmnipodManager delegate;
private final DatabaseHelperInterface databaseHelper;
private final OmnipodAlertUtil omnipodAlertUtil;
private boolean basalBeepsEnabled;
private boolean bolusBeepsEnabled;
@ -114,7 +115,8 @@ public class AapsOmnipodManager {
HasAndroidInjector injector,
ActivePluginProvider activePlugin,
Context context,
DatabaseHelperInterface databaseHelper) {
DatabaseHelperInterface databaseHelper,
OmnipodAlertUtil omnipodAlertUtil) {
if (podStateManager == null) {
throw new IllegalArgumentException("Pod state manager can not be null");
}
@ -128,6 +130,7 @@ public class AapsOmnipodManager {
this.context = context;
this.databaseHelper = databaseHelper;
this.sp = sp;
this.omnipodAlertUtil = omnipodAlertUtil;
delegate = new OmnipodManager(aapsLogger, sp, communicationService, podStateManager);
}
@ -178,7 +181,8 @@ public class AapsOmnipodManager {
} catch (Exception ex) {
throw new CommandInitializationException("Basal profile mapping failed", ex);
}
Disposable disposable = delegate.insertCannula(basalSchedule).subscribe(res -> //
Disposable disposable = delegate.insertCannula(basalSchedule, omnipodAlertUtil.getExpirationReminderTimeBeforeShutdown(), omnipodAlertUtil.getLowReservoirAlertUnits()).subscribe(res -> //
handleSetupActionResult(podInitActionType, podInitReceiver, res, System.currentTimeMillis(), profile));
rxBus.send(new EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED));
@ -194,6 +198,18 @@ public class AapsOmnipodManager {
}
}
public PumpEnactResult configureAlerts(List<AlertConfiguration> alertConfigurations) {
try {
StatusResponse statusResponse = delegate.configureAlerts(alertConfigurations);
addSuccessToHistory(PodHistoryEntryType.CONFIGURE_ALERTS, alertConfigurations);
return new PumpEnactResult(injector).success(true).enacted(false);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
addFailureToHistory(PodHistoryEntryType.CONFIGURE_ALERTS, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
}
public PumpEnactResult getPodStatus() {
try {
StatusResponse statusResponse = delegate.getPodStatus();
@ -244,27 +260,33 @@ public class AapsOmnipodManager {
} catch (CommandFailedAfterChangingDeliveryStatusException ex) {
createSuspendedFakeTbrIfNotExists();
String comment = getStringResource(R.string.omnipod_error_set_basal_failed_delivery_suspended);
showNotification(comment, Notification.URGENT, R.raw.boluserror);
showNotification(Notification.FAILED_UDPATE_PROFILE, comment, Notification.URGENT, R.raw.boluserror);
addFailureToHistory(historyEntryType, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
} catch (DeliveryStatusVerificationFailedException ex) {
String comment;
if(ex.getExpectedStatus() == DeliveryStatus.SUSPENDED) {
if (ex.getExpectedStatus() == DeliveryStatus.SUSPENDED) {
// Happened when suspending delivery before setting the new profile
comment = getStringResource(R.string.omnipod_error_set_basal_failed_delivery_might_be_suspended);
} else {
// Happened when setting the new profile (after suspending delivery)
comment = getStringResource(R.string.omnipod_error_set_basal_might_have_failed_delivery_might_be_suspended);
}
showNotification(comment, Notification.URGENT, R.raw.boluserror);
showNotification(Notification.FAILED_UDPATE_PROFILE, comment, Notification.URGENT, R.raw.boluserror);
addFailureToHistory(historyEntryType, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
showNotification(Notification.FAILED_UDPATE_PROFILE, comment, Notification.URGENT, R.raw.boluserror);
addFailureToHistory(historyEntryType, comment);
return new PumpEnactResult(injector).success(false).enacted(false).comment(comment);
}
rxBus.send(new EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED));
showNotification(Notification.PROFILE_SET_OK,
resourceHelper.gs(R.string.profile_set_ok),
Notification.INFO, null);
return new PumpEnactResult(injector).success(true).enacted(true);
}
@ -305,7 +327,7 @@ public class AapsOmnipodManager {
if (detailedBolusInfo.isSMB) {
showNotification(getStringResource(R.string.omnipod_bolus_failed_uncertain_smb, detailedBolusInfo.insulin), Notification.URGENT, R.raw.boluserror);
} else {
showErrorDialog(getStringResource(R.string.omnipod_bolus_failed_uncertain), R.raw.boluserror);
showNotification(getStringResource(R.string.omnipod_bolus_failed_uncertain), Notification.URGENT, R.raw.boluserror);
}
}
@ -381,7 +403,7 @@ public class AapsOmnipodManager {
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (PodFaultException ex) {
aapsLogger.debug(LTag.PUMP, "Successfully cancelled bolus (implicitly because of a Pod Fault)");
showPodFaultErrorDialog(ex.getFaultEvent().getFaultEventCode());
showPodFaultNotification(ex.getFaultEvent().getFaultEventCode());
addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.CANCEL_BOLUS, null);
return new PumpEnactResult(injector).success(true).enacted(true);
} catch (Exception ex) {
@ -713,7 +735,7 @@ public class AapsOmnipodManager {
comment = getStringResource(R.string.omnipod_driver_error_not_enough_data);
} else if (ex instanceof PodFaultException) {
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode();
showPodFaultErrorDialog(faultEventCode);
showPodFaultNotification(faultEventCode);
comment = createPodFaultErrorMessage(faultEventCode);
} else if (ex instanceof PodReturnedErrorResponseException) {
comment = getStringResource(R.string.omnipod_driver_error_pod_returned_error_response);
@ -741,26 +763,21 @@ public class AapsOmnipodManager {
rxBus.send(event);
}
private void showPodFaultErrorDialog(FaultEventCode faultEventCode) {
showPodFaultErrorDialog(faultEventCode, R.raw.boluserror);
private void showPodFaultNotification(FaultEventCode faultEventCode) {
showPodFaultNotification(faultEventCode, R.raw.boluserror);
}
private void showPodFaultErrorDialog(FaultEventCode faultEventCode, Integer sound) {
showErrorDialog(createPodFaultErrorMessage(faultEventCode), sound);
}
private void showErrorDialog(String message, Integer sound) {
Intent intent = new Intent(context, ErrorHelperActivity.class);
intent.putExtra("soundid", sound);
intent.putExtra("status", message);
intent.putExtra("title", resourceHelper.gs(R.string.error));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
private void showPodFaultNotification(FaultEventCode faultEventCode, Integer sound) {
showNotification(createPodFaultErrorMessage(faultEventCode), Notification.URGENT, sound);
}
private void showNotification(String message, int urgency, Integer sound) {
showNotification(Notification.OMNIPOD_PUMP_ALARM, message, urgency, sound);
}
private void showNotification(int id, String message, int urgency, Integer sound) {
Notification notification = new Notification( //
Notification.OMNIPOD_PUMP_ALARM, //
id, //
message, //
urgency);
if (sound != null) {

View file

@ -227,6 +227,7 @@ class OmnipodFragment : DaggerFragment() {
omnipod_pod_tid.text = PLACEHOLDER
omnipod_pod_firmware_version.text = PLACEHOLDER
omnipod_pod_expiry.text = PLACEHOLDER
omnipod_pod_expiry.setTextColor(Color.WHITE)
omnipod_base_basal_rate.text = PLACEHOLDER
omnipod_total_delivered.text = PLACEHOLDER
omnipod_reservoir.text = PLACEHOLDER
@ -237,10 +238,16 @@ class OmnipodFragment : DaggerFragment() {
omnipod_pod_tid.text = podStateManager.tid.toString()
omnipod_pod_firmware_version.text = resourceHelper.gs(R.string.omnipod_pod_firmware_version_value, podStateManager.pmVersion.toString(), podStateManager.piVersion.toString())
val expiresAt = podStateManager.expiresAt
omnipod_pod_expiry.text = if (expiresAt == null) {
PLACEHOLDER
if (expiresAt == null) {
omnipod_pod_expiry.text = PLACEHOLDER
omnipod_pod_expiry.setTextColor(Color.WHITE)
} else {
dateUtil.dateAndTimeString(expiresAt.toDate())
omnipod_pod_expiry.text = dateUtil.dateAndTimeString(expiresAt.toDate())
omnipod_pod_expiry.setTextColor(if (DateTime.now().isAfter(expiresAt)) {
Color.RED
} else {
Color.WHITE
})
}
if (podStateManager.hasFaultEvent()) {

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.plugins.pump.omnipod.util;
import org.joda.time.Duration;
import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodStorageKeys;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
@Singleton
public class OmnipodAlertUtil {
private final SP sp;
@Inject
public OmnipodAlertUtil(SP sp) {
this.sp = sp;
}
public Duration getExpirationReminderTimeBeforeShutdown() {
boolean expirationAlertEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.EXPIRATION_REMINDER_ENABLED, true);
return expirationAlertEnabled ? Duration.standardHours(sp.getInt(OmnipodStorageKeys.Preferences.EXPIRATION_REMINDER_HOURS_BEFORE_SHUTDOWN, 9)) : null;
}
public Integer getLowReservoirAlertUnits() {
boolean lowReservoirAlertEnabled = sp.getBoolean(OmnipodStorageKeys.Preferences.LOW_RESERVOIR_ALERT_ENABLED, true);
return lowReservoirAlertEnabled ? sp.getInt(OmnipodStorageKeys.Preferences.LOW_RESERVOIR_ALERT_UNITS, 20) : null;
}
}

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16.495,12.092l-4.921,-4.92l-1.444,1.444l2.468,2.467l-9.765,0l0,2.042l9.765,0l-2.468,2.467l1.444,1.444l4.921,-4.92l-0.012,-0.012z"
android:fillColor="@color/white"/>
<path
android:pathData="M18.682,2.975H5.152c-1.272,0 -2.307,1.035 -2.307,2.307v3.801h2.126V5.282c0,-0.1 0.081,-0.181 0.181,-0.181h13.53c0.1,0 0.181,0.081 0.181,0.181v13.436c0,0.1 -0.081,0.181 -0.181,0.181H5.152c-0.1,0 -0.181,-0.081 -0.181,-0.181v-3.593H2.845v3.593c0,1.272 1.035,2.307 2.307,2.307h13.53c1.272,0 2.308,-1.034 2.308,-2.307V5.282C20.989,4.01 19.954,2.975 18.682,2.975z"
android:fillColor="@color/white"/>
</vector>

View file

@ -4,8 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".plugins.pump.omnipod.dialogs.InitPodWizard">
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
@ -29,7 +28,7 @@
android:layout_gravity="bottom"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:text="@string/exit"
android:text="@string/omnipod_wizard_button_exit"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
android:textStyle="bold" />
</LinearLayout>
@ -75,7 +74,7 @@
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="showPreviousPage"
android:text="@string/previous_button"
android:text="@string/omnipod_wizard_button_previous"
android:textColor="#FFFFFF" />
<View
@ -89,7 +88,7 @@
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="showNextPage"
android:text="@string/next_button"
android:text="@string/omnipod_wizard_button_next"
android:textColor="#FFFFFF" />
<Button
@ -98,7 +97,7 @@
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:onClick="finishSetupWizard"
android:text="@string/setupwizard_finish"
android:text="@string/omnipod_wizard_button_finish"
android:textColor="#FFFFFF" />
</LinearLayout>

View file

@ -42,8 +42,8 @@
android:id="@+id/initAction_textErrorMessage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_marginLeft="15dp"
android:layout_marginRight="5dp"
android:layout_marginStart="15dp"
android:layout_marginEnd="5dp"
android:textSize="15sp"
android:layout_weight="0.3"
style="@style/WizardPagePodContent"
@ -54,8 +54,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:layout_marginLeft="5dp"
android:layout_marginRight="15dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="15dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:drawableTop="@drawable/ic_actions_refill"

View file

@ -41,7 +41,7 @@
<ListView android:id="@+id/podInfoList"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:saveEnabled="false"

View file

@ -20,8 +20,8 @@
android:minHeight="@dimen/list_item_height_small"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingLeft="@dimen/list_item_padding_left"
android:paddingRight="@dimen/list_item_padding_right"
android:paddingStart="@dimen/list_item_padding_left"
android:paddingEnd="@dimen/list_item_padding_right"
android:paddingTop="12dp"
android:paddingBottom="12dp">
@ -33,7 +33,7 @@
android:ellipsize="end"
android:layout_width="100sp"
android:layout_height="wrap_content"
android:layout_marginRight="16dp" />
android:layout_marginEnd="16dp" />
<TextView android:id="@android:id/text2"
style="?android:textAppearanceMedium"

View file

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".plugins.pump.omnipod.dialogs.PodHistoryActivity">
android:paddingBottom="@dimen/activity_vertical_margin">
<LinearLayout
android:id="@+id/omnipod_historytop"
@ -17,28 +15,27 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="20dp"
android:text="Type:"
android:layout_marginStart="5dp"
android:layout_marginEnd="20dp"
android:text="@string/omnipod_history_type"
android:textAppearance="?android:attr/textAppearanceSmall" />
<Spinner
android:id="@+id/omnipod_historytype"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp" />
android:layout_marginEnd="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp"
android:layout_weight="1"
android:background="@drawable/pillborder"
android:gravity="center_horizontal"
android:text="@string/omnipod_cmd_pod_history" />
</LinearLayout>
<TextView

View file

@ -1,33 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="40dp"
android:paddingLeft="20dp">
android:orientation="horizontal"
android:paddingStart="20dp">
<TextView
android:id="@+id/omnipod_history_time"
android:layout_width="88dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="Date"
android:textSize="12dp" />
android:text="@string/omnipod_history_item_date"
android:textSize="12sp" />
<TextView
android:id="@+id/omnipod_history_source"
android:layout_width="132dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="Source"
android:textSize="12dp" />
android:text="@string/omnipod_history_item_source"
android:textSize="12sp" />
<TextView
android:id="@+id/omnipod_history_description"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:text="Description"
android:gravity="center_vertical"
android:textSize="12dp" />
android:text="@string/omnipod_history_item_description"
android:textSize="12sp" />
</LinearLayout>

View file

@ -46,7 +46,7 @@
<TextView
android:id="@+id/initpod_waiting_for_rl_text"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="0dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:layout_marginRight="10dp"

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black_overlay">#66000000</color>
<color name="ribbonWarning">#f4d700</color>
</resources>

View file

@ -5,7 +5,7 @@
<!-- Omnipod - Base -->
<string name="omnipod_name" translatable="false">Omnipod</string>
<string name="omnipod_name_short" translatable="false">POD</string>
<string name="omnipod_name_short" translatable="false">Pod</string>
<string name="description_pump_omnipod">Pump integration for Omnipod, requires RileyLink (with at least 2.0 firmware) device.</string>
<!-- Omnipod Configuration -->
@ -16,6 +16,10 @@
<string name="key_omnipod_suspend_delivery_button_enabled" translatable="false">AAPS.Omnipod.suspend_delivery_button_enabled</string>
<string name="key_omnipod_pulse_log_button_enabled" translatable="false">AAPS.Omnipod.pulse_log_button_enabled</string>
<string name="key_omnipod_time_change_event_enabled" translatable="false">AAPS.Omnipod.time_change_enabled</string>
<string name="key_omnipod_expiration_reminder_enabled" translatable="false">AAPS.Omnipod.expiration_reminder_enabled</string>
<string name="key_omnipod_expiration_reminder_hours_before_shutdown" translatable="false">AAPS.Omnipod.expiration_reminder_hours_before_shutdown</string>
<string name="key_omnipod_low_reservoir_alert_enabled" translatable="false">AAPS.Omnipod.low_reservoir_alert_enabled</string>
<string name="key_omnipod_low_reservoir_alert_units" translatable="false">AAPS.Omnipod.low_reservoir_alert_units</string>
<string name="omnipod_config_bolus_beeps_enabled">Bolus beeps enabled</string>
<string name="omnipod_config_basal_beeps_enabled">Basal beeps enabled</string>
<string name="omnipod_config_smb_beeps_enabled">SMB beeps enabled</string>
@ -23,6 +27,10 @@
<string name="omnipod_config_suspend_delivery_button_enabled">Suspend Delivery button enabled</string>
<string name="omnipod_config_pulse_log_button_enabled">Pulse Log button enabled</string>
<string name="omnipod_config_time_change_enabled">DST/Time zone detection enabled</string>
<string name="omnipod_config_expiration_reminder_enabled">Expiration reminder enabled</string>
<string name="omnipod_config_expiration_reminder_hours_before_shutdown">Hours before shutdown</string>
<string name="omnipod_config_low_reservoir_alert_enabled">Low reservoir alert enabled</string>
<string name="omnipod_config_low_reservoir_alert_units">Number of units</string>
<!-- Omnipod - Fragment -->
<string name="omnipod_moments_ago">Moments ago</string>
@ -169,6 +177,19 @@
<string name="omnipod_cmd_set_fake_suspended_tbr">Set fake temporary basal because the Pod is suspended</string>
<string name="omnipod_cmd_cancel_fake_suspended_tbr">Cancel fake temporary basal that was created because the Pod was suspended</string>
<string name="omnipod_uncertain">uncertain</string>
<string name="omnipod_expiration_alerts_updated">Alert configuration updated in Pod</string>
<string name="omnipod_preference_category_rileylink">RileyLink</string>
<string name="omnipod_preference_category_other">Other</string>
<string name="omnipod_preference_category_alerts">Alerts</string>
<string name="omnipod_preference_category_confirmation_beeps">Confirmation beeps</string>
<string name="omnipod_wizard_button_exit">Exit</string>
<string name="omnipod_wizard_button_previous">Previous</string>
<string name="omnipod_wizard_button_next">Next</string>
<string name="omnipod_wizard_button_finish">Finish</string>
<string name="omnipod_history_item_description">Description</string>
<string name="omnipod_history_item_source">Source</string>
<string name="omnipod_history_item_date">Date</string>
<string name="omnipod_history_type">Type:</string>
<plurals name="omnipod_minutes">
<item quantity="one">%1$d minute</item>

View file

@ -4,8 +4,8 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:paddingLeft">20px</item>
<item name="android:paddingRight">20px</item>
<item name="android:paddingLeft">20dp</item>
<item name="android:paddingRight">20dp</item>
<item name="android:textSize">18sp</item>
</style>
@ -14,10 +14,10 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">20dp</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:paddingTop">20px</item>
<item name="android:paddingBottom">20px</item>
<item name="android:paddingLeft">60px</item>
<item name="android:paddingRight">60px</item>
<item name="android:paddingTop">20dp</item>
<item name="android:paddingBottom">20dp</item>
<item name="android:paddingLeft">60dp</item>
<item name="android:paddingRight">60dp</item>
<item name="android:textSize">18sp</item>
</style>

View file

@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:validate="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:title="@string/omnipod_name"
app:initialExpandedChildrenCount="0">
<PreferenceCategory android:title="@string/omnipod_preference_category_rileylink">
<Preference
android:enabled="true"
@ -14,6 +12,10 @@
<intent android:action="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
</Preference>
</PreferenceCategory>
<PreferenceCategory android:title="@string/omnipod_preference_category_confirmation_beeps">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_omnipod_bolus_beeps_enabled"
@ -34,6 +36,46 @@
android:key="@string/key_omnipod_tbr_beeps_enabled"
android:title="@string/omnipod_config_tbr_beeps_enabled" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/omnipod_preference_category_alerts">
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_omnipod_expiration_reminder_enabled"
android:title="@string/omnipod_config_expiration_reminder_enabled" />
<info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreference
android:defaultValue="9"
android:dependency="@string/key_omnipod_expiration_reminder_enabled"
android:digits="0123456789"
android:inputType="number"
android:key="@string/key_omnipod_expiration_reminder_hours_before_shutdown"
android:title="@string/omnipod_config_expiration_reminder_hours_before_shutdown"
validate:maxNumber="24"
validate:minNumber="2"
validate:testType="numericRange" />
<SwitchPreference
android:defaultValue="true"
android:key="@string/key_omnipod_low_reservoir_alert_enabled"
android:title="@string/omnipod_config_low_reservoir_alert_enabled" />
<info.nightscout.androidaps.utils.textValidator.ValidatingEditTextPreference
android:defaultValue="20"
android:dependency="@string/key_omnipod_low_reservoir_alert_enabled"
android:digits="0123456789"
android:inputType="number"
android:key="@string/key_omnipod_low_reservoir_alert_units"
android:title="@string/omnipod_config_low_reservoir_alert_units"
validate:maxNumber="50"
validate:minNumber="5"
validate:testType="numericRange" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/omnipod_preference_category_other">
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_omnipod_suspend_delivery_button_enabled"
@ -50,4 +92,5 @@
android:title="@string/omnipod_config_time_change_enabled" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>