AndroidAPS/danar/src/main/java/info/nightscout/androidaps/danaRv2/DanaRv2Plugin.java

411 lines
18 KiB
Java
Raw Normal View History

2020-05-10 11:03:19 +02:00
package info.nightscout.androidaps.danaRv2;
2017-04-30 21:08:00 +02:00
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
2019-12-30 00:53:44 +01:00
import androidx.annotation.NonNull;
import javax.inject.Inject;
import javax.inject.Singleton;
2020-03-08 22:42:36 +01:00
import dagger.android.HasAndroidInjector;
2020-05-11 16:58:59 +02:00
import info.nightscout.androidaps.dana.DanaPump;
2020-05-10 11:03:19 +02:00
import info.nightscout.androidaps.danaRv2.services.DanaRv2ExecutionService;
import info.nightscout.androidaps.danar.AbstractDanaRPlugin;
import info.nightscout.androidaps.danar.R;
2017-05-29 21:45:59 +02:00
import info.nightscout.androidaps.data.DetailedBolusInfo;
2018-03-20 22:09:22 +01:00
import info.nightscout.androidaps.data.Profile;
2017-04-30 21:08:00 +02:00
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TemporaryBasal;
2020-05-10 11:03:19 +02:00
import info.nightscout.androidaps.db.Treatment;
2017-04-30 21:08:00 +02:00
import info.nightscout.androidaps.events.EventAppExit;
2020-05-10 11:03:19 +02:00
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
2020-01-10 23:14:58 +01:00
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
2018-03-20 22:09:22 +01:00
import info.nightscout.androidaps.interfaces.Constraint;
2019-12-30 00:53:44 +01:00
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
2019-12-27 19:20:38 +01:00
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage;
2019-02-26 20:38:27 +01:00
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.utils.DateUtil;
2019-10-14 23:16:51 +02:00
import info.nightscout.androidaps.utils.FabricPrivacy;
2019-02-26 20:38:27 +01:00
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.T;
2019-12-30 00:53:44 +01:00
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
2019-10-14 23:16:51 +02:00
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
2017-04-30 21:08:00 +02:00
2019-12-30 00:53:44 +01:00
@Singleton
2018-01-29 11:24:03 +01:00
public class DanaRv2Plugin extends AbstractDanaRPlugin {
2019-10-14 23:16:51 +02:00
private CompositeDisposable disposable = new CompositeDisposable();
2017-04-30 21:08:00 +02:00
2019-12-30 00:53:44 +01:00
private final AAPSLogger aapsLogger;
2020-03-15 18:18:32 +01:00
private final Context context;
2019-12-30 00:53:44 +01:00
private final ResourceHelper resourceHelper;
private final ConstraintChecker constraintChecker;
2020-03-11 23:33:05 +01:00
private final DetailedBolusInfoStorage detailedBolusInfoStorage;
2020-05-10 11:03:19 +02:00
private final FabricPrivacy fabricPrivacy;
2020-03-11 23:33:05 +01:00
public long lastEventTimeLoaded = 0;
public boolean eventsLoadingDone = false;
2019-12-30 00:53:44 +01:00
@Inject
public DanaRv2Plugin(
2020-03-08 22:42:36 +01:00
HasAndroidInjector injector,
2019-12-30 00:53:44 +01:00
AAPSLogger aapsLogger,
RxBusWrapper rxBus,
2020-03-15 18:18:32 +01:00
Context context,
2020-05-11 16:58:59 +02:00
DanaPump danaPump,
2019-12-30 00:53:44 +01:00
ResourceHelper resourceHelper,
ConstraintChecker constraintChecker,
2020-05-10 11:03:19 +02:00
ActivePluginProvider activePlugin,
2020-01-10 23:14:58 +01:00
SP sp,
2020-03-11 23:33:05 +01:00
CommandQueueProvider commandQueue,
2020-05-07 23:40:59 +02:00
DetailedBolusInfoStorage detailedBolusInfoStorage,
2020-05-10 11:03:19 +02:00
DateUtil dateUtil,
FabricPrivacy fabricPrivacy
2019-12-30 00:53:44 +01:00
) {
2020-05-11 16:58:59 +02:00
super(injector, danaPump, resourceHelper, constraintChecker, aapsLogger, commandQueue, rxBus, activePlugin, sp, dateUtil);
2019-12-30 00:53:44 +01:00
this.aapsLogger = aapsLogger;
2020-03-15 18:18:32 +01:00
this.context = context;
2019-12-30 00:53:44 +01:00
this.resourceHelper = resourceHelper;
this.constraintChecker = constraintChecker;
2020-03-11 23:33:05 +01:00
this.detailedBolusInfoStorage = detailedBolusInfoStorage;
2020-05-10 11:03:19 +02:00
this.fabricPrivacy = fabricPrivacy;
getPluginDescription().description(R.string.description_pump_dana_r_v2);
2018-06-26 12:53:43 +02:00
2018-01-29 11:24:03 +01:00
useExtendedBoluses = false;
2018-09-01 11:45:29 +02:00
pumpDescription.setPumpDescription(PumpType.DanaRv2);
2017-04-30 21:08:00 +02:00
}
2018-03-31 10:36:57 +02:00
@Override
protected void onStart() {
2020-03-15 18:18:32 +01:00
Intent intent = new Intent(context, DanaRv2ExecutionService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
2018-03-31 10:36:57 +02:00
2019-12-30 00:53:44 +01:00
disposable.add(rxBus
2019-10-14 23:16:51 +02:00
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
2020-05-10 11:03:19 +02:00
.subscribe(event -> context.unbindService(mConnection), fabricPrivacy::logException)
2019-10-14 23:16:51 +02:00
);
super.onStart();
2018-03-31 10:36:57 +02:00
}
@Override
protected void onStop() {
2020-03-15 18:18:32 +01:00
context.unbindService(mConnection);
2018-03-31 10:36:57 +02:00
2019-10-14 23:16:51 +02:00
disposable.clear();
2019-08-24 10:56:36 +02:00
super.onStop();
2018-03-31 10:36:57 +02:00
}
private ServiceConnection mConnection = new ServiceConnection() {
2017-04-30 21:08:00 +02:00
public void onServiceDisconnected(ComponentName name) {
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "Service is disconnected");
2017-04-30 21:08:00 +02:00
sExecutionService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "Service is connected");
2017-04-30 21:08:00 +02:00
DanaRv2ExecutionService.LocalBinder mLocalBinder = (DanaRv2ExecutionService.LocalBinder) service;
sExecutionService = mLocalBinder.getServiceInstance();
}
};
// Plugin base interface
2019-12-30 00:53:44 +01:00
@NonNull
2017-04-30 21:08:00 +02:00
@Override
public String getName() {
2019-12-30 00:53:44 +01:00
return resourceHelper.gs(R.string.danarv2pump);
2017-04-30 21:08:00 +02:00
}
2017-11-01 20:43:59 +01:00
@Override
public int getPreferencesId() {
return R.xml.pref_danarv2;
}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return false;
2017-05-12 17:30:52 +02:00
}
2017-04-30 21:08:00 +02:00
@Override
public boolean isInitialized() {
2020-05-11 16:58:59 +02:00
return danaPump.getLastConnection() > 0 && danaPump.getMaxBasal() > 0 && danaPump.isPasswordOK();
2017-04-30 21:08:00 +02:00
}
@Override
public boolean isHandshakeInProgress() {
return sExecutionService != null && sExecutionService.isHandshakeInProgress();
}
@Override
public void finishHandshaking() {
sExecutionService.finishHandshaking();
}
2017-04-30 21:08:00 +02:00
// Pump interface
2020-01-10 23:14:58 +01:00
@NonNull @Override
2017-05-29 21:45:59 +02:00
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
2019-12-30 00:53:44 +01:00
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
2017-05-29 21:45:59 +02:00
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
// v2 stores end time for bolus, we need to adjust time
// default delivery speed is 12 sec/U
2019-12-30 00:53:44 +01:00
int preferencesSpeed = sp.getInt(R.string.key_danars_bolusspeed, 0);
2017-10-10 19:14:43 +02:00
int speed = 12;
switch (preferencesSpeed) {
case 0:
speed = 12;
break;
case 1:
speed = 30;
break;
case 2:
speed = 60;
break;
}
detailedBolusInfo.date = DateUtil.now() + (long) (speed * detailedBolusInfo.insulin * 1000);
// clean carbs to prevent counting them as twice because they will picked up as another record
// I don't think it's necessary to copy DetailedBolusInfo right now for carbs records
double carbs = detailedBolusInfo.carbs;
detailedBolusInfo.carbs = 0;
int carbTime = detailedBolusInfo.carbTime;
2018-07-15 19:48:33 +02:00
if (carbTime == 0) carbTime--; // better set 1 man back to prevent clash with insulin
detailedBolusInfo.carbTime = 0;
2020-03-11 23:33:05 +01:00
detailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
Treatment t = new Treatment();
2018-02-14 14:39:14 +01:00
t.isSMB = detailedBolusInfo.isSMB;
2017-04-30 21:08:00 +02:00
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0)
2018-07-15 19:48:33 +02:00
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t);
2020-03-09 00:28:51 +01:00
PumpEnactResult result = new PumpEnactResult(getInjector());
2018-05-02 22:20:27 +02:00
result.success = connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep;
2017-04-30 21:08:00 +02:00
result.bolusDelivered = t.insulin;
2017-05-29 21:45:59 +02:00
result.carbsDelivered = detailedBolusInfo.carbs;
if (!result.success)
2020-05-11 16:58:59 +02:00
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, danaPump.getBolusStartErrorCode());
else
2020-05-10 11:03:19 +02:00
result.comment = resourceHelper.gs(R.string.ok);
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
// remove carbs because it's get from history separately
2017-04-30 21:08:00 +02:00
return result;
} else {
2020-03-09 00:28:51 +01:00
PumpEnactResult result = new PumpEnactResult(getInjector());
2017-04-30 21:08:00 +02:00
result.success = false;
result.bolusDelivered = 0d;
2017-05-29 21:45:59 +02:00
result.carbsDelivered = 0d;
2020-05-08 14:59:30 +02:00
result.comment = resourceHelper.gs(R.string.invalidinput);
2019-12-30 00:53:44 +01:00
aapsLogger.error("deliverTreatment: Invalid input");
2017-04-30 21:08:00 +02:00
return result;
}
}
@Override
public void stopBolusDelivering() {
if (sExecutionService == null) {
2019-12-30 00:53:44 +01:00
aapsLogger.error("stopBolusDelivering sExecutionService is null");
2017-04-30 21:08:00 +02:00
return;
}
sExecutionService.bolusStop();
}
// This is called from APS
2020-01-10 23:14:58 +01:00
@NonNull @Override
2018-03-20 22:09:22 +01:00
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
2017-04-30 21:08:00 +02:00
// Recheck pump status if older than 30 min
2017-11-22 22:09:58 +01:00
//This should not be needed while using queue because connection should be done before calling this
//if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) {
// connect("setTempBasalAbsolute old data");
//}
2017-04-30 21:08:00 +02:00
2020-03-09 00:28:51 +01:00
PumpEnactResult result = new PumpEnactResult(getInjector());
2017-04-30 21:08:00 +02:00
2019-12-30 00:53:44 +01:00
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
2017-04-30 21:08:00 +02:00
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
final boolean doHighTemp = absoluteRate > getBaseBasalRate();
if (doTempOff) {
// If temp in progress
2020-05-10 11:03:19 +02:00
if (activePlugin.getActiveTreatments().isTempBasalInProgress()) {
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)");
return cancelTempBasal(false);
2017-04-30 21:08:00 +02:00
}
result.success = true;
result.enacted = false;
result.percent = 100;
result.isPercent = true;
result.isTempCancel = true;
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: doTempOff OK");
2017-04-30 21:08:00 +02:00
return result;
}
if (doLowTemp || doHighTemp) {
Integer percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue();
else percentRate = Round.floorTo((double) percentRate, 10d).intValue();
2017-05-30 22:44:26 +02:00
if (percentRate > 500) // Special high temp 500/15min
percentRate = 500;
2017-04-30 21:08:00 +02:00
// Check if some temp is already in progress
2020-05-10 11:03:19 +02:00
TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
2017-04-30 21:08:00 +02:00
// Correct basal already set ?
if (activeTemp.percentRate == percentRate && activeTemp.getPlannedRemainingMinutes() > 4) {
if (!enforceNew) {
result.success = true;
result.percent = percentRate;
result.enacted = false;
result.duration = activeTemp.getPlannedRemainingMinutes();
result.isPercent = true;
result.isTempCancel = false;
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)");
return result;
}
}
}
2017-04-30 21:08:00 +02:00
// Convert duration from minutes to hours
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
2018-06-28 10:30:45 +02:00
if (percentRate == 0 && durationInMinutes > 30) {
2019-07-28 01:22:00 +02:00
result = setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew);
2018-06-28 10:30:45 +02:00
} else {
// use special APS temp basal call ... 100+/15min .... 100-/30min
2020-03-18 16:41:08 +01:00
result = setHighTempBasalPercent(percentRate, durationInMinutes);
2018-06-28 10:30:45 +02:00
}
2017-06-01 20:52:38 +02:00
if (!result.success) {
2019-12-30 00:53:44 +01:00
aapsLogger.error("setTempBasalAbsolute: Failed to set hightemp basal");
2017-06-01 20:52:38 +02:00
return result;
}
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: hightemp basal set ok");
2017-06-01 20:52:38 +02:00
return result;
2017-04-30 21:08:00 +02:00
}
// We should never end here
2019-12-30 00:53:44 +01:00
aapsLogger.error("setTempBasalAbsolute: Internal error");
2017-04-30 21:08:00 +02:00
result.success = false;
result.comment = "Internal error";
return result;
}
2020-01-10 23:14:58 +01:00
@NonNull @Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
2020-05-11 16:58:59 +02:00
DanaPump pump = danaPump;
2020-03-09 00:28:51 +01:00
PumpEnactResult result = new PumpEnactResult(getInjector());
2019-12-30 00:53:44 +01:00
percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
2017-04-30 21:08:00 +02:00
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;
result.success = false;
2020-05-08 14:59:30 +02:00
result.comment = resourceHelper.gs(R.string.invalidinput);
2019-12-30 00:53:44 +01:00
aapsLogger.error("setTempBasalPercent: Invalid input");
2017-04-30 21:08:00 +02:00
return result;
}
2017-05-30 18:10:05 +02:00
if (percent > getPumpDescription().maxTempPercent)
percent = getPumpDescription().maxTempPercent;
long now = System.currentTimeMillis();
2020-05-10 11:03:19 +02:00
TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(now);
if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) {
2017-04-30 21:08:00 +02:00
result.enacted = false;
result.success = true;
result.isTempCancel = false;
2020-05-10 11:03:19 +02:00
result.comment = resourceHelper.gs(R.string.ok);
2020-01-12 23:43:44 +01:00
result.duration = pump.getTempBasalRemainingMin();
result.percent = pump.getTempBasalPercent();
2017-04-30 21:08:00 +02:00
result.isPercent = true;
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalPercent: Correct value already set");
2017-04-30 21:08:00 +02:00
return result;
}
2018-03-01 23:59:44 +01:00
boolean connectionOK;
if (durationInMinutes == 15 || durationInMinutes == 30) {
connectionOK = sExecutionService.tempBasalShortDuration(percent, durationInMinutes);
} else {
int durationInHours = Math.max(durationInMinutes / 60, 1);
connectionOK = sExecutionService.tempBasal(percent, durationInHours);
}
2020-01-12 23:43:44 +01:00
if (connectionOK && pump.isTempBasalInProgress() && pump.getTempBasalPercent() == percent) {
2017-04-30 21:08:00 +02:00
result.enacted = true;
result.success = true;
2020-05-10 11:03:19 +02:00
result.comment = resourceHelper.gs(R.string.ok);
2017-04-30 21:08:00 +02:00
result.isTempCancel = false;
2020-01-12 23:43:44 +01:00
result.duration = pump.getTempBasalRemainingMin();
result.percent = pump.getTempBasalPercent();
2017-04-30 21:08:00 +02:00
result.isPercent = true;
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setTempBasalPercent: OK");
2017-04-30 21:08:00 +02:00
return result;
}
result.enacted = false;
result.success = false;
2019-12-30 00:53:44 +01:00
result.comment = resourceHelper.gs(R.string.tempbasaldeliveryerror);
aapsLogger.error("setTempBasalPercent: Failed to set temp basal");
2017-04-30 21:08:00 +02:00
return result;
}
2020-03-18 16:41:08 +01:00
private PumpEnactResult setHighTempBasalPercent(Integer percent, int durationInMinutes) {
2020-05-11 16:58:59 +02:00
DanaPump pump = danaPump;
2020-03-09 00:28:51 +01:00
PumpEnactResult result = new PumpEnactResult(getInjector());
2020-03-18 16:41:08 +01:00
boolean connectionOK = sExecutionService.highTempBasal(percent, durationInMinutes);
2020-01-12 23:43:44 +01:00
if (connectionOK && pump.isTempBasalInProgress() && pump.getTempBasalPercent() == percent) {
2017-05-09 10:46:04 +02:00
result.enacted = true;
result.success = true;
2020-05-10 11:03:19 +02:00
result.comment = resourceHelper.gs(R.string.ok);
2017-05-09 10:46:04 +02:00
result.isTempCancel = false;
2020-01-12 23:43:44 +01:00
result.duration = pump.getTempBasalRemainingMin();
result.percent = pump.getTempBasalPercent();
2017-05-09 10:46:04 +02:00
result.isPercent = true;
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "setHighTempBasalPercent: OK");
2017-05-09 10:46:04 +02:00
return result;
}
result.enacted = false;
result.success = false;
2019-12-30 00:53:44 +01:00
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
aapsLogger.error("setHighTempBasalPercent: Failed to set temp basal");
2017-05-09 10:46:04 +02:00
return result;
}
2020-01-10 23:14:58 +01:00
@NonNull @Override
public PumpEnactResult cancelTempBasal(boolean force) {
2020-03-09 00:28:51 +01:00
PumpEnactResult result = new PumpEnactResult(getInjector());
2020-05-10 11:03:19 +02:00
TemporaryBasal runningTB = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis());
2017-09-25 19:34:49 +02:00
if (runningTB != null) {
2017-04-30 21:08:00 +02:00
sExecutionService.tempBasalStop();
result.enacted = true;
result.isTempCancel = true;
}
2020-05-11 16:58:59 +02:00
if (!danaPump.isTempBasalInProgress()) {
2017-04-30 21:08:00 +02:00
result.success = true;
result.isTempCancel = true;
2020-05-10 11:03:19 +02:00
result.comment = resourceHelper.gs(R.string.ok);
2019-12-30 00:53:44 +01:00
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");
2017-04-30 21:08:00 +02:00
return result;
} else {
result.success = false;
2019-12-30 00:53:44 +01:00
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
2017-04-30 21:08:00 +02:00
result.isTempCancel = true;
2019-12-30 00:53:44 +01:00
aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal");
2017-04-30 21:08:00 +02:00
return result;
}
}
2020-01-10 23:14:58 +01:00
@NonNull @Override
public PumpType model() {
return PumpType.DanaRv2;
2019-06-08 22:39:26 +02:00
}
2017-11-22 22:09:58 +01:00
@Override
public PumpEnactResult loadEvents() {
return sExecutionService.loadEvents();
}
@Override
2018-06-12 10:03:23 +02:00
public PumpEnactResult setUserOptions() {
2018-06-12 23:43:04 +02:00
return sExecutionService.setUserOptions();
}
2017-04-30 21:08:00 +02:00
}