DanaRKoreanPlugin -> kt
This commit is contained in:
parent
d898a374e6
commit
2b58bc8306
2 changed files with 304 additions and 375 deletions
|
@ -1,375 +0,0 @@
|
||||||
package info.nightscout.androidaps.danaRKorean;
|
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.os.IBinder;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import dagger.android.HasAndroidInjector;
|
|
||||||
import info.nightscout.androidaps.dana.DanaPump;
|
|
||||||
import info.nightscout.androidaps.danaRKorean.services.DanaRKoreanExecutionService;
|
|
||||||
import info.nightscout.androidaps.danar.AbstractDanaRPlugin;
|
|
||||||
import info.nightscout.androidaps.danar.R;
|
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo;
|
|
||||||
import info.nightscout.androidaps.data.Profile;
|
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
|
||||||
import info.nightscout.androidaps.events.EventAppExit;
|
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
|
||||||
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
|
|
||||||
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
|
|
||||||
import info.nightscout.androidaps.interfaces.Constraint;
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginType;
|
|
||||||
import info.nightscout.androidaps.interfaces.PumpSync;
|
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger;
|
|
||||||
import info.nightscout.androidaps.logging.LTag;
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
|
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil;
|
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
|
||||||
import info.nightscout.androidaps.utils.Round;
|
|
||||||
import info.nightscout.androidaps.utils.T;
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
|
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
|
|
||||||
private final CompositeDisposable disposable = new CompositeDisposable();
|
|
||||||
|
|
||||||
private final AAPSLogger aapsLogger;
|
|
||||||
private final Context context;
|
|
||||||
private final ResourceHelper resourceHelper;
|
|
||||||
private final ConstraintChecker constraintChecker;
|
|
||||||
private final FabricPrivacy fabricPrivacy;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public DanaRKoreanPlugin(
|
|
||||||
HasAndroidInjector injector,
|
|
||||||
AAPSLogger aapsLogger,
|
|
||||||
AapsSchedulers aapsSchedulers,
|
|
||||||
RxBusWrapper rxBus,
|
|
||||||
Context context,
|
|
||||||
ResourceHelper resourceHelper,
|
|
||||||
ConstraintChecker constraintChecker,
|
|
||||||
ActivePluginProvider activePlugin,
|
|
||||||
SP sp,
|
|
||||||
CommandQueueProvider commandQueue,
|
|
||||||
DanaPump danaPump,
|
|
||||||
DateUtil dateUtil,
|
|
||||||
FabricPrivacy fabricPrivacy,
|
|
||||||
PumpSync pumpSync
|
|
||||||
) {
|
|
||||||
super(injector, danaPump, resourceHelper, constraintChecker, aapsLogger, aapsSchedulers, commandQueue, rxBus, activePlugin, sp, dateUtil, pumpSync);
|
|
||||||
this.aapsLogger = aapsLogger;
|
|
||||||
this.context = context;
|
|
||||||
this.resourceHelper = resourceHelper;
|
|
||||||
this.constraintChecker = constraintChecker;
|
|
||||||
this.fabricPrivacy = fabricPrivacy;
|
|
||||||
getPluginDescription().description(R.string.description_pump_dana_r_korean);
|
|
||||||
|
|
||||||
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
|
|
||||||
pumpDescription.setPumpDescription(PumpType.DANA_R_KOREAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStart() {
|
|
||||||
Intent intent = new Intent(context, DanaRKoreanExecutionService.class);
|
|
||||||
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventPreferenceChange.class)
|
|
||||||
.observeOn(aapsSchedulers.getIo())
|
|
||||||
.subscribe(event -> {
|
|
||||||
if (isEnabled(PluginType.PUMP)) {
|
|
||||||
boolean previousValue = useExtendedBoluses;
|
|
||||||
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false);
|
|
||||||
|
|
||||||
if (useExtendedBoluses != previousValue && pumpSync.expectedPumpState().getExtendedBolus() != null) {
|
|
||||||
sExecutionService.extendedBolusStop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
);
|
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventAppExit.class)
|
|
||||||
.observeOn(aapsSchedulers.getIo())
|
|
||||||
.subscribe(event -> context.unbindService(mConnection), fabricPrivacy::logException)
|
|
||||||
);
|
|
||||||
super.onStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStop() {
|
|
||||||
context.unbindService(mConnection);
|
|
||||||
|
|
||||||
disposable.clear();
|
|
||||||
super.onStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName name) {
|
|
||||||
aapsLogger.debug(LTag.PUMP, "Service is disconnected");
|
|
||||||
sExecutionService = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
|
||||||
aapsLogger.debug(LTag.PUMP, "Service is connected");
|
|
||||||
DanaRKoreanExecutionService.LocalBinder mLocalBinder = (DanaRKoreanExecutionService.LocalBinder) service;
|
|
||||||
sExecutionService = mLocalBinder.getServiceInstance();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Plugin base interface
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return resourceHelper.gs(R.string.danarkoreanpump);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPreferencesId() {
|
|
||||||
return R.xml.pref_danarkorean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pump interface
|
|
||||||
@Override
|
|
||||||
public boolean isFakingTempsByExtendedBoluses() {
|
|
||||||
return useExtendedBoluses;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInitialized() {
|
|
||||||
return danaPump.getLastConnection() > 0 && danaPump.getMaxBasal() > 0 && !danaPump.isConfigUD() && !danaPump.isEasyModeEnabled() && danaPump.isExtendedBolusEnabled() && danaPump.isPasswordOK();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isHandshakeInProgress() {
|
|
||||||
return sExecutionService != null && sExecutionService.isHandshakeInProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finishHandshaking() {
|
|
||||||
sExecutionService.finishHandshaking();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
|
|
||||||
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
|
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
|
|
||||||
EventOverviewBolusProgress.Treatment t = new EventOverviewBolusProgress.Treatment(0, 0, detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB);
|
|
||||||
boolean connectionOK = false;
|
|
||||||
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0)
|
|
||||||
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, (int) detailedBolusInfo.carbs, detailedBolusInfo.carbTime, t);
|
|
||||||
PumpEnactResult result = new PumpEnactResult(getInjector());
|
|
||||||
result.success(connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.getBolusStep())
|
|
||||||
.bolusDelivered(t.insulin)
|
|
||||||
.carbsDelivered(detailedBolusInfo.carbs);
|
|
||||||
if (!result.getSuccess())
|
|
||||||
result.comment(resourceHelper.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, t.insulin, danaPump.getBolusStartErrorCode()));
|
|
||||||
else
|
|
||||||
result.comment(R.string.ok);
|
|
||||||
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.getBolusDelivered());
|
|
||||||
detailedBolusInfo.insulin = t.insulin;
|
|
||||||
detailedBolusInfo.timestamp = System.currentTimeMillis();
|
|
||||||
if (detailedBolusInfo.insulin > 0)
|
|
||||||
pumpSync.syncBolusWithPumpId(
|
|
||||||
detailedBolusInfo.timestamp,
|
|
||||||
detailedBolusInfo.insulin,
|
|
||||||
detailedBolusInfo.getBolusType(),
|
|
||||||
dateUtil._now(),
|
|
||||||
PumpType.DANA_R_KOREAN,
|
|
||||||
serialNumber()
|
|
||||||
);
|
|
||||||
if (detailedBolusInfo.carbs > 0)
|
|
||||||
pumpSync.syncCarbsWithTimestamp(
|
|
||||||
detailedBolusInfo.timestamp + T.mins(detailedBolusInfo.carbTime).msecs(),
|
|
||||||
detailedBolusInfo.carbs,
|
|
||||||
null,
|
|
||||||
PumpType.DANA_R_KOREAN,
|
|
||||||
serialNumber()
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
PumpEnactResult result = new PumpEnactResult(getInjector());
|
|
||||||
result.success(false).bolusDelivered(0d).carbsDelivered(0d).comment(R.string.invalidinput);
|
|
||||||
aapsLogger.error("deliverTreatment: Invalid input");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called from APS
|
|
||||||
@NonNull @Override
|
|
||||||
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
|
|
||||||
// Recheck pump status if older than 30 min
|
|
||||||
//This should not be needed while using queue because connection should be done before calling this
|
|
||||||
PumpEnactResult result = new PumpEnactResult(getInjector());
|
|
||||||
|
|
||||||
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
|
|
||||||
|
|
||||||
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d && absoluteRate >= 0.10d;
|
|
||||||
final boolean doLowTemp = absoluteRate < getBaseBasalRate() || absoluteRate < 0.10d;
|
|
||||||
final boolean doHighTemp = absoluteRate > getBaseBasalRate() && !useExtendedBoluses;
|
|
||||||
final boolean doExtendedTemp = absoluteRate > getBaseBasalRate() && useExtendedBoluses;
|
|
||||||
|
|
||||||
if (doTempOff) {
|
|
||||||
// If extended in progress
|
|
||||||
if (danaPump.isExtendedInProgress() && useExtendedBoluses) {
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doTempOff)");
|
|
||||||
return cancelExtendedBolus();
|
|
||||||
}
|
|
||||||
// If temp in progress
|
|
||||||
if (danaPump.isTempBasalInProgress()) {
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)");
|
|
||||||
return cancelRealTempBasal();
|
|
||||||
}
|
|
||||||
result.success(true).enacted(false).percent(100).isPercent(true).isTempCancel(true);
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: doTempOff OK");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doLowTemp || doHighTemp) {
|
|
||||||
int percentRate = Double.valueOf(absoluteRate / getBaseBasalRate() * 100).intValue();
|
|
||||||
// Any basal less than 0.10u/h will be dumped once per hour, not every 4 minutes. So if it's less than .10u/h, set a zero temp.
|
|
||||||
if (absoluteRate < 0.10d) percentRate = 0;
|
|
||||||
if (percentRate < 100) percentRate = Round.ceilTo((double) percentRate, 10d).intValue();
|
|
||||||
else percentRate = Round.floorTo((double) percentRate, 10d).intValue();
|
|
||||||
if (percentRate > getPumpDescription().getMaxTempPercent()) {
|
|
||||||
percentRate = getPumpDescription().getMaxTempPercent();
|
|
||||||
}
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Calculated percent rate: " + percentRate);
|
|
||||||
|
|
||||||
// If extended in progress
|
|
||||||
if (danaPump.isExtendedInProgress() && useExtendedBoluses) {
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)");
|
|
||||||
result = cancelExtendedBolus();
|
|
||||||
if (!result.getSuccess()) {
|
|
||||||
aapsLogger.error("setTempBasalAbsolute: Failed to stop previous extended bolus (doLowTemp || doHighTemp)");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if some temp is already in progress
|
|
||||||
if (danaPump.isTempBasalInProgress()) {
|
|
||||||
// Correct basal already set ?
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + danaPump.temporaryBasalToString());
|
|
||||||
if (danaPump.getTempBasalPercent() == percentRate && danaPump.getTempBasalRemainingMin() > 4) {
|
|
||||||
if (enforceNew) {
|
|
||||||
cancelTempBasal(true);
|
|
||||||
} else {
|
|
||||||
result.success(true).percent(percentRate).enacted(false).duration(danaPump.getTempBasalRemainingMin()).isPercent(true).isTempCancel(false);
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Convert duration from minutes to hours
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " minutes (doLowTemp || doHighTemp)");
|
|
||||||
return setTempBasalPercent(percentRate, durationInMinutes, profile, false, tbrType);
|
|
||||||
}
|
|
||||||
if (doExtendedTemp) {
|
|
||||||
// Check if some temp is already in progress
|
|
||||||
if (danaPump.isTempBasalInProgress()) {
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)");
|
|
||||||
result = cancelRealTempBasal();
|
|
||||||
// Check for proper result
|
|
||||||
if (!result.getSuccess()) {
|
|
||||||
aapsLogger.error("setTempBasalAbsolute: Failed to stop previous temp basal (doExtendedTemp)");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate # of halfHours from minutes
|
|
||||||
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
|
|
||||||
// We keep current basal running so need to sub current basal
|
|
||||||
double extendedRateToSet = absoluteRate - getBaseBasalRate();
|
|
||||||
extendedRateToSet = constraintChecker.applyBasalConstraints(new Constraint<>(extendedRateToSet), profile).value();
|
|
||||||
// needs to be rounded to 0.1
|
|
||||||
extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.getExtendedBolusStep() * 2); // *2 because of half hours
|
|
||||||
|
|
||||||
// What is current rate of extended bolusing in u/h?
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + (danaPump.isExtendedInProgress()) + " rate: " + danaPump.getExtendedBolusAbsoluteRate() + "U/h duration remaining: " + danaPump.getExtendedBolusRemainingMinutes() + "min");
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h");
|
|
||||||
|
|
||||||
// Compare with extended rate in progress
|
|
||||||
if (danaPump.isExtendedInProgress() && Math.abs(danaPump.getExtendedBolusAbsoluteRate() - extendedRateToSet) < getPumpDescription().getExtendedBolusStep()) {
|
|
||||||
// correct extended already set
|
|
||||||
result.success(true).absolute(danaPump.getExtendedBolusAbsoluteRate()).enacted(false).duration(danaPump.getExtendedBolusRemainingMinutes()).isPercent(false).isTempCancel(false);
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct extended already set");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now set new extended, no need to to stop previous (if running) because it's replaced
|
|
||||||
double extendedAmount = extendedRateToSet / 2 * durationInHalfHours;
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting extended: " + extendedAmount + "U half hours: " + durationInHalfHours);
|
|
||||||
result = setExtendedBolus(extendedAmount, durationInMinutes);
|
|
||||||
if (!result.getSuccess()) {
|
|
||||||
aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus set ok");
|
|
||||||
result.absolute(result.getAbsolute() + getBaseBasalRate());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// We should never end here
|
|
||||||
aapsLogger.error("setTempBasalAbsolute: Internal error");
|
|
||||||
result.success(false).comment("Internal error");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public PumpEnactResult cancelTempBasal(boolean force) {
|
|
||||||
if (danaPump.isTempBasalInProgress())
|
|
||||||
return cancelRealTempBasal();
|
|
||||||
if (danaPump.isExtendedInProgress() && useExtendedBoluses) {
|
|
||||||
return cancelExtendedBolus();
|
|
||||||
}
|
|
||||||
PumpEnactResult result = new PumpEnactResult(getInjector());
|
|
||||||
result.success(true).enacted(false).comment(R.string.ok).isTempCancel(true);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public PumpType model() {
|
|
||||||
return PumpType.DANA_R_KOREAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PumpEnactResult cancelRealTempBasal() {
|
|
||||||
PumpEnactResult result = new PumpEnactResult(getInjector());
|
|
||||||
if (danaPump.isTempBasalInProgress()) {
|
|
||||||
sExecutionService.tempBasalStop();
|
|
||||||
if (!danaPump.isTempBasalInProgress()) {
|
|
||||||
pumpSync.syncStopTemporaryBasalWithPumpId(
|
|
||||||
dateUtil._now(),
|
|
||||||
dateUtil._now(),
|
|
||||||
getPumpDescription().getPumpType(),
|
|
||||||
serialNumber()
|
|
||||||
);
|
|
||||||
result.success(true).enacted(true).isTempCancel(true);
|
|
||||||
} else
|
|
||||||
result.success(false).enacted(false).isTempCancel(true);
|
|
||||||
} else {
|
|
||||||
result.success(true).isTempCancel(true).comment(R.string.ok);
|
|
||||||
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public PumpEnactResult loadEvents() {
|
|
||||||
return new PumpEnactResult(getInjector()); // no history, not needed
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull @Override
|
|
||||||
public PumpEnactResult setUserOptions() {
|
|
||||||
return new PumpEnactResult(getInjector());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,304 @@
|
||||||
|
package info.nightscout.androidaps.danaRKorean
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
|
import android.os.IBinder
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.dana.DanaPump
|
||||||
|
import info.nightscout.androidaps.danaRKorean.services.DanaRKoreanExecutionService
|
||||||
|
import info.nightscout.androidaps.danar.AbstractDanaRPlugin
|
||||||
|
import info.nightscout.androidaps.danar.R
|
||||||
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
|
import info.nightscout.androidaps.events.EventAppExit
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePluginProvider
|
||||||
|
import info.nightscout.androidaps.interfaces.CommandQueueProvider
|
||||||
|
import info.nightscout.androidaps.interfaces.Constraint
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpSync
|
||||||
|
import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType
|
||||||
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
|
import info.nightscout.androidaps.logging.LTag
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
import info.nightscout.androidaps.utils.Round
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
|
import io.reactivex.rxkotlin.plusAssign
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class DanaRKoreanPlugin @Inject constructor(
|
||||||
|
injector: HasAndroidInjector,
|
||||||
|
aapsLogger: AAPSLogger,
|
||||||
|
aapsSchedulers: AapsSchedulers,
|
||||||
|
rxBus: RxBusWrapper,
|
||||||
|
private val context: Context,
|
||||||
|
resourceHelper: ResourceHelper,
|
||||||
|
constraintChecker: ConstraintChecker,
|
||||||
|
activePlugin: ActivePluginProvider,
|
||||||
|
sp: SP,
|
||||||
|
commandQueue: CommandQueueProvider,
|
||||||
|
danaPump: DanaPump,
|
||||||
|
dateUtil: DateUtil,
|
||||||
|
private val fabricPrivacy: FabricPrivacy,
|
||||||
|
pumpSync: PumpSync
|
||||||
|
) : AbstractDanaRPlugin(injector, danaPump, resourceHelper, constraintChecker, aapsLogger, aapsSchedulers, commandQueue, rxBus, activePlugin, sp, dateUtil, pumpSync) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
pluginDescription.description(R.string.description_pump_dana_r_korean)
|
||||||
|
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false)
|
||||||
|
pumpDescription.setPumpDescription(PumpType.DANA_R_KOREAN)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
context.bindService(Intent(context, DanaRKoreanExecutionService::class.java), mConnection, Context.BIND_AUTO_CREATE)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe({
|
||||||
|
if (isEnabled(PluginType.PUMP)) {
|
||||||
|
val previousValue = useExtendedBoluses
|
||||||
|
useExtendedBoluses = sp.getBoolean(R.string.key_danar_useextended, false)
|
||||||
|
if (useExtendedBoluses != previousValue && pumpSync.expectedPumpState().extendedBolus != null) {
|
||||||
|
sExecutionService.extendedBolusStop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventAppExit::class.java)
|
||||||
|
.observeOn(aapsSchedulers.io)
|
||||||
|
.subscribe({ context.unbindService(mConnection) }, fabricPrivacy::logException)
|
||||||
|
super.onStart()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
context.unbindService(mConnection)
|
||||||
|
disposable.clear()
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mConnection: ServiceConnection = object : ServiceConnection {
|
||||||
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
|
aapsLogger.debug(LTag.PUMP, "Service is disconnected")
|
||||||
|
sExecutionService = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||||
|
aapsLogger.debug(LTag.PUMP, "Service is connected")
|
||||||
|
val mLocalBinder = service as DanaRKoreanExecutionService.LocalBinder
|
||||||
|
sExecutionService = mLocalBinder.serviceInstance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin base interface
|
||||||
|
override val name: String
|
||||||
|
get() = resourceHelper.gs(R.string.danarkoreanpump)
|
||||||
|
override val preferencesId: Int
|
||||||
|
get() = R.xml.pref_danarkorean
|
||||||
|
|
||||||
|
// Pump interface
|
||||||
|
override val isFakingTempsByExtendedBoluses: Boolean
|
||||||
|
get() = useExtendedBoluses
|
||||||
|
|
||||||
|
override fun isInitialized(): Boolean =
|
||||||
|
danaPump.lastConnection > 0 && danaPump.maxBasal > 0 && !danaPump.isConfigUD && !danaPump.isEasyModeEnabled && danaPump.isExtendedBolusEnabled && danaPump.isPasswordOK
|
||||||
|
|
||||||
|
override fun isHandshakeInProgress(): Boolean =
|
||||||
|
sExecutionService != null && sExecutionService.isHandshakeInProgress
|
||||||
|
|
||||||
|
override fun finishHandshaking() {
|
||||||
|
sExecutionService.finishHandshaking()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
|
||||||
|
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(Constraint(detailedBolusInfo.insulin)).value()
|
||||||
|
if (detailedBolusInfo.carbs > 0) throw IllegalArgumentException()
|
||||||
|
return if (detailedBolusInfo.insulin > 0) {
|
||||||
|
val t = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.bolusType == DetailedBolusInfo.BolusType.SMB)
|
||||||
|
var connectionOK = false
|
||||||
|
if (detailedBolusInfo.insulin > 0)
|
||||||
|
connectionOK = sExecutionService.bolus(detailedBolusInfo.insulin, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.carbTime.toLong(), t)
|
||||||
|
val result = PumpEnactResult(injector)
|
||||||
|
result.success(connectionOK && abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep)
|
||||||
|
.bolusDelivered(t.insulin)
|
||||||
|
if (!result.success) result.comment(resourceHelper.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, t.insulin, danaPump.bolusStartErrorCode)) else result.comment(R.string.ok)
|
||||||
|
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered)
|
||||||
|
detailedBolusInfo.insulin = t.insulin
|
||||||
|
detailedBolusInfo.timestamp = dateUtil._now()
|
||||||
|
if (detailedBolusInfo.insulin > 0) pumpSync.syncBolusWithPumpId(
|
||||||
|
detailedBolusInfo.timestamp,
|
||||||
|
detailedBolusInfo.insulin,
|
||||||
|
detailedBolusInfo.bolusType,
|
||||||
|
dateUtil._now(),
|
||||||
|
PumpType.DANA_R_KOREAN,
|
||||||
|
serialNumber()
|
||||||
|
)
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
val result = PumpEnactResult(injector)
|
||||||
|
result.success(false).bolusDelivered(0.0).carbsDelivered(0.0).comment(R.string.invalidinput)
|
||||||
|
aapsLogger.error("deliverTreatment: Invalid input")
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called from APS
|
||||||
|
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult {
|
||||||
|
// Recheck pump status if older than 30 min
|
||||||
|
//This should not be needed while using queue because connection should be done before calling this
|
||||||
|
var result = PumpEnactResult(injector)
|
||||||
|
val absoluteRateAfterConstraint = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value()
|
||||||
|
val doTempOff = baseBasalRate - absoluteRateAfterConstraint == 0.0 && absoluteRateAfterConstraint >= 0.10
|
||||||
|
val doLowTemp = absoluteRateAfterConstraint < baseBasalRate || absoluteRateAfterConstraint < 0.10
|
||||||
|
val doHighTemp = absoluteRateAfterConstraint > baseBasalRate && !useExtendedBoluses
|
||||||
|
val doExtendedTemp = absoluteRateAfterConstraint > baseBasalRate && useExtendedBoluses
|
||||||
|
if (doTempOff) {
|
||||||
|
// If extended in progress
|
||||||
|
if (danaPump.isExtendedInProgress && useExtendedBoluses) {
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doTempOff)")
|
||||||
|
return cancelExtendedBolus()
|
||||||
|
}
|
||||||
|
// If temp in progress
|
||||||
|
if (danaPump.isTempBasalInProgress) {
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)")
|
||||||
|
return cancelRealTempBasal()
|
||||||
|
}
|
||||||
|
result.success(true).enacted(false).percent(100).isPercent(true).isTempCancel(true)
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: doTempOff OK")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
if (doLowTemp || doHighTemp) {
|
||||||
|
var percentRate: Int = java.lang.Double.valueOf(absoluteRateAfterConstraint / baseBasalRate * 100).toInt()
|
||||||
|
// Any basal less than 0.10u/h will be dumped once per hour, not every 4 minutes. So if it's less than .10u/h, set a zero temp.
|
||||||
|
if (absoluteRateAfterConstraint < 0.10) percentRate = 0
|
||||||
|
percentRate = if (percentRate < 100) Round.ceilTo(percentRate.toDouble(), 10.0).toInt() else Round.floorTo(percentRate.toDouble(), 10.0).toInt()
|
||||||
|
if (percentRate > pumpDescription.maxTempPercent) {
|
||||||
|
percentRate = pumpDescription.maxTempPercent
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Calculated percent rate: $percentRate")
|
||||||
|
|
||||||
|
// If extended in progress
|
||||||
|
if (danaPump.isExtendedInProgress && useExtendedBoluses) {
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping extended bolus (doLowTemp || doHighTemp)")
|
||||||
|
result = cancelExtendedBolus()
|
||||||
|
if (!result.success) {
|
||||||
|
aapsLogger.error("setTempBasalAbsolute: Failed to stop previous extended bolus (doLowTemp || doHighTemp)")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check if some temp is already in progress
|
||||||
|
if (danaPump.isTempBasalInProgress) {
|
||||||
|
// Correct basal already set ?
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + danaPump.temporaryBasalToString())
|
||||||
|
if (danaPump.tempBasalPercent == percentRate && danaPump.tempBasalRemainingMin > 4) {
|
||||||
|
if (enforceNew) {
|
||||||
|
cancelTempBasal(true)
|
||||||
|
} else {
|
||||||
|
result.success(true).percent(percentRate).enacted(false).duration(danaPump.tempBasalRemainingMin).isPercent(true).isTempCancel(false)
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convert duration from minutes to hours
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal $percentRate% for $durationInMinutes minutes (doLowTemp || doHighTemp)")
|
||||||
|
return setTempBasalPercent(percentRate, durationInMinutes, profile, false, tbrType)
|
||||||
|
}
|
||||||
|
if (doExtendedTemp) {
|
||||||
|
// Check if some temp is already in progress
|
||||||
|
if (danaPump.isTempBasalInProgress) {
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doExtendedTemp)")
|
||||||
|
result = cancelRealTempBasal()
|
||||||
|
// Check for proper result
|
||||||
|
if (!result.success) {
|
||||||
|
aapsLogger.error("setTempBasalAbsolute: Failed to stop previous temp basal (doExtendedTemp)")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate # of halfHours from minutes
|
||||||
|
val durationInHalfHours = max(durationInMinutes / 30, 1)
|
||||||
|
// We keep current basal running so need to sub current basal
|
||||||
|
var extendedRateToSet: Double = absoluteRateAfterConstraint - baseBasalRate
|
||||||
|
extendedRateToSet = constraintChecker.applyBasalConstraints(Constraint(extendedRateToSet), profile).value()
|
||||||
|
// needs to be rounded to 0.1
|
||||||
|
extendedRateToSet = Round.roundTo(extendedRateToSet, pumpDescription.extendedBolusStep * 2) // *2 because of half hours
|
||||||
|
|
||||||
|
// What is current rate of extended bolusing in u/h?
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus in progress: " + danaPump.isExtendedInProgress + " rate: " + danaPump.extendedBolusAbsoluteRate + "U/h duration remaining: " + danaPump.extendedBolusRemainingMinutes + "min")
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Rate to set: " + extendedRateToSet + "U/h")
|
||||||
|
|
||||||
|
// Compare with extended rate in progress
|
||||||
|
if (danaPump.isExtendedInProgress && abs(danaPump.extendedBolusAbsoluteRate - extendedRateToSet) < pumpDescription.extendedBolusStep) {
|
||||||
|
// correct extended already set
|
||||||
|
result.success(true).absolute(danaPump.extendedBolusAbsoluteRate).enacted(false).duration(danaPump.extendedBolusRemainingMinutes).isPercent(false).isTempCancel(false)
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Correct extended already set")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now set new extended, no need to to stop previous (if running) because it's replaced
|
||||||
|
val extendedAmount = extendedRateToSet / 2 * durationInHalfHours
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Setting extended: " + extendedAmount + "U half hours: " + durationInHalfHours)
|
||||||
|
result = setExtendedBolus(extendedAmount, durationInMinutes)
|
||||||
|
if (!result.success) {
|
||||||
|
aapsLogger.error("setTempBasalAbsolute: Failed to set extended bolus")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Extended bolus set ok")
|
||||||
|
result.absolute(result.absolute + baseBasalRate)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
// We should never end here
|
||||||
|
aapsLogger.error("setTempBasalAbsolute: Internal error")
|
||||||
|
result.success(false).comment("Internal error")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult {
|
||||||
|
if (danaPump.isTempBasalInProgress) return cancelRealTempBasal()
|
||||||
|
if (danaPump.isExtendedInProgress && useExtendedBoluses) {
|
||||||
|
return cancelExtendedBolus()
|
||||||
|
}
|
||||||
|
val result = PumpEnactResult(injector)
|
||||||
|
result.success(true).enacted(false).comment(R.string.ok).isTempCancel(true)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun model(): PumpType = PumpType.DANA_R_KOREAN
|
||||||
|
|
||||||
|
private fun cancelRealTempBasal(): PumpEnactResult {
|
||||||
|
val result = PumpEnactResult(injector)
|
||||||
|
if (danaPump.isTempBasalInProgress) {
|
||||||
|
sExecutionService.tempBasalStop()
|
||||||
|
if (!danaPump.isTempBasalInProgress) {
|
||||||
|
pumpSync.syncStopTemporaryBasalWithPumpId(
|
||||||
|
dateUtil._now(),
|
||||||
|
dateUtil._now(),
|
||||||
|
pumpDescription.pumpType,
|
||||||
|
serialNumber()
|
||||||
|
)
|
||||||
|
result.success(true).enacted(true).isTempCancel(true)
|
||||||
|
} else result.success(false).enacted(false).isTempCancel(true)
|
||||||
|
} else {
|
||||||
|
result.success(true).isTempCancel(true).comment(R.string.ok)
|
||||||
|
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK")
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadEvents(): PumpEnactResult = PumpEnactResult(injector) // no history, not needed
|
||||||
|
override fun setUserOptions(): PumpEnactResult = PumpEnactResult(injector)
|
||||||
|
}
|
Loading…
Reference in a new issue