DanaRSPlugin, DanaRSService -> kt, allign with R code

This commit is contained in:
Milos Kozak 2020-03-29 11:40:57 +02:00
parent a85ec262d3
commit df03a8a2c0
25 changed files with 1187 additions and 1479 deletions

View file

@ -15,6 +15,11 @@ public class PumpDescription {
resetSettings();
}
public PumpDescription (PumpType pumpType) {
this();
setPumpDescription(pumpType);
}
public static final int NONE = 0;
public static final int PERCENT = 0x01;
public static final int ABSOLUTE = 0x02;

View file

@ -709,7 +709,7 @@ class SmsCommunicatorPlugin @Inject constructor(
sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))
return
}
time = midnight + T.secs(seconds.toLong()).msecs()
time = midnight + T.secs(seconds.toLong()).msecs() // TODO: this is wrong during leap day
}
grams = constraintChecker.applyCarbsConstraints(Constraint(grams)).value()
if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, resourceHelper.gs(R.string.wrongformat)))

View file

@ -165,7 +165,7 @@ public class DanaRPlugin extends AbstractDanaRPlugin {
result.bolusDelivered = t.insulin;
result.carbsDelivered = detailedBolusInfo.carbs;
if (!result.success)
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, danaRPump.getMessageStartErrorCode());
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, danaRPump.getBolusStartErrorCode());
else
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);

View file

@ -141,15 +141,15 @@ class DanaRPump @Inject constructor(
return if (units == UNITS_MGDL) Constants.MGDL else Constants.MMOL
}
// DanaR,Rv2,RK specific flags
// last start bolus erroCode
var messageStartErrorCode: Int = 0
var historyDoneReceived: Boolean = false
var bolusStartErrorCode: Int = 0 // last start bolus erroCode
var historyDoneReceived: Boolean = false // true when last history message is received
var bolusingTreatment: Treatment? = null // actually delivered treatment
var bolusAmountToBeDelivered = 0.0 // amount to be delivered
var bolusProgressLastTimeStamp: Long = 0 // timestamp of last bolus progress message
var bolusStopped = false // bolus finished
var bolusStopForced = false // bolus forced to stop by user
var bolusDone = false // success end
var lastEventTimeLoaded: Long = 0 // timestamp of last received event
fun createConvertedProfile(): ProfileStore? {
pumpProfiles?.let {

View file

@ -4,7 +4,6 @@ import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
class MsgBolusStart(
@ -31,6 +30,6 @@ class MsgBolusStart(
failed = false
aapsLogger.debug(LTag.PUMPBTCOMM, "Messsage response: $errorCode OK")
}
danaRPump.messageStartErrorCode = errorCode
danaRPump.bolusStartErrorCode = errorCode
}
}

View file

@ -4,7 +4,6 @@ import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
class MsgBolusStartWithSpeed(
@ -33,6 +32,6 @@ class MsgBolusStartWithSpeed(
failed = false
aapsLogger.debug(LTag.PUMPBTCOMM, "Messsage response: $errorCode OK")
}
danaRPump.messageStartErrorCode = errorCode
danaRPump.bolusStartErrorCode = errorCode
}
}

View file

@ -168,7 +168,7 @@ public class DanaRKoreanPlugin extends AbstractDanaRPlugin {
result.bolusDelivered = t.insulin;
result.carbsDelivered = detailedBolusInfo.carbs;
if (!result.success)
result.comment = resourceHelper.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, t.insulin, danaRPump.getMessageStartErrorCode());
result.comment = resourceHelper.gs(R.string.boluserrorcode, detailedBolusInfo.insulin, t.insulin, danaRPump.getBolusStartErrorCode());
else
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);

View file

@ -1,843 +0,0 @@
package info.nightscout.androidaps.plugins.pump.danaRS;
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 androidx.preference.Preference;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventConfigBuilderChange;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.DanaRInterface;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRFragment;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump;
import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSDeviceChange;
import info.nightscout.androidaps.plugins.pump.danaRS.services.DanaRSService;
import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.Round;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.ToastUtils;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
@Singleton
public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaRInterface, ConstraintsInterface {
private CompositeDisposable disposable = new CompositeDisposable();
private final Context context;
private final ResourceHelper resourceHelper;
private final ConstraintChecker constraintChecker;
private final ProfileFunction profileFunction;
private final TreatmentsPlugin treatmentsPlugin;
private final SP sp;
private final RxBusWrapper rxBus;
private final DanaRPump danaRPump;
private final DetailedBolusInfoStorage detailedBolusInfoStorage;
private final FabricPrivacy fabricPrivacy;
private DanaRSService danaRSService;
private String mDeviceAddress = "";
public String mDeviceName = "";
public PumpDescription pumpDescription = new PumpDescription();
// Bolus & history handling
public int bolusStartErrorCode; // from start message
public Treatment bolusingTreatment; // actually delivered treatment
public double bolusAmountToBeDelivered = 0.0; // amount to be delivered
public boolean bolusStopped = false; // bolus finished
public boolean bolusStopForced = false; // bolus forced to stop by user
public boolean bolusDone = false; // success end
public long bolusProgressLastTimeStamp = 0; // timestamp of last bolus progress message
public boolean apsHistoryDone = false; // true when last history message is received
public long lastEventTimeLoaded = 0; // timestamp of last received event
@Inject
public DanaRSPlugin(
HasAndroidInjector injector,
AAPSLogger aapsLogger,
RxBusWrapper rxBus,
Context context,
ResourceHelper resourceHelper,
ConstraintChecker constraintChecker,
ProfileFunction profileFunction,
TreatmentsPlugin treatmentsPlugin,
SP sp,
CommandQueueProvider commandQueue,
DanaRPump danaRPump,
DetailedBolusInfoStorage detailedBolusInfoStorage,
FabricPrivacy fabricPrivacy
) {
super(new PluginDescription()
.mainType(PluginType.PUMP)
.fragmentClass(DanaRFragment.class.getName())
.pluginName(R.string.danarspump)
.shortName(R.string.danarspump_shortname)
.preferencesId(R.xml.pref_danars)
.description(R.string.description_pump_dana_rs),
injector, aapsLogger, resourceHelper, commandQueue
);
this.context = context;
this.rxBus = rxBus;
this.resourceHelper = resourceHelper;
this.constraintChecker = constraintChecker;
this.profileFunction = profileFunction;
this.treatmentsPlugin = treatmentsPlugin;
this.sp = sp;
this.danaRPump = danaRPump;
this.detailedBolusInfoStorage = detailedBolusInfoStorage;
this.fabricPrivacy = fabricPrivacy;
pumpDescription.setPumpDescription(PumpType.DanaRS);
}
@Override
public void updatePreferenceSummary(@NotNull Preference pref) {
super.updatePreferenceSummary(pref);
if (pref.getKey().equals(resourceHelper.gs(R.string.key_danars_name)))
pref.setSummary(sp.getString(R.string.key_danars_name, ""));
}
@Override
protected void onStart() {
Intent intent = new Intent(context, DanaRSService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
.subscribe(event -> context.unbindService(mConnection), fabricPrivacy::logException)
);
disposable.add(rxBus
.toObservable(EventConfigBuilderChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> danaRPump.reset())
);
disposable.add(rxBus
.toObservable(EventDanaRSDeviceChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> changePump(), fabricPrivacy::logException)
);
changePump(); // load device name
super.onStart();
}
@Override
protected void onStop() {
context.unbindService(mConnection);
disposable.clear();
super.onStop();
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
getAapsLogger().debug(LTag.PUMP, "Service is disconnected");
danaRSService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
getAapsLogger().debug(LTag.PUMP, "Service is connected");
DanaRSService.LocalBinder mLocalBinder = (DanaRSService.LocalBinder) service;
danaRSService = mLocalBinder.getServiceInstance();
}
};
public void changePump() {
mDeviceAddress = sp.getString(R.string.key_danars_address, "");
mDeviceName = sp.getString(R.string.key_danars_name, "");
danaRPump.reset();
getCommandQueue().readStatus("DeviceChanged", null);
}
@Override
public void connect(String from) {
getAapsLogger().debug(LTag.PUMP, "RS connect from: " + from);
if (danaRSService != null && !mDeviceAddress.equals("") && !mDeviceName.equals("")) {
boolean success = danaRSService.connect(from, mDeviceAddress);
if (!success)
ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.rileylink_scanner_ble_not_supported));
}
}
@Override
public boolean isConnected() {
return danaRSService != null && danaRSService.isConnected();
}
@Override
public boolean isConnecting() {
return danaRSService != null && danaRSService.isConnecting();
}
@Override
public boolean isHandshakeInProgress() {
return false;
}
@Override
public void finishHandshaking() {
}
@Override
public void disconnect(String from) {
getAapsLogger().debug(LTag.PUMP, "RS disconnect from: " + from);
if (danaRSService != null) danaRSService.disconnect(from);
}
@Override
public void stopConnecting() {
if (danaRSService != null) danaRSService.stopConnecting();
}
@Override
public void getPumpStatus() {
if (danaRSService != null) {
danaRSService.getPumpStatus();
pumpDescription.basalStep = danaRPump.getBasalStep();
pumpDescription.bolusStep = danaRPump.getBolusStep();
}
}
// DanaR interface
@Override
public PumpEnactResult loadHistory(byte type) {
return danaRSService.loadHistory(type);
}
@Override
public PumpEnactResult loadEvents() {
return danaRSService.loadEvents();
}
@Override
public PumpEnactResult setUserOptions() {
return danaRSService.setUserSettings();
}
// Constraints interface
@NonNull
@Override
public Constraint<Double> applyBasalConstraints(Constraint<Double> absoluteRate, @NonNull Profile profile) {
absoluteRate.setIfSmaller(getAapsLogger(), danaRPump.getMaxBasal(), resourceHelper.gs(R.string.limitingbasalratio, danaRPump.getMaxBasal(), resourceHelper.gs(R.string.pumplimit)), this);
return absoluteRate;
}
@NonNull
@Override
public Constraint<Integer> applyBasalPercentConstraints(Constraint<Integer> percentRate, @NonNull Profile profile) {
percentRate.setIfGreater(getAapsLogger(), 0, resourceHelper.gs(R.string.limitingpercentrate, 0, resourceHelper.gs(R.string.itmustbepositivevalue)), this);
percentRate.setIfSmaller(getAapsLogger(), getPumpDescription().maxTempPercent, resourceHelper.gs(R.string.limitingpercentrate, getPumpDescription().maxTempPercent, resourceHelper.gs(R.string.pumplimit)), this);
return percentRate;
}
@NonNull
@Override
public Constraint<Double> applyBolusConstraints(Constraint<Double> insulin) {
insulin.setIfSmaller(getAapsLogger(), danaRPump.getMaxBolus(), resourceHelper.gs(R.string.limitingbolus, danaRPump.getMaxBolus(), resourceHelper.gs(R.string.pumplimit)), this);
return insulin;
}
@NonNull
@Override
public Constraint<Double> applyExtendedBolusConstraints(@NonNull Constraint<Double> insulin) {
return applyBolusConstraints(insulin);
}
// Pump interface
@Override
public boolean isInitialized() {
return danaRPump.getLastConnection() > 0 && danaRPump.getMaxBasal() > 0;
}
@Override
public boolean isSuspended() {
return danaRPump.getPumpSuspended();
}
@Override
public boolean isBusy() {
if (danaRSService == null) return false;
return danaRSService.isConnected() || danaRSService.isConnecting();
}
@NonNull @Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
PumpEnactResult result = new PumpEnactResult(getInjector());
if (danaRSService == null) {
getAapsLogger().error("setNewBasalProfile sExecutionService is null");
result.comment = "setNewBasalProfile sExecutionService is null";
return result;
}
if (!isInitialized()) {
getAapsLogger().error("setNewBasalProfile not initialized");
Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, resourceHelper.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT);
rxBus.send(new EventNewNotification(notification));
result.comment = resourceHelper.gs(R.string.pumpNotInitializedProfileNotSet);
return result;
} else {
rxBus.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
}
if (!danaRSService.updateBasalsInPump(profile)) {
Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, resourceHelper.gs(R.string.failedupdatebasalprofile), Notification.URGENT);
rxBus.send(new EventNewNotification(notification));
result.comment = resourceHelper.gs(R.string.failedupdatebasalprofile);
return result;
} else {
rxBus.send(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED));
rxBus.send(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE));
Notification notification = new Notification(Notification.PROFILE_SET_OK, resourceHelper.gs(R.string.profile_set_ok), Notification.INFO, 60);
rxBus.send(new EventNewNotification(notification));
result.success = true;
result.enacted = true;
result.comment = "OK";
return result;
}
}
@Override
public boolean isThisProfileSet(Profile profile) {
if (!isInitialized())
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
if (danaRPump.getPumpProfiles() == null)
return true; // TODO: not sure what's better. so far TRUE to prevent too many SMS
int basalValues = danaRPump.getBasal48Enable() ? 48 : 24;
int basalIncrement = danaRPump.getBasal48Enable() ? 30 * 60 : 60 * 60;
for (int h = 0; h < basalValues; h++) {
Double pumpValue = danaRPump.getPumpProfiles()[danaRPump.getActiveProfile()][h];
Double profileValue = profile.getBasalTimeFromMidnight(h * basalIncrement);
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
getAapsLogger().debug(LTag.PUMP, "Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
return false;
}
}
return true;
}
@Override
public long lastDataTime() {
return danaRPump.getLastConnection();
}
@Override
public double getBaseBasalRate() {
return danaRPump.getCurrentBasal();
}
@Override
public double getReservoirLevel() {
return danaRPump.getReservoirRemainingUnits();
}
@Override
public int getBatteryLevel() {
return danaRPump.getBatteryRemaining();
}
@NonNull @Override
public synchronized PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(new Constraint<>(detailedBolusInfo.insulin)).value();
if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
int preferencesSpeed = sp.getInt(R.string.key_danars_bolusspeed, 0);
int speed = 12;
switch (preferencesSpeed) {
case 0:
speed = 12;
break;
case 1:
speed = 30;
break;
case 2:
speed = 60;
break;
}
// RS stores end time for bolus, we need to adjust time
// default delivery speed is 12 sec/U
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;
if (carbTime == 0) carbTime--; // better set 1 min back to prevents clash with insulin
detailedBolusInfo.carbTime = 0;
detailedBolusInfoStorage.add(detailedBolusInfo); // will be picked up on reading history
Treatment t = new Treatment();
t.isSMB = detailedBolusInfo.isSMB;
boolean connectionOK = false;
if (detailedBolusInfo.insulin > 0 || carbs > 0)
connectionOK = danaRSService.bolus(detailedBolusInfo.insulin, (int) carbs, DateUtil.now() + T.mins(carbTime).msecs(), t);
PumpEnactResult result = new PumpEnactResult(getInjector());
result.success = connectionOK && Math.abs(detailedBolusInfo.insulin - t.insulin) < pumpDescription.bolusStep;
result.bolusDelivered = t.insulin;
result.carbsDelivered = detailedBolusInfo.carbs;
if (!result.success) {
String error = "" + bolusStartErrorCode;
switch (bolusStartErrorCode) {
// 4 reported as max bolus violation. Check later
case 0x10:
error = resourceHelper.gs(R.string.maxbolusviolation);
break;
case 0x20:
error = resourceHelper.gs(R.string.commanderror);
break;
case 0x40:
error = resourceHelper.gs(R.string.speederror);
break;
case 0x80:
error = resourceHelper.gs(R.string.insulinlimitviolation);
break;
}
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, error);
} else
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
getAapsLogger().debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);
return result;
} else {
PumpEnactResult result = new PumpEnactResult(getInjector());
result.success = false;
result.bolusDelivered = 0d;
result.carbsDelivered = 0d;
result.comment = resourceHelper.gs(R.string.danar_invalidinput);
getAapsLogger().error("deliverTreatment: Invalid input");
return result;
}
}
@Override
public void stopBolusDelivering() {
if (danaRSService == null) {
getAapsLogger().error("stopBolusDelivering sExecutionService is null");
return;
}
danaRSService.bolusStop();
}
// This is called from APS
@NonNull @Override
public synchronized PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
// Recheck pump status if older than 30 min
//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");
//}
PumpEnactResult result = new PumpEnactResult(getInjector());
absoluteRate = constraintChecker.applyBasalConstraints(new Constraint<>(absoluteRate), profile).value();
final boolean doTempOff = getBaseBasalRate() - absoluteRate == 0d;
final boolean doLowTemp = absoluteRate < getBaseBasalRate();
final boolean doHighTemp = absoluteRate > getBaseBasalRate();
if (doTempOff) {
// If temp in progress
if (treatmentsPlugin.isTempBasalInProgress()) {
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)");
return cancelTempBasal(false);
}
result.success = true;
result.enacted = false;
result.percent = 100;
result.isPercent = true;
result.isTempCancel = true;
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute: doTempOff OK");
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();
if (percentRate > 500) // Special high temp 500/15min
percentRate = 500;
// Check if some temp is already in progress
TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute: currently running: " + activeTemp.toString());
// 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;
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute: Correct temp basal already set (doLowTemp || doHighTemp)");
return result;
}
}
}
// Convert duration from minutes to hours
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute: Setting temp basal " + percentRate + "% for " + durationInMinutes + " mins (doLowTemp || doHighTemp)");
if (percentRate == 0 && durationInMinutes > 30) {
result = setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew);
} else {
// use special APS temp basal call ... 100+/15min .... 100-/30min
result = setHighTempBasalPercent(percentRate);
}
if (!result.success) {
getAapsLogger().error("setTempBasalAbsolute: Failed to set hightemp basal");
return result;
}
getAapsLogger().debug(LTag.PUMP, "setTempBasalAbsolute: hightemp basal set ok");
return result;
}
// We should never end here
getAapsLogger().error("setTempBasalAbsolute: Internal error");
result.success = false;
result.comment = "Internal error";
return result;
}
@NonNull @Override
public synchronized PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
DanaRPump pump = danaRPump;
PumpEnactResult result = new PumpEnactResult(getInjector());
percent = constraintChecker.applyBasalPercentConstraints(new Constraint<>(percent), profile).value();
if (percent < 0) {
result.isTempCancel = false;
result.enacted = false;
result.success = false;
result.comment = resourceHelper.gs(R.string.danar_invalidinput);
getAapsLogger().error("setTempBasalPercent: Invalid input");
return result;
}
if (percent > getPumpDescription().maxTempPercent)
percent = getPumpDescription().maxTempPercent;
long now = System.currentTimeMillis();
TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(now);
if (activeTemp != null && activeTemp.percentRate == percent && activeTemp.getPlannedRemainingMinutes() > 4 && !enforceNew) {
result.enacted = false;
result.success = true;
result.isTempCancel = false;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
result.duration = pump.getTempBasalRemainingMin();
result.percent = pump.getTempBasalPercent();
result.isPercent = true;
getAapsLogger().debug(LTag.PUMP, "setTempBasalPercent: Correct value already set");
return result;
}
boolean connectionOK;
if (durationInMinutes == 15 || durationInMinutes == 30) {
connectionOK = danaRSService.tempBasalShortDuration(percent, durationInMinutes);
} else {
int durationInHours = Math.max(durationInMinutes / 60, 1);
connectionOK = danaRSService.tempBasal(percent, durationInHours);
}
if (connectionOK && pump.isTempBasalInProgress() && pump.getTempBasalPercent() == percent) {
result.enacted = true;
result.success = true;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.getTempBasalRemainingMin();
result.percent = pump.getTempBasalPercent();
result.isPercent = true;
getAapsLogger().debug(LTag.PUMP, "setTempBasalPercent: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = resourceHelper.gs(R.string.tempbasaldeliveryerror);
getAapsLogger().error("setTempBasalPercent: Failed to set temp basal");
return result;
}
private synchronized PumpEnactResult setHighTempBasalPercent(Integer percent) {
DanaRPump pump = danaRPump;
PumpEnactResult result = new PumpEnactResult(getInjector());
boolean connectionOK = danaRSService.highTempBasal(percent);
if (connectionOK && pump.isTempBasalInProgress() && pump.getTempBasalPercent() == percent) {
result.enacted = true;
result.success = true;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.getTempBasalRemainingMin();
result.percent = pump.getTempBasalPercent();
result.isPercent = true;
getAapsLogger().debug(LTag.PUMP, "setHighTempBasalPercent: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
getAapsLogger().error("setHighTempBasalPercent: Failed to set temp basal");
return result;
}
@NonNull @Override
public synchronized PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
DanaRPump pump = danaRPump;
insulin = constraintChecker.applyExtendedBolusConstraints(new Constraint<>(insulin)).value();
// needs to be rounded
int durationInHalfHours = Math.max(durationInMinutes / 30, 1);
insulin = Round.roundTo(insulin, getPumpDescription().extendedBolusStep);
PumpEnactResult result = new PumpEnactResult(getInjector());
ExtendedBolus runningEB = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis());
if (runningEB != null && Math.abs(runningEB.insulin - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = false;
result.success = true;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
result.duration = pump.getExtendedBolusRemainingMinutes();
result.absolute = pump.getExtendedBolusAbsoluteRate();
result.isPercent = false;
result.isTempCancel = false;
getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + pump.getExtendedBolusAmount() + " Asked: " + insulin);
return result;
}
boolean connectionOK = danaRSService.extendedBolus(insulin, durationInHalfHours);
if (connectionOK && pump.isExtendedInProgress() && Math.abs(pump.getExtendedBolusAbsoluteRate() - insulin) < getPumpDescription().extendedBolusStep) {
result.enacted = true;
result.success = true;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
result.isTempCancel = false;
result.duration = pump.getExtendedBolusRemainingMinutes();
result.absolute = pump.getExtendedBolusAbsoluteRate();
result.bolusDelivered = pump.getExtendedBolusAmount();
result.isPercent = false;
getAapsLogger().debug(LTag.PUMP, "setExtendedBolus: OK");
return result;
}
result.enacted = false;
result.success = false;
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
getAapsLogger().error("setExtendedBolus: Failed to extended bolus");
return result;
}
@NonNull @Override
public synchronized PumpEnactResult cancelTempBasal(boolean force) {
PumpEnactResult result = new PumpEnactResult(getInjector());
TemporaryBasal runningTB = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis());
if (runningTB != null) {
danaRSService.tempBasalStop();
result.enacted = true;
result.isTempCancel = true;
}
if (!danaRPump.isTempBasalInProgress()) {
result.success = true;
result.isTempCancel = true;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
getAapsLogger().debug(LTag.PUMP, "cancelRealTempBasal: OK");
return result;
} else {
result.success = false;
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
result.isTempCancel = true;
getAapsLogger().error("cancelRealTempBasal: Failed to cancel temp basal");
return result;
}
}
@NonNull @Override
public synchronized PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult(getInjector());
ExtendedBolus runningEB = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis());
if (runningEB != null) {
danaRSService.extendedBolusStop();
result.enacted = true;
result.isTempCancel = true;
}
if (!danaRPump.isExtendedInProgress()) {
result.success = true;
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
getAapsLogger().debug(LTag.PUMP, "cancelExtendedBolus: OK");
return result;
} else {
result.success = false;
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly);
getAapsLogger().error("cancelExtendedBolus: Failed to cancel extended bolus");
return result;
}
}
@NonNull @Override
public JSONObject getJSONStatus(Profile profile, String profileName) {
DanaRPump pump = danaRPump;
long now = System.currentTimeMillis();
if (pump.getLastConnection() + 5 * 60 * 1000L < System.currentTimeMillis()) {
return new JSONObject();
}
JSONObject pumpjson = new JSONObject();
JSONObject battery = new JSONObject();
JSONObject status = new JSONObject();
JSONObject extended = new JSONObject();
try {
battery.put("percent", pump.getBatteryRemaining());
status.put("status", pump.getPumpSuspended() ? "suspended" : "normal");
status.put("timestamp", DateUtil.toISOString(pump.getLastConnection()));
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
if (pump.getLastBolusTime() != 0) {
extended.put("LastBolus", DateUtil.dateAndTimeString(pump.getLastBolusTime()));
extended.put("LastBolusAmount", pump.getLastBolusAmount());
}
TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now);
if (tb != null) {
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile));
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
}
ExtendedBolus eb = treatmentsPlugin.getExtendedBolusFromHistory(now);
if (eb != null) {
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
}
extended.put("BaseBasalRate", getBaseBasalRate());
try {
extended.put("ActiveProfile", profileFunction.getProfileName());
} catch (Exception e) {
getAapsLogger().error("Unhandled exception", e);
}
pumpjson.put("battery", battery);
pumpjson.put("status", status);
pumpjson.put("extended", extended);
pumpjson.put("reservoir", (int) pump.getReservoirRemainingUnits());
pumpjson.put("clock", DateUtil.toISOString(now));
} catch (JSONException e) {
getAapsLogger().error("Unhandled exception", e);
}
return pumpjson;
}
@NonNull @Override
public ManufacturerType manufacturer() {
return ManufacturerType.Sooil;
}
@NonNull @Override
public PumpType model() {
return PumpType.DanaRS;
}
@NonNull @Override
public String serialNumber() {
return danaRPump.getSerialNumber();
}
@NonNull @Override
public PumpDescription getPumpDescription() {
return pumpDescription;
}
@NonNull @Override
public String shortStatus(boolean veryShort) {
DanaRPump pump = danaRPump;
String ret = "";
if (pump.getLastConnection() != 0) {
long agoMsec = System.currentTimeMillis() - pump.getLastConnection();
int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " minago\n";
}
if (pump.getLastBolusTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pump.getLastBolusAmount()) + "U @" + android.text.format.DateFormat.format("HH:mm", pump.getLastBolusTime()) + "\n";
}
TemporaryBasal activeTemp = treatmentsPlugin.getRealTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
ret += "Temp: " + activeTemp.toStringFull() + "\n";
}
ExtendedBolus activeExtendedBolus = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis());
if (activeExtendedBolus != null) {
ret += "Extended: " + activeExtendedBolus.toString() + "\n";
}
if (!veryShort) {
ret += "TDD: " + DecimalFormatter.to0Decimal(pump.getDailyTotalUnits()) + " / " + pump.getMaxDailyTotalUnits() + " U\n";
}
ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.getReservoirRemainingUnits()) + "U\n";
ret += "Batt: " + pump.getBatteryRemaining() + "\n";
return ret;
}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return false;
}
@NonNull @Override
public PumpEnactResult loadTDDs() {
return loadHistory(RecordTypes.RECORD_TYPE_DAILY);
}
@Override
public List<CustomAction> getCustomActions() {
return null;
}
@Override
public void executeCustomAction(CustomActionType customActionType) {
}
@Override
public boolean canHandleDST() {
return false;
}
@Override
public void timeDateOrTimeZoneChanged() {
}
}

View file

@ -0,0 +1,658 @@
package info.nightscout.androidaps.plugins.pump.danaRS
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.text.format.DateFormat
import androidx.preference.Preference
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.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.EventConfigBuilderChange
import info.nightscout.androidaps.interfaces.*
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.common.ManufacturerType
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.danaR.DanaRFragment
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes
import info.nightscout.androidaps.plugins.pump.danaRS.events.EventDanaRSDeviceChange
import info.nightscout.androidaps.plugins.pump.danaRS.services.DanaRSService
import info.nightscout.androidaps.plugins.treatments.Treatment
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import org.json.JSONException
import org.json.JSONObject
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.abs
import kotlin.math.max
@Singleton
class DanaRSPlugin @Inject constructor(
injector: HasAndroidInjector,
aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
private val context: Context,
resourceHelper: ResourceHelper,
private val constraintChecker: ConstraintChecker,
private val profileFunction: ProfileFunction,
private val treatmentsPlugin: TreatmentsPlugin,
private val sp: SP,
commandQueue: CommandQueueProvider,
private val danaRPump: DanaRPump,
private val detailedBolusInfoStorage: DetailedBolusInfoStorage,
private val fabricPrivacy: FabricPrivacy
) : PumpPluginBase(PluginDescription()
.mainType(PluginType.PUMP)
.fragmentClass(DanaRFragment::class.java.name)
.pluginName(R.string.danarspump)
.shortName(R.string.danarspump_shortname)
.preferencesId(R.xml.pref_danars)
.description(R.string.description_pump_dana_rs),
injector, aapsLogger, resourceHelper, commandQueue
), PumpInterface, DanaRInterface, ConstraintsInterface {
private val disposable = CompositeDisposable()
private var danaRSService: DanaRSService? = null
private var mDeviceAddress = ""
var mDeviceName = ""
private var pumpDesc = PumpDescription(PumpType.DanaRS)
override fun updatePreferenceSummary(pref: Preference) {
super.updatePreferenceSummary(pref)
if (pref.key == resourceHelper.gs(R.string.key_danars_name)) pref.summary = sp.getString(R.string.key_danars_name, "")
}
override fun onStart() {
super.onStart()
val intent = Intent(context, DanaRSService::class.java)
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
disposable.add(rxBus
.toObservable(EventAppExit::class.java)
.observeOn(Schedulers.io())
.subscribe({ context.unbindService(mConnection) }) { fabricPrivacy.logException(it) }
)
disposable.add(rxBus
.toObservable(EventConfigBuilderChange::class.java)
.observeOn(Schedulers.io())
.subscribe { danaRPump.reset() }
)
disposable.add(rxBus
.toObservable(EventDanaRSDeviceChange::class.java)
.observeOn(Schedulers.io())
.subscribe({ changePump() }) { fabricPrivacy.logException(it) }
)
changePump() // load device name
}
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")
danaRSService = null
}
override fun onServiceConnected(name: ComponentName, service: IBinder) {
aapsLogger.debug(LTag.PUMP, "Service is connected")
val mLocalBinder = service as DanaRSService.LocalBinder
danaRSService = mLocalBinder.serviceInstance
}
}
fun changePump() {
mDeviceAddress = sp.getString(R.string.key_danars_address, "")
mDeviceName = sp.getString(R.string.key_danars_name, "")
danaRPump.reset()
commandQueue.readStatus("DeviceChanged", null)
}
override fun connect(from: String) {
aapsLogger.debug(LTag.PUMP, "RS connect from: $from")
if (danaRSService != null && mDeviceAddress != "" && mDeviceName != "") {
val success = danaRSService?.connect(from, mDeviceAddress) ?: false
if (!success) ToastUtils.showToastInUiThread(context, resourceHelper.gs(R.string.rileylink_scanner_ble_not_supported))
}
}
override fun isConnected(): Boolean {
return danaRSService?.isConnected ?: false
}
override fun isConnecting(): Boolean {
return danaRSService?.isConnecting ?: false
}
override fun isHandshakeInProgress(): Boolean {
return false
}
override fun finishHandshaking() {}
override fun disconnect(from: String) {
aapsLogger.debug(LTag.PUMP, "RS disconnect from: $from")
danaRSService?.disconnect(from)
}
override fun stopConnecting() {
danaRSService?.stopConnecting()
}
override fun getPumpStatus() {
danaRSService?.readPumpStatus()
pumpDesc.basalStep = danaRPump.basalStep
pumpDesc.bolusStep = danaRPump.bolusStep
}
// DanaR interface
override fun loadHistory(type: Byte): PumpEnactResult {
return danaRSService?.loadHistory(type) ?: PumpEnactResult(injector).success(false)
}
override fun loadEvents(): PumpEnactResult {
return danaRSService?.loadEvents() ?: PumpEnactResult(injector).success(false)
}
override fun setUserOptions(): PumpEnactResult {
return danaRSService?.setUserSettings() ?: PumpEnactResult(injector).success(false)
}
// Constraints interface
override fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> {
absoluteRate.setIfSmaller(aapsLogger, danaRPump.maxBasal, resourceHelper.gs(R.string.limitingbasalratio, danaRPump.maxBasal, resourceHelper.gs(R.string.pumplimit)), this)
return absoluteRate
}
override fun applyBasalPercentConstraints(percentRate: Constraint<Int>, profile: Profile): Constraint<Int> {
percentRate.setIfGreater(aapsLogger, 0, resourceHelper.gs(R.string.limitingpercentrate, 0, resourceHelper.gs(R.string.itmustbepositivevalue)), this)
percentRate.setIfSmaller(aapsLogger, pumpDescription.maxTempPercent, resourceHelper.gs(R.string.limitingpercentrate, pumpDescription.maxTempPercent, resourceHelper.gs(R.string.pumplimit)), this)
return percentRate
}
override fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
insulin.setIfSmaller(aapsLogger, danaRPump.maxBolus, resourceHelper.gs(R.string.limitingbolus, danaRPump.maxBolus, resourceHelper.gs(R.string.pumplimit)), this)
return insulin
}
override fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
return applyBolusConstraints(insulin)
}
// Pump interface
override fun isInitialized(): Boolean {
return danaRPump.lastConnection > 0 && danaRPump.maxBasal > 0
}
override fun isSuspended(): Boolean {
return danaRPump.pumpSuspended
}
override fun isBusy(): Boolean {
return danaRSService?.isConnected ?: false || danaRSService?.isConnecting ?: false
}
override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
val result = PumpEnactResult(injector)
if (!isInitialized) {
aapsLogger.error("setNewBasalProfile not initialized")
val notification = Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, resourceHelper.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT)
rxBus.send(EventNewNotification(notification))
result.comment = resourceHelper.gs(R.string.pumpNotInitializedProfileNotSet)
return result
} else {
rxBus.send(EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED))
}
return if (danaRSService?.updateBasalsInPump(profile) != true) {
val notification = Notification(Notification.FAILED_UDPATE_PROFILE, resourceHelper.gs(R.string.failedupdatebasalprofile), Notification.URGENT)
rxBus.send(EventNewNotification(notification))
result.comment = resourceHelper.gs(R.string.failedupdatebasalprofile)
result
} else {
rxBus.send(EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED))
rxBus.send(EventDismissNotification(Notification.FAILED_UDPATE_PROFILE))
val notification = Notification(Notification.PROFILE_SET_OK, resourceHelper.gs(R.string.profile_set_ok), Notification.INFO, 60)
rxBus.send(EventNewNotification(notification))
result.success = true
result.enacted = true
result.comment = "OK"
result
}
}
override fun isThisProfileSet(profile: Profile): Boolean {
if (!isInitialized) return true // TODO: not sure what's better. so far TRUE to prevent too many SMS
if (danaRPump.pumpProfiles == null) return true // TODO: not sure what's better. so far TRUE to prevent too many SMS
val basalValues = if (danaRPump.basal48Enable) 48 else 24
val basalIncrement = if (danaRPump.basal48Enable) 30 * 60 else 60 * 60
for (h in 0 until basalValues) {
val pumpValue = danaRPump.pumpProfiles!![danaRPump.activeProfile][h]
val profileValue = profile.getBasalTimeFromMidnight(h * basalIncrement)
if (abs(pumpValue - profileValue) > pumpDescription.basalStep) {
aapsLogger.debug(LTag.PUMP, "Diff found. Hour: $h Pump: $pumpValue Profile: $profileValue")
return false
}
}
return true
}
override fun lastDataTime(): Long {
return danaRPump.lastConnection
}
override fun getBaseBasalRate(): Double {
return danaRPump.currentBasal
}
override fun getReservoirLevel(): Double {
return danaRPump.reservoirRemainingUnits
}
override fun getBatteryLevel(): Int {
return danaRPump.batteryRemaining
}
@Synchronized
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
detailedBolusInfo.insulin = constraintChecker.applyBolusConstraints(Constraint(detailedBolusInfo.insulin)).value()
return if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) {
val preferencesSpeed = sp.getInt(R.string.key_danars_bolusspeed, 0)
var speed = 12
when (preferencesSpeed) {
0 -> speed = 12
1 -> speed = 30
2 -> speed = 60
}
// RS stores end time for bolus, we need to adjust time
// default delivery speed is 12 sec/U
detailedBolusInfo.date = DateUtil.now() + (speed * detailedBolusInfo.insulin * 1000).toLong()
// 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
val carbs = detailedBolusInfo.carbs
detailedBolusInfo.carbs = 0.0
var carbTime = detailedBolusInfo.carbTime
if (carbTime == 0) carbTime-- // better set 1 min back to prevents clash with insulin
detailedBolusInfo.carbTime = 0
detailedBolusInfoStorage.add(detailedBolusInfo) // will be picked up on reading history
val t = Treatment()
t.isSMB = detailedBolusInfo.isSMB
var connectionOK = false
if (detailedBolusInfo.insulin > 0 || carbs > 0) connectionOK = danaRSService?.bolus(detailedBolusInfo.insulin, carbs.toInt(), DateUtil.now() + T.mins(carbTime.toLong()).msecs(), t) ?: false
val result = PumpEnactResult(injector)
result.success = connectionOK && abs(detailedBolusInfo.insulin - t.insulin) < pumpDesc.bolusStep
result.bolusDelivered = t.insulin
result.carbsDelivered = detailedBolusInfo.carbs
if (!result.success) {
var error = "" + danaRPump.bolusStartErrorCode
when (danaRPump.bolusStartErrorCode) {
0x10 -> error = resourceHelper.gs(R.string.maxbolusviolation)
0x20 -> error = resourceHelper.gs(R.string.commanderror)
0x40 -> error = resourceHelper.gs(R.string.speederror)
0x80 -> error = resourceHelper.gs(R.string.insulinlimitviolation)
}
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, error)
} else result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered)
result
} else {
val result = PumpEnactResult(injector)
result.success = false
result.bolusDelivered = 0.0
result.carbsDelivered = 0.0
result.comment = resourceHelper.gs(R.string.danar_invalidinput)
aapsLogger.error("deliverTreatment: Invalid input")
result
}
}
override fun stopBolusDelivering() {
danaRSService?.bolusStop()
}
// This is called from APS
@Synchronized
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult {
var result = PumpEnactResult(injector)
val absoluteAfterConstrain = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value()
val doTempOff = baseBasalRate - absoluteAfterConstrain == 0.0
val doLowTemp = absoluteAfterConstrain < baseBasalRate
val doHighTemp = absoluteAfterConstrain > baseBasalRate
if (doTempOff) {
// If temp in progress
if (treatmentsPlugin.isTempBasalInProgress) {
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: Stopping temp basal (doTempOff)")
return cancelTempBasal(false)
}
result.success = true
result.enacted = false
result.percent = 100
result.isPercent = true
result.isTempCancel = true
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: doTempOff OK")
return result
}
if (doLowTemp || doHighTemp) {
var percentRate = java.lang.Double.valueOf(absoluteAfterConstrain / baseBasalRate * 100).toInt()
percentRate = if (percentRate < 100) Round.ceilTo(percentRate.toDouble(), 10.0).toInt() else Round.floorTo(percentRate.toDouble(), 10.0).toInt()
if (percentRate > 500) // Special high temp 500/15min
percentRate = 500
// Check if some temp is already in progress
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())
if (activeTemp != null) {
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: currently running: $activeTemp")
// Correct basal already set ?
if (activeTemp.percentRate == percentRate && activeTemp.plannedRemainingMinutes > 4) {
if (!enforceNew) {
result.success = true
result.percent = percentRate
result.enacted = false
result.duration = activeTemp.plannedRemainingMinutes
result.isPercent = true
result.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 mins (doLowTemp || doHighTemp)")
result = if (percentRate == 0 && durationInMinutes > 30) {
setTempBasalPercent(percentRate, durationInMinutes, profile, enforceNew)
} else {
// use special APS temp basal call ... 100+/15min .... 100-/30min
setHighTempBasalPercent(percentRate)
}
if (!result.success) {
aapsLogger.error("setTempBasalAbsolute: Failed to set hightemp basal")
return result
}
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute: hightemp basal set ok")
return result
}
// We should never end here
aapsLogger.error("setTempBasalAbsolute: Internal error")
result.success = false
result.comment = "Internal error"
return result
}
@Synchronized
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean): PumpEnactResult {
val pump = danaRPump
val result = PumpEnactResult(injector)
var percentAfterConstraint = constraintChecker.applyBasalPercentConstraints(Constraint(percent), profile).value()
if (percentAfterConstraint < 0) {
result.isTempCancel = false
result.enacted = false
result.success = false
result.comment = resourceHelper.gs(R.string.danar_invalidinput)
aapsLogger.error("setTempBasalPercent: Invalid input")
return result
}
if (percentAfterConstraint > pumpDescription.maxTempPercent) percentAfterConstraint = pumpDescription.maxTempPercent
val now = System.currentTimeMillis()
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(now)
if (activeTemp != null && activeTemp.percentRate == percentAfterConstraint && activeTemp.plannedRemainingMinutes > 4 && !enforceNew) {
result.enacted = false
result.success = true
result.isTempCancel = false
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
result.duration = pump.tempBasalRemainingMin
result.percent = pump.tempBasalPercent
result.isPercent = true
aapsLogger.debug(LTag.PUMP, "setTempBasalPercent: Correct value already set")
return result
}
val connectionOK: Boolean
connectionOK = if (durationInMinutes == 15 || durationInMinutes == 30) {
danaRSService?.tempBasalShortDuration(percentAfterConstraint, durationInMinutes) ?: false
} else {
val durationInHours = max(durationInMinutes / 60, 1)
danaRSService?.tempBasal(percentAfterConstraint, durationInHours) ?: false
}
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percentAfterConstraint) {
result.enacted = true
result.success = true
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
result.isTempCancel = false
result.duration = pump.tempBasalRemainingMin
result.percent = pump.tempBasalPercent
result.isPercent = true
aapsLogger.debug(LTag.PUMP, "setTempBasalPercent: OK")
return result
}
result.enacted = false
result.success = false
result.comment = resourceHelper.gs(R.string.tempbasaldeliveryerror)
aapsLogger.error("setTempBasalPercent: Failed to set temp basal")
return result
}
@Synchronized private fun setHighTempBasalPercent(percent: Int): PumpEnactResult {
val pump = danaRPump
val result = PumpEnactResult(injector)
val connectionOK = danaRSService?.highTempBasal(percent) ?: false
if (connectionOK && pump.isTempBasalInProgress && pump.tempBasalPercent == percent) {
result.enacted = true
result.success = true
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
result.isTempCancel = false
result.duration = pump.tempBasalRemainingMin
result.percent = pump.tempBasalPercent
result.isPercent = true
aapsLogger.debug(LTag.PUMP, "setHighTempBasalPercent: OK")
return result
}
result.enacted = false
result.success = false
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly)
aapsLogger.error("setHighTempBasalPercent: Failed to set temp basal")
return result
}
@Synchronized
override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult {
val pump = danaRPump
var insulinAfterConstraint = constraintChecker.applyExtendedBolusConstraints(Constraint(insulin)).value()
// needs to be rounded
val durationInHalfHours = max(durationInMinutes / 30, 1)
insulinAfterConstraint = Round.roundTo(insulinAfterConstraint, pumpDescription.extendedBolusStep)
val result = PumpEnactResult(injector)
val runningEB = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis())
if (runningEB != null && abs(runningEB.insulin - insulinAfterConstraint) < pumpDescription.extendedBolusStep) {
result.enacted = false
result.success = true
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
result.duration = pump.extendedBolusRemainingMinutes
result.absolute = pump.extendedBolusAbsoluteRate
result.isPercent = false
result.isTempCancel = false
aapsLogger.debug(LTag.PUMP, "setExtendedBolus: Correct extended bolus already set. Current: " + pump.extendedBolusAmount + " Asked: " + insulinAfterConstraint)
return result
}
val connectionOK = danaRSService?.extendedBolus(insulinAfterConstraint, durationInHalfHours) ?: false
if (connectionOK && pump.isExtendedInProgress && abs(pump.extendedBolusAbsoluteRate - insulinAfterConstraint) < pumpDescription.extendedBolusStep) {
result.enacted = true
result.success = true
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
result.isTempCancel = false
result.duration = pump.extendedBolusRemainingMinutes
result.absolute = pump.extendedBolusAbsoluteRate
result.bolusDelivered = pump.extendedBolusAmount
result.isPercent = false
aapsLogger.debug(LTag.PUMP, "setExtendedBolus: OK")
return result
}
result.enacted = false
result.success = false
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly)
aapsLogger.error("setExtendedBolus: Failed to extended bolus")
return result
}
@Synchronized
override fun cancelTempBasal(force: Boolean): PumpEnactResult {
val result = PumpEnactResult(injector)
val runningTB = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())
if (runningTB != null) {
danaRSService?.tempBasalStop()
result.enacted = true
result.isTempCancel = true
}
return if (!danaRPump.isTempBasalInProgress) {
result.success = true
result.isTempCancel = true
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
aapsLogger.debug(LTag.PUMP, "cancelRealTempBasal: OK")
result
} else {
result.success = false
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly)
result.isTempCancel = true
aapsLogger.error("cancelRealTempBasal: Failed to cancel temp basal")
result
}
}
@Synchronized override fun cancelExtendedBolus(): PumpEnactResult {
val result = PumpEnactResult(injector)
val runningEB = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis())
if (runningEB != null) {
danaRSService?.extendedBolusStop()
result.enacted = true
result.isTempCancel = true
}
return if (!danaRPump.isExtendedInProgress) {
result.success = true
result.comment = resourceHelper.gs(R.string.virtualpump_resultok)
aapsLogger.debug(LTag.PUMP, "cancelExtendedBolus: OK")
result
} else {
result.success = false
result.comment = resourceHelper.gs(R.string.danar_valuenotsetproperly)
aapsLogger.error("cancelExtendedBolus: Failed to cancel extended bolus")
result
}
}
override fun getJSONStatus(profile: Profile, profileName: String): JSONObject {
val pump = danaRPump
val now = System.currentTimeMillis()
if (pump.lastConnection + 5 * 60 * 1000L < System.currentTimeMillis()) {
return JSONObject()
}
val pumpJson = JSONObject()
val battery = JSONObject()
val status = JSONObject()
val extended = JSONObject()
try {
battery.put("percent", pump.batteryRemaining)
status.put("status", if (pump.pumpSuspended) "suspended" else "normal")
status.put("timestamp", DateUtil.toISOString(pump.lastConnection))
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)
if (pump.lastBolusTime != 0L) {
extended.put("LastBolus", DateUtil.dateAndTimeString(pump.lastBolusTime))
extended.put("LastBolusAmount", pump.lastBolusAmount)
}
val tb = treatmentsPlugin.getTempBasalFromHistory(now)
if (tb != null) {
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile))
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date))
extended.put("TempBasalRemaining", tb.plannedRemainingMinutes)
}
val eb = treatmentsPlugin.getExtendedBolusFromHistory(now)
if (eb != null) {
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate())
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date))
extended.put("ExtendedBolusRemaining", eb.plannedRemainingMinutes)
}
extended.put("BaseBasalRate", baseBasalRate)
try {
extended.put("ActiveProfile", profileFunction.getProfileName())
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
pumpJson.put("battery", battery)
pumpJson.put("status", status)
pumpJson.put("extended", extended)
pumpJson.put("reservoir", pump.reservoirRemainingUnits.toInt())
pumpJson.put("clock", DateUtil.toISOString(now))
} catch (e: JSONException) {
aapsLogger.error("Unhandled exception", e)
}
return pumpJson
}
override fun manufacturer(): ManufacturerType {
return ManufacturerType.Sooil
}
override fun model(): PumpType {
return PumpType.DanaRS
}
override fun serialNumber(): String {
return danaRPump.serialNumber
}
override fun getPumpDescription(): PumpDescription {
return pumpDesc
}
override fun shortStatus(veryShort: Boolean): String {
val pump = danaRPump
var ret = ""
if (pump.lastConnection != 0L) {
val agoMillis = System.currentTimeMillis() - pump.lastConnection
val agoMin = (agoMillis / 60.0 / 1000.0).toInt()
ret += "LastConn: $agoMin minago\n"
}
if (pump.lastBolusTime != 0L)
ret += "LastBolus: ${DecimalFormatter.to2Decimal(pump.lastBolusAmount)}U @${DateFormat.format("HH:mm", pump.lastBolusTime)}"
val activeTemp = treatmentsPlugin.getRealTempBasalFromHistory(System.currentTimeMillis())
if (activeTemp != null)
ret += "Temp: ${activeTemp.toStringFull()}"
val activeExtendedBolus = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis())
if (activeExtendedBolus != null)
ret += "Extended: $activeExtendedBolus\n"
if (!veryShort) {
ret += "TDD: ${DecimalFormatter.to0Decimal(pump.dailyTotalUnits)} / ${pump.maxDailyTotalUnits} U"
}
ret += "Reserv: ${DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits)} U"
ret += "Batt: ${pump.batteryRemaining}"
return ret
}
override fun isFakingTempsByExtendedBoluses(): Boolean = false
override fun loadTDDs(): PumpEnactResult = loadHistory(RecordTypes.RECORD_TYPE_DAILY)
override fun getCustomActions(): List<CustomAction>? = null
override fun executeCustomAction(customActionType: CustomActionType) {}
override fun canHandleDST(): Boolean = false
override fun timeDateOrTimeZoneChanged() {}
}

View file

@ -18,7 +18,6 @@ class DanaRSMessageHashTable @Inject constructor(
rxBus: RxBusWrapper,
resourceHelper: ResourceHelper,
danaRPump: DanaRPump,
danaRSPlugin: DanaRSPlugin,
activePlugin: ActivePluginProvider,
constraintChecker: ConstraintChecker,
detailedBolusInfoStorage: DetailedBolusInfoStorage
@ -62,16 +61,16 @@ class DanaRSMessageHashTable @Inject constructor(
put(DanaRS_Packet_Bolus_Set_Dual_Bolus(aapsLogger))
put(DanaRS_Packet_Bolus_Set_Extended_Bolus(aapsLogger))
put(DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel(aapsLogger))
put(DanaRS_Packet_Bolus_Set_Step_Bolus_Start(aapsLogger, danaRSPlugin, constraintChecker))
put(DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(aapsLogger, rxBus, resourceHelper, danaRSPlugin))
put(DanaRS_Packet_Bolus_Set_Step_Bolus_Start(aapsLogger, danaRPump, constraintChecker))
put(DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(aapsLogger, rxBus, resourceHelper, danaRPump))
put(DanaRS_Packet_Etc_Keep_Connection(aapsLogger))
put(DanaRS_Packet_Etc_Set_History_Save(aapsLogger))
put(DanaRS_Packet_General_Delivery_Status(aapsLogger))
put(DanaRS_Packet_General_Get_Password(aapsLogger, danaRPump))
put(DanaRS_Packet_General_Initial_Screen_Information(aapsLogger, danaRPump))
put(DanaRS_Packet_Notify_Alarm(aapsLogger, resourceHelper, rxBus))
put(DanaRS_Packet_Notify_Delivery_Complete(aapsLogger, rxBus, resourceHelper, danaRSPlugin))
put(DanaRS_Packet_Notify_Delivery_Rate_Display(aapsLogger, rxBus, resourceHelper, danaRSPlugin))
put(DanaRS_Packet_Notify_Delivery_Complete(aapsLogger, rxBus, resourceHelper, danaRPump))
put(DanaRS_Packet_Notify_Delivery_Rate_Display(aapsLogger, rxBus, resourceHelper, danaRPump))
put(DanaRS_Packet_Notify_Missed_Bolus_Alarm(aapsLogger))
put(DanaRS_Packet_Option_Get_Pump_Time(aapsLogger, danaRPump))
put(DanaRS_Packet_Option_Get_User_Option(aapsLogger, danaRPump))
@ -99,7 +98,7 @@ class DanaRSMessageHashTable @Inject constructor(
put(DanaRS_Packet_History_Temporary(aapsLogger, rxBus))
// APS
put(DanaRS_Packet_APS_Basal_Set_Temporary_Basal(aapsLogger, 0))
put(DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRSPlugin, detailedBolusInfoStorage, 0))
put(DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRPump, detailedBolusInfoStorage, 0))
put(DanaRS_Packet_APS_Set_Event_History(aapsLogger, 0, 0, 0, 0))
// v3
put(DanaRS_Packet_General_Get_Shipping_Version(aapsLogger, danaRPump))

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.db.ExtendedBolus
@ -13,7 +12,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.*
@ -23,7 +22,7 @@ open class DanaRS_Packet_APS_History_Events(
private val rxBus: RxBusWrapper,
private val resourceHelper: ResourceHelper,
private val activePlugin: ActivePluginProvider,
private val danaRSPlugin: DanaRSPlugin,
private val danaRPump: DanaRPump,
private val detailedBolusInfoStorage: DetailedBolusInfoStorage,
private var from: Long
) : DanaRS_Packet() {
@ -50,7 +49,7 @@ open class DanaRS_Packet_APS_History_Events(
min = cal[Calendar.MINUTE]
sec = cal[Calendar.SECOND]
aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + DateUtil.dateAndTimeString(cal.timeInMillis))
danaRSPlugin.apsHistoryDone = false
danaRPump.historyDoneReceived = false
}
override fun getRequestParams(): ByteArray {
@ -68,7 +67,7 @@ open class DanaRS_Packet_APS_History_Events(
val recordCode = intFromBuff(data, 0, 1).toByte()
// Last record
if (recordCode == 0xFF.toByte()) {
danaRSPlugin.apsHistoryDone = true
danaRPump.historyDoneReceived = true
aapsLogger.debug(LTag.PUMPCOMM, "Last record received")
return
}
@ -191,7 +190,7 @@ open class DanaRS_Packet_APS_History_Events(
status = "UNKNOWN " + DateUtil.timeString(datetime)
}
}
if (datetime > danaRSPlugin.lastEventTimeLoaded) danaRSPlugin.lastEventTimeLoaded = datetime
if (datetime > danaRPump.lastEventTimeLoaded) danaRPump.lastEventTimeLoaded = datetime
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.processinghistory) + ": " + status))
}

View file

@ -1,15 +1,15 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
class DanaRS_Packet_Bolus_Set_Step_Bolus_Start(
private val aapsLogger: AAPSLogger,
private val danaRSPlugin: DanaRSPlugin,
private val danaRPump: DanaRPump,
constraintChecker: ConstraintChecker,
private var amount: Double = 0.0,
private var speed: Int = 0
@ -34,12 +34,12 @@ class DanaRS_Packet_Bolus_Set_Step_Bolus_Start(
}
override fun handleMessage(data: ByteArray) {
danaRSPlugin.bolusStartErrorCode = intFromBuff(data, 0, 1)
if (danaRSPlugin.bolusStartErrorCode == 0) {
danaRPump.bolusStartErrorCode = intFromBuff(data, 0, 1)
if (danaRPump.bolusStartErrorCode == 0) {
failed = false
aapsLogger.debug(LTag.PUMPCOMM, "Result OK")
} else {
aapsLogger.error("Result Error: ${danaRSPlugin.bolusStartErrorCode}")
aapsLogger.error("Result Error: ${danaRPump.bolusStartErrorCode}")
failed = true
}
}

View file

@ -1,19 +1,19 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.utils.resources.ResourceHelper
open class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
private val resourceHelper: ResourceHelper,
private val danaRSPlugin: DanaRSPlugin
private val danaRPump: DanaRPump
) : DanaRS_Packet() {
@ -31,10 +31,10 @@ open class DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(
failed = true
}
val bolusingEvent = EventOverviewBolusProgress
danaRSPlugin.bolusStopped = true
if (!danaRSPlugin.bolusStopForced) {
danaRPump.bolusStopped = true
if (!danaRPump.bolusStopForced) {
// delivery ended without user intervention
danaRSPlugin.bolusingTreatment.insulin = danaRSPlugin.bolusAmountToBeDelivered
danaRPump.bolusingTreatment?.insulin = danaRPump.bolusAmountToBeDelivered
bolusingEvent.status = resourceHelper.gs(R.string.overview_bolusprogress_delivered)
bolusingEvent.percent = 100
} else {

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.min
@ -14,7 +14,7 @@ class DanaRS_Packet_Notify_Delivery_Complete(
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
private val resourceHelper: ResourceHelper,
private val danaRSPlugin: DanaRSPlugin
private val danaRPump: DanaRPump
) : DanaRS_Packet() {
init {
@ -25,12 +25,12 @@ class DanaRS_Packet_Notify_Delivery_Complete(
override fun handleMessage(data: ByteArray) {
val deliveredInsulin = byteArrayToInt(getBytes(data, DATA_START, 2)) / 100.0
danaRSPlugin.bolusingTreatment.insulin = deliveredInsulin
danaRPump.bolusingTreatment?.insulin = deliveredInsulin
val bolusingEvent = EventOverviewBolusProgress
bolusingEvent.status = resourceHelper.gs(R.string.bolusdelivering, deliveredInsulin)
bolusingEvent.t = danaRSPlugin.bolusingTreatment
bolusingEvent.percent = min((deliveredInsulin / danaRSPlugin.bolusAmountToBeDelivered * 100).toInt(), 100)
danaRSPlugin.bolusDone = true
bolusingEvent.t = danaRPump.bolusingTreatment
bolusingEvent.percent = min((deliveredInsulin / danaRPump.bolusAmountToBeDelivered * 100).toInt(), 100)
danaRPump.bolusDone = true
rxBus.send(bolusingEvent)
aapsLogger.debug(LTag.PUMPCOMM, "Delivered insulin: $deliveredInsulin")
}

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlin.math.min
@ -14,7 +14,7 @@ class DanaRS_Packet_Notify_Delivery_Rate_Display(
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
private val resourceHelper: ResourceHelper,
private val danaRSPlugin: DanaRSPlugin
private val danaRPump: DanaRPump
) : DanaRS_Packet() {
@ -25,12 +25,12 @@ class DanaRS_Packet_Notify_Delivery_Rate_Display(
override fun handleMessage(data: ByteArray) {
val deliveredInsulin = byteArrayToInt(getBytes(data, DATA_START, 2)) / 100.0
danaRSPlugin.bolusProgressLastTimeStamp = System.currentTimeMillis()
danaRSPlugin.bolusingTreatment.insulin = deliveredInsulin
danaRPump.bolusProgressLastTimeStamp = System.currentTimeMillis()
danaRPump.bolusingTreatment?.insulin = deliveredInsulin
val bolusingEvent = EventOverviewBolusProgress
bolusingEvent.status = resourceHelper.gs(R.string.bolusdelivering, deliveredInsulin)
bolusingEvent.t = danaRSPlugin.bolusingTreatment
bolusingEvent.percent = min((deliveredInsulin / danaRSPlugin.bolusAmountToBeDelivered * 100).toInt(), 100)
bolusingEvent.t = danaRPump.bolusingTreatment
bolusingEvent.percent = min((deliveredInsulin / danaRPump.bolusAmountToBeDelivered * 100).toInt(), 100)
failed = bolusingEvent.percent < 100
rxBus.send(bolusingEvent)
aapsLogger.debug(LTag.PUMPCOMM, "Delivered insulin so far: $deliveredInsulin")

View file

@ -615,9 +615,8 @@ class BLEComm @Inject internal constructor(
}
// the rest of packets
fun sendMessage(message: DanaRS_Packet?) {
fun sendMessage(message: DanaRS_Packet) {
processedMessage = message
if (message == null) return
val command = byteArrayOf(message.type.toByte(), message.opCode.toByte())
val params = message.requestParams
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + message.friendlyName + " " + DanaRS_Packet.toHexString(command) + " " + DanaRS_Packet.toHexString(params))

View file

@ -1,565 +0,0 @@
package info.nightscout.androidaps.plugins.pump.danaRS.services;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import javax.inject.Inject;
import dagger.android.DaggerService;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.dialogs.BolusProgressDialog;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.events.EventProfileNeedsUpdate;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.PumpInterface;
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.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump;
import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes;
import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus;
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRSMessageHashTable;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_APS_Basal_Set_Temporary_Basal;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_APS_History_Events;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_APS_Set_Event_History;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Get_Basal_Rate;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Get_Profile_Number;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Get_Temporary_Basal_State;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Profile_Basal_Rate;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Profile_Number;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Basal_Set_Temporary_Basal;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Bolus_Option;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_CIR_CF_Array;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Calculation_Information;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Extended_Bolus_State;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Get_Step_Bolus_Information;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Start;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Bolus_Set_Step_Bolus_Stop;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Get_Pump_Check;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Get_Shipping_Information;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Initial_Screen_Information;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_General_Set_History_Upload_Mode;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Alarm;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Basal;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Blood_Glucose;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Bolus;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Carbohydrate;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Daily;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Prime;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Refill;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_History_Suspend;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Get_Pump_Time;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Get_User_Option;
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRS_Packet_Option_Set_Pump_Time;
import info.nightscout.androidaps.plugins.treatments.Treatment;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class DanaRSService extends DaggerService {
@Inject HasAndroidInjector injector;
@Inject AAPSLogger aapsLogger;
@Inject RxBusWrapper rxBus;
@Inject SP sp;
@Inject ResourceHelper resourceHelper;
@Inject ProfileFunction profileFunction;
@Inject CommandQueueProvider commandQueue;
@Inject Context context;
@Inject DanaRSPlugin danaRSPlugin;
@Inject DanaRPump danaRPump;
@Inject DanaRSMessageHashTable danaRSMessageHashTable;
@Inject ActivePluginProvider activePlugin;
@Inject ConstraintChecker constraintChecker;
@Inject DetailedBolusInfoStorage detailedBolusInfoStorage;
@Inject BLEComm bleComm;
@Inject FabricPrivacy fabricPrivacy;
private CompositeDisposable disposable = new CompositeDisposable();
private IBinder mBinder = new LocalBinder();
private Treatment bolusingTreatment = null;
private long lastHistoryFetched = 0;
private long lastApproachingDailyLimit = 0;
@Override
public void onCreate() {
super.onCreate();
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
aapsLogger.debug(LTag.PUMPCOMM, "EventAppExit received");
stopSelf();
}, fabricPrivacy::logException)
);
}
@Override
public void onDestroy() {
disposable.clear();
super.onDestroy();
}
public boolean isConnected() {
return bleComm.isConnected();
}
public boolean isConnecting() {
return bleComm.isConnecting();
}
public boolean connect(String from, String address) {
return bleComm.connect(from, address);
}
public void stopConnecting() {
bleComm.stopConnecting();
}
public void disconnect(String from) {
bleComm.disconnect(from);
}
@SuppressWarnings("unused")
public void sendMessage(DanaRS_Packet message) {
bleComm.sendMessage(message);
}
public void getPumpStatus() {
try {
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpstatus)));
bleComm.sendMessage(new DanaRS_Packet_General_Initial_Screen_Information(aapsLogger, danaRPump));
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingextendedbolusstatus)));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State(aapsLogger, danaRPump));
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingbolusstatus)));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information(aapsLogger, danaRPump)); // last bolus, bolusStep, maxBolus
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingtempbasalstatus)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump));
danaRPump.setLastConnection(System.currentTimeMillis());
Profile profile = profileFunction.getProfile();
PumpInterface pump = activePlugin.getActivePump();
if (profile != null && Math.abs(danaRPump.getCurrentBasal() - profile.getBasal()) >= pump.getPumpDescription().basalStep) {
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate(aapsLogger, rxBus, resourceHelper, danaRPump)); // basal profile, basalStep, maxBasal
if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) {
rxBus.send(new EventProfileNeedsUpdate());
}
}
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumptime)));
bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time(aapsLogger, danaRPump));
long timeDiff = (danaRPump.getPumpTime() - System.currentTimeMillis()) / 1000L;
if (danaRPump.getPumpTime() == 0) {
// initial handshake was not successfull
// deinitialize pump
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;
}
long now = System.currentTimeMillis();
if (danaRPump.getLastSettingsRead() + 60 * 60 * 1000L < now || !pump.isInitialized()) {
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings)));
bleComm.sendMessage(new DanaRS_Packet_General_Get_Shipping_Information(aapsLogger, danaRPump)); // serial no
bleComm.sendMessage(new DanaRS_Packet_General_Get_Pump_Check(aapsLogger, danaRPump, rxBus, resourceHelper)); // firmware
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Profile_Number(aapsLogger, danaRPump));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Bolus_Option(aapsLogger, rxBus, resourceHelper, danaRPump)); // isExtendedEnabled
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Basal_Rate(aapsLogger, rxBus, resourceHelper, danaRPump)); // basal profile, basalStep, maxBasal
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Calculation_Information(aapsLogger, danaRPump)); // target
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_CIR_CF_Array(aapsLogger, danaRPump));
bleComm.sendMessage(new DanaRS_Packet_Option_Get_User_Option(aapsLogger, danaRPump)); // Getting user options
danaRPump.setLastSettingsRead(now);
}
aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: " + timeDiff + " seconds");
if (Math.abs(timeDiff) > 3) {
if (Math.abs(timeDiff) > 60 * 60 * 1.5) {
aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: " + timeDiff + " seconds - large difference");
//If time-diff is very large, warn user until we can synchronize history readings properly
Intent i = new Intent(context, ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.error);
i.putExtra("status", resourceHelper.gs(R.string.largetimediff));
i.putExtra("title", resourceHelper.gs(R.string.largetimedifftitle));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
//deinitialize pump
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;
} else {
if (danaRPump.getProtocol() >= 6) {
bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(aapsLogger, DateUtil.now()));
} else {
waitForWholeMinute(); // Dana can set only whole minute
// add 10sec to be sure we are over minute (will be cutted off anyway)
bleComm.sendMessage(new DanaRS_Packet_Option_Set_Pump_Time(aapsLogger, DateUtil.now() + T.secs(10).msecs()));
}
bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time(aapsLogger, danaRPump));
timeDiff = (danaRPump.getPumpTime() - System.currentTimeMillis()) / 1000L;
aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: " + timeDiff + " seconds");
}
}
loadEvents();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
//NSUpload.uploadDeviceStatus();
if (danaRPump.getDailyTotalUnits() > danaRPump.getMaxDailyTotalUnits() * Constants.dailyLimitWarning) {
aapsLogger.debug(LTag.PUMPCOMM, "Approaching daily limit: " + danaRPump.getDailyTotalUnits() + "/" + danaRPump.getMaxDailyTotalUnits());
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
Notification reportFail = new Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT);
rxBus.send(new EventNewNotification(reportFail));
NSUpload.uploadError(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaRPump.getDailyTotalUnits() + "/" + danaRPump.getMaxDailyTotalUnits() + "U");
lastApproachingDailyLimit = System.currentTimeMillis();
}
}
} catch (Exception e) {
aapsLogger.error(LTag.PUMPCOMM, "Unhandled exception", e);
}
aapsLogger.debug(LTag.PUMPCOMM, "Pump status loaded");
}
public PumpEnactResult loadEvents() {
if (!danaRSPlugin.isInitialized()) {
PumpEnactResult result = new PumpEnactResult(injector).success(false);
result.comment = "pump not initialized";
return result;
}
SystemClock.sleep(1000);
DanaRS_Packet_APS_History_Events msg;
if (lastHistoryFetched == 0) {
msg = new DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRSPlugin, detailedBolusInfoStorage, 0);
aapsLogger.debug(LTag.PUMPCOMM, "Loading complete event history");
} else {
msg = new DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRSPlugin, detailedBolusInfoStorage, lastHistoryFetched);
aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + DateUtil.dateAndTimeString(lastHistoryFetched));
}
bleComm.sendMessage(msg);
while (!danaRSPlugin.apsHistoryDone && bleComm.isConnected()) {
SystemClock.sleep(100);
}
if (danaRSPlugin.lastEventTimeLoaded != 0)
lastHistoryFetched = danaRSPlugin.lastEventTimeLoaded - T.mins(1).msecs();
else
lastHistoryFetched = 0;
aapsLogger.debug(LTag.PUMPCOMM, "Events loaded");
danaRPump.setLastConnection(System.currentTimeMillis());
return new PumpEnactResult(injector).success(true);
}
public PumpEnactResult setUserSettings() {
bleComm.sendMessage(new DanaRS_Packet_Option_Get_User_Option(aapsLogger, danaRPump));
return new PumpEnactResult(injector).success(true);
}
public boolean bolus(final double insulin, int carbs, long carbtime, Treatment t) {
if (!isConnected()) return false;
if (BolusProgressDialog.stopPressed) return false;
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.startingbolus)));
bolusingTreatment = t;
final int preferencesSpeed = sp.getInt(R.string.key_danars_bolusspeed, 0);
danaRSPlugin.bolusingTreatment = t;
danaRSPlugin.bolusAmountToBeDelivered = insulin;
danaRSPlugin.bolusStopped = false;
danaRSPlugin.bolusStopForced = false;
danaRSPlugin.bolusProgressLastTimeStamp = DateUtil.now();
DanaRS_Packet_Bolus_Set_Step_Bolus_Start start = new DanaRS_Packet_Bolus_Set_Step_Bolus_Start(aapsLogger, danaRSPlugin, constraintChecker, insulin, preferencesSpeed);
if (carbs > 0) {
// MsgSetCarbsEntry msg = new MsgSetCarbsEntry(carbtime, carbs); ####
// bleComm.sendMessage(msg);
DanaRS_Packet_APS_Set_Event_History msgSetHistoryEntry_v2 = new DanaRS_Packet_APS_Set_Event_History(aapsLogger, DanaRPump.CARBS, carbtime, carbs, 0);
bleComm.sendMessage(msgSetHistoryEntry_v2);
lastHistoryFetched = Math.min(lastHistoryFetched, carbtime - T.mins(1).msecs());
}
final long bolusStart = System.currentTimeMillis();
if (insulin > 0) {
if (!danaRSPlugin.bolusStopped) {
bleComm.sendMessage(start);
} else {
t.insulin = 0d;
return false;
}
while (!danaRSPlugin.bolusStopped && !start.failed && !danaRSPlugin.bolusDone) {
SystemClock.sleep(100);
if ((System.currentTimeMillis() - danaRSPlugin.bolusProgressLastTimeStamp) > 15 * 1000L) { // if i didn't receive status for more than 20 sec expecting broken comm
danaRSPlugin.bolusStopped = true;
danaRSPlugin.bolusStopForced = true;
aapsLogger.debug(LTag.PUMPCOMM, "Communication stopped");
}
}
}
final EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(t);
bolusingEvent.setPercent(99);
bolusingTreatment = null;
int speed = 12;
switch (preferencesSpeed) {
case 0:
speed = 12;
break;
case 1:
speed = 30;
break;
case 2:
speed = 60;
break;
}
long bolusDurationInMSec = (long) (insulin * speed * 1000);
long expectedEnd = bolusStart + bolusDurationInMSec + 2000;
while (System.currentTimeMillis() < expectedEnd) {
long waitTime = expectedEnd - System.currentTimeMillis();
bolusingEvent.setStatus(String.format(resourceHelper.gs(R.string.waitingforestimatedbolusend), waitTime / 1000));
rxBus.send(bolusingEvent);
SystemClock.sleep(1000);
}
// do not call loadEvents() directly, reconnection may be needed
commandQueue.loadEvents(new Callback() {
@Override
public void run() {
// reread bolus status
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.gettingbolusstatus)));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Step_Bolus_Information(aapsLogger, danaRPump)); // last bolus
bolusingEvent.setPercent(100);
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.disconnecting)));
}
});
return !start.failed;
}
public void bolusStop() {
aapsLogger.debug(LTag.PUMPCOMM, "bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
DanaRS_Packet_Bolus_Set_Step_Bolus_Stop stop = new DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(aapsLogger, rxBus, resourceHelper, danaRSPlugin);
danaRSPlugin.bolusStopForced = true;
if (isConnected()) {
bleComm.sendMessage(stop);
while (!danaRSPlugin.bolusStopped) {
bleComm.sendMessage(stop);
SystemClock.sleep(200);
}
} else {
danaRSPlugin.bolusStopped = true;
}
}
public boolean tempBasal(Integer percent, int durationInHours) {
if (!isConnected()) return false;
if (danaRPump.isTempBasalInProgress()) {
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger));
SystemClock.sleep(500);
}
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Temporary_Basal(aapsLogger, percent, durationInHours));
SystemClock.sleep(200);
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump));
loadEvents();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public boolean highTempBasal(Integer percent) {
if (danaRPump.isTempBasalInProgress()) {
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger));
SystemClock.sleep(500);
}
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_APS_Basal_Set_Temporary_Basal(aapsLogger, percent));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump));
loadEvents();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public boolean tempBasalShortDuration(Integer percent, int durationInMinutes) {
if (durationInMinutes != 15 && durationInMinutes != 30) {
aapsLogger.error(LTag.PUMPCOMM, "Wrong duration param");
return false;
}
if (danaRPump.isTempBasalInProgress()) {
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger));
SystemClock.sleep(500);
}
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_APS_Basal_Set_Temporary_Basal(aapsLogger, percent));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump));
loadEvents();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public boolean tempBasalStop() {
if (!isConnected()) return false;
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)));
bleComm.sendMessage(new DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger));
bleComm.sendMessage(new DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump));
loadEvents();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public boolean extendedBolus(Double insulin, int durationInHalfHours) {
if (!isConnected()) return false;
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.settingextendedbolus)));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Set_Extended_Bolus(aapsLogger, insulin, durationInHalfHours));
SystemClock.sleep(200);
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State(aapsLogger, danaRPump));
loadEvents();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public boolean extendedBolusStop() {
if (!isConnected()) return false;
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingextendedbolus)));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel(aapsLogger));
bleComm.sendMessage(new DanaRS_Packet_Bolus_Get_Extended_Bolus_State(aapsLogger, danaRPump));
loadEvents();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public boolean updateBasalsInPump(Profile profile) {
if (!isConnected()) return false;
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.updatingbasalrates)));
Double[] basal = danaRPump.buildDanaRProfileRecord(profile);
DanaRS_Packet_Basal_Set_Profile_Basal_Rate msgSet = new DanaRS_Packet_Basal_Set_Profile_Basal_Rate(aapsLogger, 0, basal);
bleComm.sendMessage(msgSet);
DanaRS_Packet_Basal_Set_Profile_Number msgActivate = new DanaRS_Packet_Basal_Set_Profile_Number(aapsLogger, 0);
bleComm.sendMessage(msgActivate);
danaRPump.setLastSettingsRead(0); // force read full settings
getPumpStatus();
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
return true;
}
public PumpEnactResult loadHistory(byte type) {
PumpEnactResult result = new PumpEnactResult(injector);
if (!isConnected()) return result;
DanaRS_Packet_History_ msg = null;
switch (type) {
case RecordTypes.RECORD_TYPE_ALARM:
msg = new DanaRS_Packet_History_Alarm(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_PRIME:
msg = new DanaRS_Packet_History_Prime(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_BASALHOUR:
msg = new DanaRS_Packet_History_Basal(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_BOLUS:
msg = new DanaRS_Packet_History_Bolus(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_CARBO:
msg = new DanaRS_Packet_History_Carbohydrate(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_DAILY:
msg = new DanaRS_Packet_History_Daily(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_GLUCOSE:
msg = new DanaRS_Packet_History_Blood_Glucose(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_REFILL:
msg = new DanaRS_Packet_History_Refill(aapsLogger, rxBus);
break;
case RecordTypes.RECORD_TYPE_SUSPEND:
msg = new DanaRS_Packet_History_Suspend(aapsLogger, rxBus);
break;
}
if (msg != null) {
bleComm.sendMessage(new DanaRS_Packet_General_Set_History_Upload_Mode(aapsLogger, 1));
SystemClock.sleep(200);
bleComm.sendMessage(msg);
while (!msg.getDone() && isConnected()) {
SystemClock.sleep(100);
}
SystemClock.sleep(200);
bleComm.sendMessage(new DanaRS_Packet_General_Set_History_Upload_Mode(aapsLogger, 0));
}
result.success = true;
result.comment = "OK";
return result;
}
public class LocalBinder extends Binder {
public DanaRSService getServiceInstance() {
return DanaRSService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
void waitForWholeMinute() {
while (true) {
long time = DateUtil.now();
long timeToWholeMinute = (60000 - time % 60000);
if (timeToWholeMinute > 59800 || timeToWholeMinute < 300)
break;
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.waitingfortimesynchronization, (int) (timeToWholeMinute / 1000))));
SystemClock.sleep(Math.min(timeToWholeMinute, 100));
}
}
}

View file

@ -0,0 +1,462 @@
package info.nightscout.androidaps.plugins.pump.danaRS.services
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.os.SystemClock
import dagger.android.DaggerService
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.dialogs.BolusProgressDialog
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.events.EventInitializationChanged
import info.nightscout.androidaps.events.EventProfileNeedsUpdate
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
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.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaR.comm.RecordTypes
import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaRS.comm.*
import info.nightscout.androidaps.plugins.treatments.Treatment
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.min
class DanaRSService : DaggerService() {
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var context: Context
@Inject lateinit var danaRSPlugin: DanaRSPlugin
@Inject lateinit var danaRPump: DanaRPump
@Inject lateinit var danaRSMessageHashTable: DanaRSMessageHashTable
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var constraintChecker: ConstraintChecker
@Inject lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage
@Inject lateinit var bleComm: BLEComm
@Inject lateinit var fabricPrivacy: FabricPrivacy
private val disposable = CompositeDisposable()
private val mBinder: IBinder = LocalBinder()
private var bolusingTreatment: Treatment? = null
private var lastHistoryFetched: Long = 0
private var lastApproachingDailyLimit: Long = 0
override fun onCreate() {
super.onCreate()
disposable.add(rxBus
.toObservable(EventAppExit::class.java)
.observeOn(Schedulers.io())
.subscribe({ stopSelf() }) { fabricPrivacy.logException(it) }
)
}
override fun onDestroy() {
disposable.clear()
super.onDestroy()
}
val isConnected: Boolean
get() = bleComm.isConnected
val isConnecting: Boolean
get() = bleComm.isConnecting
fun connect(from: String, address: String): Boolean {
return bleComm.connect(from, address)
}
fun stopConnecting() {
bleComm.stopConnecting()
}
fun disconnect(from: String) {
bleComm.disconnect(from)
}
fun sendMessage(message: DanaRS_Packet) {
bleComm.sendMessage(message)
}
fun readPumpStatus() {
try {
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpstatus)))
sendMessage(DanaRS_Packet_General_Initial_Screen_Information(aapsLogger, danaRPump))
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingextendedbolusstatus)))
sendMessage(DanaRS_Packet_Bolus_Get_Extended_Bolus_State(aapsLogger, danaRPump))
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingbolusstatus)))
sendMessage(DanaRS_Packet_Bolus_Get_Step_Bolus_Information(aapsLogger, danaRPump)) // last bolus, bolusStep, maxBolus
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingtempbasalstatus)))
sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump))
danaRPump.lastConnection = System.currentTimeMillis()
val profile = profileFunction.getProfile()
val pump = activePlugin.activePump
if (profile != null && abs(danaRPump.currentBasal - profile.basal) >= pump.pumpDescription.basalStep) {
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings)))
sendMessage(DanaRS_Packet_Basal_Get_Basal_Rate(aapsLogger, rxBus, resourceHelper, danaRPump)) // basal profile, basalStep, maxBasal
if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) {
rxBus.send(EventProfileNeedsUpdate())
}
}
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumptime)))
sendMessage(DanaRS_Packet_Option_Get_Pump_Time(aapsLogger, danaRPump))
var timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L
if (danaRPump.pumpTime == 0L) {
// initial handshake was not successful
// de-initialize pump
danaRPump.reset()
rxBus.send(EventDanaRNewStatus())
rxBus.send(EventInitializationChanged())
return
}
val now = System.currentTimeMillis()
if (danaRPump.lastSettingsRead + 60 * 60 * 1000L < now || !pump.isInitialized) {
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingpumpsettings)))
sendMessage(DanaRS_Packet_General_Get_Shipping_Information(aapsLogger, danaRPump)) // serial no
sendMessage(DanaRS_Packet_General_Get_Pump_Check(aapsLogger, danaRPump, rxBus, resourceHelper)) // firmware
sendMessage(DanaRS_Packet_Basal_Get_Profile_Number(aapsLogger, danaRPump))
sendMessage(DanaRS_Packet_Bolus_Get_Bolus_Option(aapsLogger, rxBus, resourceHelper, danaRPump)) // isExtendedEnabled
sendMessage(DanaRS_Packet_Basal_Get_Basal_Rate(aapsLogger, rxBus, resourceHelper, danaRPump)) // basal profile, basalStep, maxBasal
sendMessage(DanaRS_Packet_Bolus_Get_Calculation_Information(aapsLogger, danaRPump)) // target
sendMessage(DanaRS_Packet_Bolus_Get_CIR_CF_Array(aapsLogger, danaRPump))
sendMessage(DanaRS_Packet_Option_Get_User_Option(aapsLogger, danaRPump)) // Getting user options
danaRPump.lastSettingsRead = now
}
aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: $timeDiff seconds")
if (abs(timeDiff) > 3) {
if (abs(timeDiff) > 60 * 60 * 1.5) {
aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: $timeDiff seconds - large difference")
//If time-diff is very large, warn user until we can synchronize history readings properly
val i = Intent(context, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.error)
i.putExtra("status", resourceHelper.gs(R.string.largetimediff))
i.putExtra("title", resourceHelper.gs(R.string.largetimedifftitle))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(i)
//de-initialize pump
danaRPump.reset()
rxBus.send(EventDanaRNewStatus())
rxBus.send(EventInitializationChanged())
return
} else {
if (danaRPump.protocol >= 6) {
sendMessage(DanaRS_Packet_Option_Set_Pump_Time(aapsLogger, DateUtil.now()))
} else {
waitForWholeMinute() // Dana can set only whole minute
// add 10sec to be sure we are over minute (will be cut off anyway)
sendMessage(DanaRS_Packet_Option_Set_Pump_Time(aapsLogger, DateUtil.now() + T.secs(10).msecs()))
}
sendMessage(DanaRS_Packet_Option_Get_Pump_Time(aapsLogger, danaRPump))
timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L
aapsLogger.debug(LTag.PUMPCOMM, "Pump time difference: $timeDiff seconds")
}
}
loadEvents()
rxBus.send(EventDanaRNewStatus())
rxBus.send(EventInitializationChanged())
//NSUpload.uploadDeviceStatus();
if (danaRPump.dailyTotalUnits > danaRPump.maxDailyTotalUnits * Constants.dailyLimitWarning) {
aapsLogger.debug(LTag.PUMPCOMM, "Approaching daily limit: " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits)
if (System.currentTimeMillis() > lastApproachingDailyLimit + 30 * 60 * 1000) {
val reportFail = Notification(Notification.APPROACHING_DAILY_LIMIT, resourceHelper.gs(R.string.approachingdailylimit), Notification.URGENT)
rxBus.send(EventNewNotification(reportFail))
NSUpload.uploadError(resourceHelper.gs(R.string.approachingdailylimit) + ": " + danaRPump.dailyTotalUnits + "/" + danaRPump.maxDailyTotalUnits + "U")
lastApproachingDailyLimit = System.currentTimeMillis()
}
}
} catch (e: Exception) {
aapsLogger.error(LTag.PUMPCOMM, "Unhandled exception", e)
}
aapsLogger.debug(LTag.PUMPCOMM, "Pump status loaded")
}
fun loadEvents(): PumpEnactResult {
if (!danaRSPlugin.isInitialized) {
val result = PumpEnactResult(injector).success(false)
result.comment = "pump not initialized"
return result
}
SystemClock.sleep(1000)
val msg: DanaRS_Packet_APS_History_Events
if (lastHistoryFetched == 0L) {
msg = DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRPump, detailedBolusInfoStorage, 0)
aapsLogger.debug(LTag.PUMPCOMM, "Loading complete event history")
} else {
msg = DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRPump, detailedBolusInfoStorage, lastHistoryFetched)
aapsLogger.debug(LTag.PUMPCOMM, "Loading event history from: " + DateUtil.dateAndTimeString(lastHistoryFetched))
}
sendMessage(msg)
while (!danaRPump.historyDoneReceived && bleComm.isConnected) {
SystemClock.sleep(100)
}
lastHistoryFetched = if (danaRPump.lastEventTimeLoaded != 0L) danaRPump.lastEventTimeLoaded - T.mins(1).msecs() else 0
aapsLogger.debug(LTag.PUMPCOMM, "Events loaded")
danaRPump.lastConnection = System.currentTimeMillis()
return PumpEnactResult(injector).success(true)
}
fun setUserSettings(): PumpEnactResult {
sendMessage(DanaRS_Packet_Option_Get_User_Option(aapsLogger, danaRPump))
return PumpEnactResult(injector).success(true)
}
fun bolus(insulin: Double, carbs: Int, carbTime: Long, t: Treatment): Boolean {
if (!isConnected) return false
if (BolusProgressDialog.stopPressed) return false
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.startingbolus)))
bolusingTreatment = t
val preferencesSpeed = sp.getInt(R.string.key_danars_bolusspeed, 0)
danaRPump.bolusingTreatment = t
danaRPump.bolusAmountToBeDelivered = insulin
danaRPump.bolusStopped = false
danaRPump.bolusStopForced = false
danaRPump.bolusProgressLastTimeStamp = DateUtil.now()
val start = DanaRS_Packet_Bolus_Set_Step_Bolus_Start(aapsLogger, danaRPump, constraintChecker, insulin, preferencesSpeed)
if (carbs > 0) {
// MsgSetCarbsEntry msg = new MsgSetCarbsEntry(carbTime, carbs); ####
// sendMessage(msg);
val msgSetHistoryEntryV2 = DanaRS_Packet_APS_Set_Event_History(aapsLogger, DanaRPump.CARBS, carbTime, carbs, 0)
sendMessage(msgSetHistoryEntryV2)
lastHistoryFetched = min(lastHistoryFetched, carbTime - T.mins(1).msecs())
}
val bolusStart = System.currentTimeMillis()
if (insulin > 0) {
if (!danaRPump.bolusStopped) {
sendMessage(start)
} else {
t.insulin = 0.0
return false
}
while (!danaRPump.bolusStopped && !start.failed && !danaRPump.bolusDone) {
SystemClock.sleep(100)
if (System.currentTimeMillis() - danaRPump.bolusProgressLastTimeStamp > 15 * 1000L) { // if i didn't receive status for more than 20 sec expecting broken comm
danaRPump.bolusStopped = true
danaRPump.bolusStopForced = true
aapsLogger.debug(LTag.PUMPCOMM, "Communication stopped")
}
}
}
val bolusingEvent = EventOverviewBolusProgress
bolusingEvent.t = t
bolusingEvent.percent = 99
bolusingTreatment = null
var speed = 12
when (preferencesSpeed) {
0 -> speed = 12
1 -> speed = 30
2 -> speed = 60
}
val bolusDurationInMSec = (insulin * speed * 1000).toLong()
val expectedEnd = bolusStart + bolusDurationInMSec + 2000
while (System.currentTimeMillis() < expectedEnd) {
val waitTime = expectedEnd - System.currentTimeMillis()
bolusingEvent.status = String.format(resourceHelper.gs(R.string.waitingforestimatedbolusend), waitTime / 1000)
rxBus.send(bolusingEvent)
SystemClock.sleep(1000)
}
// do not call loadEvents() directly, reconnection may be needed
commandQueue.loadEvents(object : Callback() {
override fun run() {
// reread bolus status
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.gettingbolusstatus)))
sendMessage(DanaRS_Packet_Bolus_Get_Step_Bolus_Information(aapsLogger, danaRPump)) // last bolus
bolusingEvent.percent = 100
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.disconnecting)))
}
})
return !start.failed
}
fun bolusStop() {
aapsLogger.debug(LTag.PUMPCOMM, "bolusStop >>>>> @ " + if (bolusingTreatment == null) "" else bolusingTreatment?.insulin)
val stop = DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(aapsLogger, rxBus, resourceHelper, danaRPump)
danaRPump.bolusStopForced = true
if (isConnected) {
sendMessage(stop)
while (!danaRPump.bolusStopped) {
sendMessage(stop)
SystemClock.sleep(200)
}
} else {
danaRPump.bolusStopped = true
}
}
fun tempBasal(percent: Int, durationInHours: Int): Boolean {
if (!isConnected) return false
if (danaRPump.isTempBasalInProgress) {
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)))
sendMessage(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger))
SystemClock.sleep(500)
}
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal)))
sendMessage(DanaRS_Packet_Basal_Set_Temporary_Basal(aapsLogger, percent, durationInHours))
SystemClock.sleep(200)
sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump))
loadEvents()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun highTempBasal(percent: Int): Boolean {
if (danaRPump.isTempBasalInProgress) {
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)))
sendMessage(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger))
SystemClock.sleep(500)
}
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal)))
sendMessage(DanaRS_Packet_APS_Basal_Set_Temporary_Basal(aapsLogger, percent))
sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump))
loadEvents()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun tempBasalShortDuration(percent: Int, durationInMinutes: Int): Boolean {
if (durationInMinutes != 15 && durationInMinutes != 30) {
aapsLogger.error(LTag.PUMPCOMM, "Wrong duration param")
return false
}
if (danaRPump.isTempBasalInProgress) {
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)))
sendMessage(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger))
SystemClock.sleep(500)
}
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingtempbasal)))
sendMessage(DanaRS_Packet_APS_Basal_Set_Temporary_Basal(aapsLogger, percent))
sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump))
loadEvents()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun tempBasalStop(): Boolean {
if (!isConnected) return false
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingtempbasal)))
sendMessage(DanaRS_Packet_Basal_Set_Cancel_Temporary_Basal(aapsLogger))
sendMessage(DanaRS_Packet_Basal_Get_Temporary_Basal_State(aapsLogger, danaRPump))
loadEvents()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun extendedBolus(insulin: Double, durationInHalfHours: Int): Boolean {
if (!isConnected) return false
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.settingextendedbolus)))
sendMessage(DanaRS_Packet_Bolus_Set_Extended_Bolus(aapsLogger, insulin, durationInHalfHours))
SystemClock.sleep(200)
sendMessage(DanaRS_Packet_Bolus_Get_Extended_Bolus_State(aapsLogger, danaRPump))
loadEvents()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun extendedBolusStop(): Boolean {
if (!isConnected) return false
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.stoppingextendedbolus)))
sendMessage(DanaRS_Packet_Bolus_Set_Extended_Bolus_Cancel(aapsLogger))
sendMessage(DanaRS_Packet_Bolus_Get_Extended_Bolus_State(aapsLogger, danaRPump))
loadEvents()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun updateBasalsInPump(profile: Profile): Boolean {
if (!isConnected) return false
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.updatingbasalrates)))
val basal = danaRPump.buildDanaRProfileRecord(profile)
val msgSet = DanaRS_Packet_Basal_Set_Profile_Basal_Rate(aapsLogger, 0, basal)
sendMessage(msgSet)
val msgActivate = DanaRS_Packet_Basal_Set_Profile_Number(aapsLogger, 0)
sendMessage(msgActivate)
danaRPump.lastSettingsRead = 0 // force read full settings
readPumpStatus()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
return true
}
fun loadHistory(type: Byte): PumpEnactResult {
val result = PumpEnactResult(injector)
if (!isConnected) return result
var msg: DanaRS_Packet_History_? = null
when (type) {
RecordTypes.RECORD_TYPE_ALARM -> msg = DanaRS_Packet_History_Alarm(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_PRIME -> msg = DanaRS_Packet_History_Prime(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_BASALHOUR -> msg = DanaRS_Packet_History_Basal(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_BOLUS -> msg = DanaRS_Packet_History_Bolus(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_CARBO -> msg = DanaRS_Packet_History_Carbohydrate(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_DAILY -> msg = DanaRS_Packet_History_Daily(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_GLUCOSE -> msg = DanaRS_Packet_History_Blood_Glucose(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_REFILL -> msg = DanaRS_Packet_History_Refill(aapsLogger, rxBus)
RecordTypes.RECORD_TYPE_SUSPEND -> msg = DanaRS_Packet_History_Suspend(aapsLogger, rxBus)
}
if (msg != null) {
sendMessage(DanaRS_Packet_General_Set_History_Upload_Mode(aapsLogger, 1))
SystemClock.sleep(200)
sendMessage(msg)
while (!msg.done && isConnected) {
SystemClock.sleep(100)
}
SystemClock.sleep(200)
sendMessage(DanaRS_Packet_General_Set_History_Upload_Mode(aapsLogger, 0))
}
result.success = true
result.comment = "OK"
return result
}
inner class LocalBinder : Binder() {
val serviceInstance: DanaRSService
get() = this@DanaRSService
}
override fun onBind(intent: Intent): IBinder {
return mBinder
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return Service.START_STICKY
}
private fun waitForWholeMinute() {
while (true) {
val time = DateUtil.now()
val timeToWholeMinute = 60000 - time % 60000
if (timeToWholeMinute > 59800 || timeToWholeMinute < 300) break
rxBus.send(EventPumpStatusChanged(resourceHelper.gs(R.string.waitingfortimesynchronization, (timeToWholeMinute / 1000).toInt())))
SystemClock.sleep(min(timeToWholeMinute, 100))
}
}
}

View file

@ -188,7 +188,7 @@ public class DanaRv2Plugin extends AbstractDanaRPlugin {
result.bolusDelivered = t.insulin;
result.carbsDelivered = detailedBolusInfo.carbs;
if (!result.success)
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, danaRPump.getMessageStartErrorCode());
result.comment = String.format(resourceHelper.gs(R.string.boluserrorcode), detailedBolusInfo.insulin, t.insulin, danaRPump.getBolusStartErrorCode());
else
result.comment = resourceHelper.gs(R.string.virtualpump_resultok);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: OK. Asked: " + detailedBolusInfo.insulin + " Delivered: " + result.bolusDelivered);

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@ -16,10 +16,9 @@ import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest(ConstraintChecker::class, DetailedBolusInfoStorage::class)
@PrepareForTest(ConstraintChecker::class, DetailedBolusInfoStorage::class, DanaRSPlugin::class)
class DanaRSMessageHashTableTest : DanaRSTestBase() {
@Mock lateinit var danaRSPlugin: DanaRSPlugin
@Mock lateinit var activePlugin: ActivePluginProvider
@Mock lateinit var constraintChecker: ConstraintChecker
@Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage
@ -28,7 +27,7 @@ class DanaRSMessageHashTableTest : DanaRSTestBase() {
fun runTest() {
`when`(constraintChecker.applyBolusConstraints(anyObject())).thenReturn(Constraint(0.0))
val danaRSMessageHashTable = DanaRSMessageHashTable(aapsLogger, rxBus, resourceHelper, danaRPump, danaRSPlugin, activePlugin, constraintChecker, detailedBolusInfoStorage)
val danaRSMessageHashTable = DanaRSMessageHashTable(aapsLogger, rxBus, resourceHelper, danaRPump, activePlugin, constraintChecker, detailedBolusInfoStorage)
val forTesting: DanaRS_Packet = DanaRS_Packet_APS_Set_Event_History(aapsLogger, DanaRPump.CARBS, 0, 0, 0)
val testPacket: DanaRS_Packet = danaRSMessageHashTable.findMessage(forTesting.command)
Assert.assertEquals(BleEncryption.DANAR_PACKET__OPCODE__APS_SET_EVENT_HISTORY.toLong(), testPacket.getOpCode().toLong())

View file

@ -14,17 +14,16 @@ import org.powermock.modules.junit4.PowerMockRunner
import java.util.*
@RunWith(PowerMockRunner::class)
@PrepareForTest(RxBusWrapper::class, DetailedBolusInfoStorage::class)
@PrepareForTest(RxBusWrapper::class, DetailedBolusInfoStorage::class, DanaRSPlugin::class)
class DanaRS_Packet_APS_History_EventsTest : DanaRSTestBase() {
@Mock lateinit var activePlugin: ActivePluginProvider
@Mock lateinit var danaRSPlugin: DanaRSPlugin
@Mock lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage
@Test fun runTest() {
val now = DateUtil.now()
val testPacket = DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRSPlugin, detailedBolusInfoStorage, now)
val testPacket = DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRPump, detailedBolusInfoStorage, now)
// test getRequestedParams
val returnedValues = testPacket.requestParams
val expectedValues = getCalender(now)

View file

@ -31,7 +31,7 @@ class DanaRS_Packet_Bolus_Set_Step_Bolus_StartTest : DanaRSTestBase() {
private lateinit var danaRSPlugin: DanaRSPlugin
@Test fun runTest() {
val packet = DanaRS_Packet_Bolus_Set_Step_Bolus_Start(aapsLogger, danaRSPlugin, constraintChecker)
val packet = DanaRS_Packet_Bolus_Set_Step_Bolus_Start(aapsLogger, danaRPump, constraintChecker)
// test params
val testparams = packet.requestParams
Assert.assertEquals(0.toByte(), testparams[0])

View file

@ -18,13 +18,12 @@ import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest(RxBusWrapper::class)
@PrepareForTest(RxBusWrapper::class, DanaRSPlugin::class)
class DanaRS_Packet_Bolus_Set_Step_Bolus_StopTest : DanaRSTestBase() {
@Mock lateinit var defaultValueHelper: DefaultValueHelper
@Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var activePlugin: ActivePluginProvider
@Mock lateinit var danaRSPlugin: DanaRSPlugin
private var treatmentInjector: HasAndroidInjector = HasAndroidInjector {
AndroidInjector {
@ -40,8 +39,8 @@ class DanaRS_Packet_Bolus_Set_Step_Bolus_StopTest : DanaRSTestBase() {
@Test fun runTest() {
`when`(resourceHelper.gs(Mockito.anyInt())).thenReturn("SomeString")
danaRSPlugin.bolusingTreatment = Treatment(treatmentInjector)
val testPacket = DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(aapsLogger, rxBus, resourceHelper, danaRSPlugin)
danaRPump.bolusingTreatment = Treatment(treatmentInjector)
val testPacket = DanaRS_Packet_Bolus_Set_Step_Bolus_Stop(aapsLogger, rxBus, resourceHelper, danaRPump)
// test message decoding
testPacket.handleMessage(byteArrayOf(0.toByte(), 0.toByte(), 0.toByte()))
Assert.assertEquals(false, testPacket.failed)

View file

@ -19,11 +19,10 @@ import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest(RxBusWrapper::class)
@PrepareForTest(RxBusWrapper::class, DanaRSPlugin::class)
class DanaRS_Packet_Notify_Delivery_CompleteTest : DanaRSTestBase() {
@Mock lateinit var defaultValueHelper: DefaultValueHelper
@Mock lateinit var danaRSPlugin: DanaRSPlugin
@Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var activePlugin: ActivePluginProvider
@ -41,13 +40,13 @@ class DanaRS_Packet_Notify_Delivery_CompleteTest : DanaRSTestBase() {
@Test fun runTest() {
`when`(resourceHelper.gs(anyInt(), anyDouble())).thenReturn("SomeString")
danaRSPlugin.bolusingTreatment = Treatment(treatmentInjector)
val packet = DanaRS_Packet_Notify_Delivery_Complete(aapsLogger, rxBus, resourceHelper, danaRSPlugin)
danaRPump.bolusingTreatment = Treatment(treatmentInjector)
val packet = DanaRS_Packet_Notify_Delivery_Complete(aapsLogger, rxBus, resourceHelper, danaRPump)
// test params
Assert.assertEquals(null, packet.requestParams)
// test message decoding
packet.handleMessage(createArray(17, 0.toByte()))
Assert.assertEquals(true, danaRSPlugin.bolusDone)
Assert.assertEquals(true, danaRPump.bolusDone)
Assert.assertEquals("NOTIFY__DELIVERY_COMPLETE", packet.friendlyName)
}
}

View file

@ -50,7 +50,7 @@ class DanaRS_Packet_Notify_Delivery_Rate_DisplayTest : DanaRSTestBase() {
@Test fun runTest() {
`when`(resourceHelper.gs(ArgumentMatchers.anyInt(), anyObject())).thenReturn("SomeString")
// val packet = DanaRS_Packet_Notify_Delivery_Rate_Display(1.0, Treatment(treatmentInjector))
val packet = DanaRS_Packet_Notify_Delivery_Rate_Display(aapsLogger, rxBus, resourceHelper, danaRSPlugin)
val packet = DanaRS_Packet_Notify_Delivery_Rate_Display(aapsLogger, rxBus, resourceHelper, danaRPump)
// test params
Assert.assertEquals(null, packet.requestParams)
// test message decoding
@ -66,6 +66,6 @@ class DanaRS_Packet_Notify_Delivery_Rate_DisplayTest : DanaRSTestBase() {
@Before
fun mock() {
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage, fabricPrivacy)
danaRSPlugin.bolusingTreatment = Treatment(treatmentInjector)
danaRPump.bolusingTreatment = Treatment(treatmentInjector)
}
}