Merge pull request #32 from jotomo/pump-basal-rate-sanity-and-german-translation

Pump basal rate sanity and german translation
This commit is contained in:
Johannes Mockenhaupt 2017-12-27 12:50:40 +01:00 committed by GitHub
commit 75cb44339c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 130 additions and 55 deletions

View file

@ -85,6 +85,8 @@ Usage:
- The integration of the Combo with AndroidAPS is designed with the assumption that all inputs are
made via AndroidAPS. Boluses entered on the pump will NOT be detected by AAPS and may therefore
result in too much insulin being delivered.
- The pump's first basal rate profile is read on app start and is updated by AAPS. Manually changing
the pump's basal rate profile will lead to wrong basals being delivered and is NOT supported.
- It's recommended to enable key lock on the pump to prevent bolusing from the pump, esp. when the
pump was used before and quick bolusing was a habit.
Also, with keylock enabled, accidentally pressing a key will NOT interrupt a running command

View file

@ -74,12 +74,19 @@
- [ ] Check displayed data (state, battery, reservoir, temp basal) is the same
as on the pump
- [ ] Unsafe usage
- [ ] An extended or multiwave bolus given within the last six hour must raise an alert and
restrict the loop functionality to low-suspend only (setting maxIOB to zero)
- [ ] An active extended or multiwave bolus must raise an alert and
restrict the loop functionality to low-suspend only for the next 6h (setting maxIOB to zero)
and cancel an active TBR.
- [ ] Closed loop functionality must resume 6 h after the last ext/multiwave bolus
- [ ] An active ext/multiwave bolus must also raise an alert and restrict the loop
- [ ] If a basal rate other than profile 1 is activated, this must also raise an alert and disable
the restrict the loop
- [ ] If a basal rate other than profile 1 is active on start, the pump must refuse to finish
initialization and disable the loop. When setting the profile to 1 and refreshing,
the pump must finish initialization and enable the loop (the overview screen will
still show "closed loop", but the Combo and Loop tabs will say the loop is disabled
due to a constraint violation).
- [ ] When changing profile to one other than the first after AAPS has started and read the first
basal profile, a warning must be shown, the loop must be disabled and the active TBR be cancelled.
- [ ] A request to change the AAPS profil (e.g. increase to 110%) must be rejected if the pump
doesn't have profile one active.
- [ ] Reading/setting basal profile
- [ ] AAPS reads basal rate properly
- [ ] Test profile with 115% (or something like that) change to ask the

View file

@ -41,6 +41,7 @@ import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
@ -138,7 +139,9 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
String getStateSummary() {
PumpState ps = pump.state;
if (ps.activeAlert != null) {
if (!validBasalRateProfileSelectedOnPump) {
return MainApp.sResources.getString(R.string.loopdisabled);
} else if (ps.activeAlert != null) {
return ps.activeAlert.errorCode != null
? "E" + ps.activeAlert.errorCode + ": " + ps.activeAlert.message
: "W" + ps.activeAlert.warningCode + ": " + ps.activeAlert.message;
@ -258,6 +261,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
return new PumpEnactResult().success(true).enacted(false);
}
CommandResult stateResult = runCommand(null, 1, ruffyScripter::readPumpState);
if (stateResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
return new PumpEnactResult().success(false).enacted(false).comment(MainApp.sResources.getString(R.string.combo_force_disabled_notification));
}
CommandResult setResult = runCommand(MainApp.sResources.getString(R.string.combo_activity_setting_basal_profile), 2,
() -> ruffyScripter.setBasalProfile(requestedBasalProfile));
if (!setResult.success) {
@ -324,14 +332,18 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
return new Date(pump.lastSuccessfulCmdTime);
}
/**
* Runs pump initializing if needed, checks for boluses given on the pump, updates the
* reservoir level and checks the running TBR on the pump.
*/
/** Runs pump initializing if needed and reads the pump state from the main screen. */
@Override
public synchronized void getPumpStatus() {
log.debug("getPumpStatus called");
if (!pump.initialized) {
initializePump();
} else {
runCommand(MainApp.sResources.getString(R.string.combo_pump_action_refreshing), 1, ruffyScripter::readPumpState);
}
}
private synchronized void initializePump() {
long maxWait = System.currentTimeMillis() + 15 * 1000;
while (!ruffyScripter.isPumpAvailable()) {
log.debug("Waiting for ruffy service to come up ...");
@ -341,31 +353,33 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
return;
}
}
}
CommandResult stateResult = runCommand(pump.initialized ? MainApp.sResources.getString(R.string.combo_pump_action_refreshing) : MainApp.sResources.getString(R.string.combo_pump_action_initializing),
1, ruffyScripter::readPumpState);
CommandResult stateResult = runCommand(MainApp.sResources.getString(R.string.combo_pump_action_initializing),1, ruffyScripter::readPumpState);
if (!stateResult.success) {
return;
}
// read basal profile into cache and update pump profile if needed
if (!pump.initialized) {
if (stateResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
Notification n = new Notification(Notification.COMBO_PUMP_ALARM,
MainApp.sResources.getString(R.string.combo_force_disabled_notification),
Notification.URGENT);
n.soundId = R.raw.alarm;
MainApp.bus().post(new EventNewNotification(n));
return;
}
// read basal profile into cache (KeepAlive will trigger a profile update if needed)
CommandResult readBasalResult = runCommand("Reading basal profile", 2, ruffyScripter::readBasalProfile);
if (!readBasalResult.success) {
return;
}
pump.basalProfile = readBasalResult.basalProfile;
}
if (!pump.initialized) {
validBasalRateProfileSelectedOnPump = true;
pump.initialized = true;
MainApp.bus().post(new EventInitializationChanged());
}
// ComboFragment updates state fully only after the pump has initialized,
// this fetches state again and updates the UI proper
runCommand(null, 0, ruffyScripter::readPumpState);
// ComboFragment updates state fully only after the pump has initialized, so run this manually here
updateLocalData(readBasalResult);
}
private void updateLocalData(CommandResult result) {
@ -716,9 +730,15 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
if (commandResult.success) {
pump.lastSuccessfulCmdTime = System.currentTimeMillis();
if (validBasalRateProfileSelectedOnPump && commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
validBasalRateProfileSelectedOnPump = false;
Notification n = new Notification(Notification.COMBO_PUMP_ALARM,
MainApp.sResources.getString(R.string.combo_force_disabled_notification),
Notification.URGENT);
n.soundId = R.raw.alarm;
MainApp.bus().post(new EventNewNotification(n));
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
}
if (commandResult.success) {
updateLocalData(commandResult);
}
} finally {
@ -760,7 +780,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
notification.date = new Date();
notification.id = Notification.COMBO_PUMP_ALARM;
notification.level = Notification.URGENT;
notification.text = MainApp.sResources.getString(R.string.combo_is_in_error_state);
notification.text = MainApp.sResources.getString(R.string.combo_is_in_error_state, activeAlert.errorCode, activeAlert.message);
MainApp.bus().post(new EventNewNotification(notification));
return preCheckResult.success(false);
}
@ -811,7 +831,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
if (commandResult == null) return;
long lastViolation = 0;
if (commandResult.state.unsafeUsageDetected) {
if (commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BOLUS_TYPE) {
lastViolation = System.currentTimeMillis();
} else if (commandResult.lastBolus != null && !commandResult.lastBolus.isValid) {
lastViolation = commandResult.lastBolus.timestamp;
@ -823,14 +843,15 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
}
}
if (lastViolation > 0) {
lowSuspendOnlyLoopEnforcetTill = lastViolation + 6 * 60 * 60 * 1000;
if (lowSuspendOnlyLoopEnforcetTill > System.currentTimeMillis() && violationWarningRaisedFor != lowSuspendOnlyLoopEnforcetTill) {
lowSuspendOnlyLoopEnforcedUntil = lastViolation + 6 * 60 * 60 * 1000;
if (lowSuspendOnlyLoopEnforcedUntil > System.currentTimeMillis() && violationWarningRaisedForBolusAt != lowSuspendOnlyLoopEnforcedUntil) {
Notification n = new Notification(Notification.COMBO_PUMP_ALARM,
MainApp.sResources.getString(R.string.combo_force_disabled_notification),
MainApp.sResources.getString(R.string.combo_low_suspend_forced_notification),
Notification.URGENT);
n.soundId = R.raw.alarm;
MainApp.bus().post(new EventNewNotification(n));
violationWarningRaisedFor = lowSuspendOnlyLoopEnforcetTill;
violationWarningRaisedForBolusAt = lowSuspendOnlyLoopEnforcedUntil;
ConfigBuilderPlugin.getCommandQueue().cancelTempBasal(true, null);
}
}
}
@ -1058,12 +1079,13 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
}
// Constraints interface
private long lowSuspendOnlyLoopEnforcetTill = 0;
private long violationWarningRaisedFor = 0;
private long lowSuspendOnlyLoopEnforcedUntil = 0;
private long violationWarningRaisedForBolusAt = 0;
private boolean validBasalRateProfileSelectedOnPump = false;
@Override
public boolean isLoopEnabled() {
return true;
return validBasalRateProfileSelectedOnPump;
}
@Override
@ -1103,6 +1125,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
@Override
public Double applyMaxIOBConstraints(Double maxIob) {
return lowSuspendOnlyLoopEnforcetTill < System.currentTimeMillis() ? maxIob : 0;
return lowSuspendOnlyLoopEnforcedUntil < System.currentTimeMillis() ? maxIob : 0;
}
}

View file

@ -300,7 +300,7 @@
<string name="actions_shortname">AKT</string>
<string name="wear_shortname">WEAR</string>
<string name="virtualpump_shortname">VP</string>
<string name="treatments_shortname">TREAT</string>
<string name="treatments_shortname">BEH</string>
<string name="temptargetrange_shortname">TT</string>
<string name="tempbasals_shortname">TB</string>
<string name="smscommunicator_shortname">SMS</string>
@ -695,4 +695,36 @@
<string name="combo_pump_action_cancelling_tbr">TBR wird abgebrochen</string>
<string name="combo_pump_action_setting_tbr">TBR wird gesetzt (%d%% / %d min)</string>
<string name="combo_pump_action_bolusing">Bolus (%.1f E) wird abgegeben</string>
<string name="combo_activity_reading_pump_history">Historik wird gelesen</string>
<string name="combo_activity_setting_basal_profile">Basalratenprofil wird aktualisiert</string>
<string name="combo_error_bolus_recovery_progress">Verbindung wurde unterbrochen, es wird versucht fortzusetzen</string>
<string name="combo_error_bolus_verification_failed">Der abgegebene Bolus konnte nicht bestätigt werden. Bitte prüfen Sie auf der Pumpe ob ein Bolus abgegeben wurde und erstellen Sie einen Eintrag im Careportal Reiter falls nötig.</string>
<string name="combo_error_no_bolus_delivered">Die Bolusabgabe ist fehlgeschlagen, es wurde scheinbar kein Bolus abgegeben. Bitte prüfen Sie auf der Pumpe ob ein Bolus abgegeben wurde. Um dopplte Boli durch Programmfehler zu vermeiden werden Boli nicht automatisch erneut versucht.</string>
<string name="combo_error_partial_bolus_delivered">Wegen eines Fehlers wurden nur %.2f IE von den angeforderten %.2f IE abgegeben. Bitte prüfen Sie den abgegeben Bolus auf der Pumpe.</string>
<string name="combo_history">Historik</string>
<string name="combo_pump_action_refreshing">Status wird aktualisiert</string>
<string name="combo_pump_action_initializing">Die Pumpe wird initialisiert</string>
<string name="combo_pump_connected_now">Jetzt</string>
<string name="combo_pump_never_connected">Nie</string>
<string name="combo_pump_tbr_cancelled_warrning">Ein TBR ABGEBROCHEN Alarm wurde bestätigt</string>
<string name="combo_warning">Warnung</string>
<string name="combo_reservoir_empty">Leer</string>
<string name="combo_reservoir_low">Niedrig</string>
<string name="combo_reservoir_normal">Normal</string>
<string name="combo_tdd_average">Durchschnitt: %3.1f IE</string>
<string name="combo_tdd_maximum">Maximum: %3.1f IE</string>
<string name="combo_tdd_minimum">Minimum: %3.1f IE</string>
<string name="combo_pump_unsupported_operation">Diese Aktion wird von der Pumpe nicht unterstützt</string>
<string name="combo_pump_alerts">Alarme</string>
<string name="combo_pump_battery_low_warrning">Die Batterie in der Pumpe ist fast leer</string>
<string name="combo_pump_cartridge_low_warrning">Das Reservoir in der Pumpe ist fast leer</string>
<string name="combo_is_in_error_state">Die Pumpe zeigt einen Fehler an E%d: %s</string>
<string name="combo_force_disabled_notification">Unsichere Verwendung: die Pumpe hat nicht das erste Basalratenprofil als aktiv gesetzt. Der Loop wird deaktiviert bis dies korrigiert ist.</string>
<string name="combo_low_suspend_forced_notification">Unsichere Verwendung: ein erweiterter- oder Multiwave-Bolus ist aktiv. Der Loop wird für die nächsten 6 Stunden kein zusätzliches Insulin abgeben.</string>
<string name="combo_no_alert_data_note">Um die Fehlerhistorik der Pumpe zu lesen, drücken Sie den ALARME Knopf lange.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst ein Konpf gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden.</string>
<string name="combo_notification_check_time_date">Bitte aktualisieren Sie die Uhr auf der Pumpe</string>
<string name="combo_no_tdd_data_note">Um die TDD-Statistik der Pumpe zu lesen, drücken Sie den TDDS Knopf lange.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst ein Konpf gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden.</string>
<string name="combo_read_full_history_confirmation">Sind Sie sich sicher, dass Sie diese Aktion ausführen möchen und verstehen Sie die Konsequenzen die sich daraus ergeben?</string>
<string name="combo_read_full_history_warning">Diese Aktion wird die gesamte Historik und die Basalrate aus der Pumpe auslesen. Boli und temporäre Basalrate werden zu den Behandlungen hinzugefügt wenn diese noch nicht vorhanden sind. Dies kann zu doppelten Einträge und somit zu falschen IOB-Werten führen, da die Uhr der Pumpe ungenau ist. Diese Aktion sollte NIE durchgeführt werden wenn die Pumpe im Loop verwendet wird. Wenn Sie diese Aktion trotzdem durchführen möchten, drücken Sie lange erneut auf den diesen Knopf.\nWARNUNG: Es gibt einen bekannten Fehler in der Pumpe der dazu führt, dass die Pumpe nach dieser Aktion erst wieder Verbindungen annimmt, wenn auf der Pumpe selbst ein Konpf gedrückt wird. Aus diesem Grund sollte diese Aktion nicht durchgeführt werden.</string>
<string name="urgent_alarm">Dringender Alarm</string>
</resources>

View file

@ -799,7 +799,6 @@
<string name="combo_pump_state_label">State</string>
<string name="combo_pump_activity_label">Activity</string>
<string name="combo_no_pump_connection">No connection for %d min</string>
<string name="combo_last_connection_time">%s</string>
<string name="combo_tbr_remaining">%d%% (%d min remaining)</string>
<string name="combo_last_bolus">%.1f U (%s, %s)</string>
<string name="combo_pump_action_initializing">Initializing</string>
@ -807,7 +806,6 @@
<string name="combo_pump_state_suspended_due_to_error">Suspended due to error</string>
<string name="combo_pump_state_suspended_by_user">Suspended by user</string>
<string name="combo_pump_state_running">Running</string>
<string name="combo_pump_action_checking_history">Checking pump history</string>
<string name="combo_pump_action_cancelling_tbr">Cancelling TBR</string>
<string name="combo_pump_action_setting_tbr">Setting TBR (%d%% / %d min)</string>
<string name="combo_pump_action_bolusing">Bolusing (%.1f U)</string>
@ -816,7 +814,8 @@
<string name="raise_urgent_alarms_as_android_notification">Use system notifications for alerts</string>
<string name="combo_pump_never_connected">Never</string>
<string name="combo_pump_unsupported_operation">Requested operation not supported by pump</string>
<string name="combo_force_disabled_notification">Unsafe usage: extended or multiwave boluses have been delivered within the last 6 hours or the selected basal rate is not 1. Loop mode has been set to low-suspend only until 6 hours after the last unsupported bolus or basal rate profile. Only normal boluses are supported in loop mode with basal rate profile 1.</string>
<string name="combo_low_suspend_forced_notification">Unsafe usage: extended or multiwave boluses are active. Loop mode has been set to low-suspend only 6 hours. Only normal boluses are supported in loop mode</string>
<string name="combo_force_disabled_notification">Unsafe usage: the pump uses a different basal rate profile than the first. The loop has been disabled. Select the first profile on the pump and refresh.</string>
<string name="bolus_frequency_exceeded">A bolus with the same amount was requested within the last minute. To prevent accidental double boluses and to guard against bugs this is disallowed.</string>
<string name="combo_pump_connected_now">Now</string>
<string name="combo_activity_reading_pump_history">Reading pump history</string>
@ -825,7 +824,7 @@
<string name="combo_activity_setting_basal_profile">Setting basal profile</string>
<string name="combo_pump_cartridge_low_warrning">Pump cartridge level is low</string>
<string name="combo_pump_battery_low_warrning">Pump battery is low</string>
<string name="combo_is_in_error_state">Pump is in an error state, please check the pump</string>
<string name="combo_is_in_error_state">The pump is showing the error E%d: %s</string>
<string name="combo_no_alert_data_note">To read the pump\'s error history, long press the ALERTS button\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided.</string>
<string name="combo_no_tdd_data_note">To read the pump\'s TDD history, long press the TDDS button\n\nWARNING: this can trigger a bug which causes the pump to reject all connection attempts and requires pressing a button on the pump to recover and should therefore be avoided.</string>
<string name="key_sync_profile_to_pump">sync_profile_to_pump</string>
@ -843,7 +842,6 @@
<string name="combo_pump_tbr_cancelled_warrning">TBR CANCELLED warning was confirmed</string>
<string name="combo_error_no_bolus_delivered">Bolus delivery failed. It appears no bolus was delivered. To be sure, please check the pump to avoid a double bolus and then bolus again. To guard against bugs, boluses are not automatically retried.</string>
<string name="combo_error_partial_bolus_delivered">Only %.2f U of the requested bolus of %.2f U was delivered due to an error. Please check the pump to verify this and take appropriate actions.</string>
<string name="combo_activity_verifying_delivered_bolus">Verifying delivered bolus</string>
<string name="combo_error_bolus_verification_failed">Delivering the bolus and verifying the pump\'s history failed, please check the pump and manually create a bolus record using the Careportal tab if a bolus was delivered.</string>
<string name="combo_error_bolus_recovery_progress">Recovering from connection loss</string>
</resources>

View file

@ -30,8 +30,12 @@ public class PumpState {
public int insulinState = UNKNOWN;
public int activeBasalProfileNumber;
public static final int SAFE_USAGE = 0;
public static final int UNSUPPORTED_BOLUS_TYPE = 1;
public static final int UNSUPPORTED_BASAL_RATE_PROFILE = 2;
/** True if use of an extended or multiwave bolus has been detected */
public boolean unsafeUsageDetected;
public int unsafeUsageDetected = SAFE_USAGE;
public PumpState menu(String menu) {
this.menu = menu;

View file

@ -501,8 +501,10 @@ public class RuffyScripter implements RuffyCommands {
BolusType bolusType = (BolusType) menu.getAttribute(MenuAttribute.BOLUS_TYPE);
Integer activeBasalRate = (Integer) menu.getAttribute(MenuAttribute.BASAL_SELECTED);
if (bolusType != null && bolusType != BolusType.NORMAL || !activeBasalRate.equals(1)) {
state.unsafeUsageDetected = true;
if (!activeBasalRate.equals(1)) {
state.unsafeUsageDetected = PumpState.UNSUPPORTED_BASAL_RATE_PROFILE;
} else if (bolusType != null && bolusType != BolusType.NORMAL) {
state.unsafeUsageDetected = PumpState.UNSUPPORTED_BOLUS_TYPE;
} else if (tbrPercentage != null && tbrPercentage != 100) {
state.tbrActive = true;
Double displayedTbr = (Double) menu.getAttribute(MenuAttribute.TBR);

View file

@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory;
import java.util.Arrays;
import de.jotomo.ruffy.spi.BasalProfile;
import de.jotomo.ruffy.spi.PumpState;
public class ReadBasalProfileCommand extends BaseCommand {
private static final Logger log = LoggerFactory.getLogger(ReadBasalProfileCommand.class);
@ -17,6 +18,9 @@ public class ReadBasalProfileCommand extends BaseCommand {
@Override
public void execute() {
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
if (scripter.readPumpStateInternal().unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
throw new CommandException("Active basal rate profile != 1");
}
scripter.navigateToMenu(MenuType.BASAL_1_MENU);
scripter.verifyMenuIsDisplayed(MenuType.BASAL_1_MENU);
scripter.pressCheckKey();

View file

@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List;
import de.jotomo.ruffy.spi.BasalProfile;
import de.jotomo.ruffy.spi.PumpState;
public class SetBasalProfileCommand extends BaseCommand {
private static final Logger log = LoggerFactory.getLogger(SetBasalProfileCommand.class);
@ -26,6 +27,9 @@ public class SetBasalProfileCommand extends BaseCommand {
@Override
public void execute() {
scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU);
if (scripter.readPumpStateInternal().unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
throw new CommandException("Active basal rate profile != 1");
}
scripter.navigateToMenu(MenuType.BASAL_1_MENU);
scripter.verifyMenuIsDisplayed(MenuType.BASAL_1_MENU);
scripter.pressCheckKey();