- kotlin changes to most of the classes, most of it is tested

This commit is contained in:
Andy Rozman 2021-04-18 15:30:05 +01:00
parent bb657a2498
commit a202178426
76 changed files with 2581 additions and 4173 deletions

View file

@ -1,5 +1,5 @@
package info.nightscout.androidaps.plugins.general.actions.defs package info.nightscout.androidaps.plugins.general.actions.defs
interface CustomActionType { interface CustomActionType {
val key: String? fun getKey(): String
} }

View file

@ -244,7 +244,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
public long lastDataTime() { public long lastDataTime() {
aapsLogger.debug(LTag.PUMP, "lastDataTime [PumpPluginAbstract]."); aapsLogger.debug(LTag.PUMP, "lastDataTime [PumpPluginAbstract].");
return getPumpStatusData().lastConnection; return getPumpStatusData().getLastConnection();
} }
@ -308,7 +308,8 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
// Pump capabilities // Pump capabilities
@NonNull public PumpDescription getPumpDescription() {
public PumpDescription getPumpDescription() {
return pumpDescription; return pumpDescription;
} }
@ -331,7 +332,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
@NonNull @Override @NonNull @Override
public JSONObject getJSONStatus(@NonNull Profile profile, @NonNull String profileName, @NonNull String version) { public JSONObject getJSONStatus(@NonNull Profile profile, @NonNull String profileName, @NonNull String version) {
if ((getPumpStatusData().lastConnection + 60 * 60 * 1000L) < System.currentTimeMillis()) { if ((getPumpStatusData().getLastConnection() + 60 * 60 * 1000L) < System.currentTimeMillis()) {
return new JSONObject(); return new JSONObject();
} }
@ -341,8 +342,8 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
JSONObject status = new JSONObject(); JSONObject status = new JSONObject();
JSONObject extended = new JSONObject(); JSONObject extended = new JSONObject();
try { try {
battery.put("percent", getPumpStatusData().batteryRemaining); battery.put("percent", getPumpStatusData().getBatteryRemaining());
status.put("status", getPumpStatusData().pumpStatusType != null ? getPumpStatusData().pumpStatusType.getStatus() : "normal"); status.put("status", getPumpStatusData().getPumpStatusType() != null ? getPumpStatusData().getPumpStatusType().getStatus() : "normal");
extended.put("Version", version); extended.put("Version", version);
try { try {
extended.put("ActiveProfile", profileName); extended.put("ActiveProfile", profileName);
@ -368,7 +369,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
pump.put("battery", battery); pump.put("battery", battery);
pump.put("status", status); pump.put("status", status);
pump.put("extended", extended); pump.put("extended", extended);
pump.put("reservoir", getPumpStatusData().reservoirRemainingUnits); pump.put("reservoir", getPumpStatusData().getReservoirRemainingUnits());
pump.put("clock", dateUtil.toISOString(dateUtil.now())); pump.put("clock", dateUtil.toISOString(dateUtil.now()));
} catch (JSONException e) { } catch (JSONException e) {
aapsLogger.error("Unhandled exception", e); aapsLogger.error("Unhandled exception", e);
@ -381,14 +382,14 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
@NonNull @Override @NonNull @Override
public String shortStatus(boolean veryShort) { public String shortStatus(boolean veryShort) {
String ret = ""; String ret = "";
if (getPumpStatusData().lastConnection != 0) { if (getPumpStatusData().getLastConnection() != 0) {
long agoMsec = System.currentTimeMillis() - getPumpStatusData().lastConnection; long agoMsec = System.currentTimeMillis() - getPumpStatusData().getLastConnection();
int agoMin = (int) (agoMsec / 60d / 1000d); int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " min ago\n"; ret += "LastConn: " + agoMin + " min ago\n";
} }
if (getPumpStatusData().lastBolusTime != null && getPumpStatusData().lastBolusTime.getTime() != 0) { if (getPumpStatusData().getLastBolusTime() != null && getPumpStatusData().getLastBolusTime().getTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().lastBolusAmount) + "U @" + // ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().getLastBolusAmount()) + "U @" + //
android.text.format.DateFormat.format("HH:mm", getPumpStatusData().lastBolusTime) + "\n"; android.text.format.DateFormat.format("HH:mm", getPumpStatusData().getLastBolusTime()) + "\n";
} }
PumpSync.PumpState.TemporaryBasal activeTemp = pumpSync.expectedPumpState().getTemporaryBasal(); PumpSync.PumpState.TemporaryBasal activeTemp = pumpSync.expectedPumpState().getTemporaryBasal();
if (activeTemp != null) { if (activeTemp != null) {
@ -402,9 +403,9 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump,
// ret += "TDD: " + DecimalFormatter.to0Decimal(pumpStatus.dailyTotalUnits) + " / " // ret += "TDD: " + DecimalFormatter.to0Decimal(pumpStatus.dailyTotalUnits) + " / "
// + pumpStatus.maxDailyTotalUnits + " U\n"; // + pumpStatus.maxDailyTotalUnits + " U\n";
// } // }
ret += "IOB: " + getPumpStatusData().iob + "U\n"; ret += "IOB: " + getPumpStatusData().getIob() + "U\n";
ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(getPumpStatusData().reservoirRemainingUnits) + "U\n"; ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(getPumpStatusData().getReservoirRemainingUnits()) + "U\n";
ret += "Batt: " + getPumpStatusData().batteryRemaining + "\n"; ret += "Batt: " + getPumpStatusData().getBatteryRemaining() + "\n";
return ret; return ret;
} }

View file

@ -1,535 +0,0 @@
package info.nightscout.androidaps.plugins.pump.common;
import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute;
import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import androidx.annotation.NonNull;
import org.json.JSONException;
import org.json.JSONObject;
<<<<<<< HEAD
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
=======
>>>>>>> meallink
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.core.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.EventCustomActionsChanged;
import info.nightscout.androidaps.extensions.PumpStateExtensionKt;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.pump.common.data.PumpDbEntry;
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.rx.AapsSchedulers;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.disposables.CompositeDisposable;
/**
* Created by andy on 23.04.18.
*/
// When using this class, make sure that your first step is to create mConnection (see MedtronicPumpPlugin)
public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpInterface, ConstraintsInterface {
private final CompositeDisposable disposable = new CompositeDisposable();
protected HasAndroidInjector injector;
protected AAPSLogger aapsLogger;
protected RxBusWrapper rxBus;
protected ActivePluginProvider activePlugin;
protected Context context;
protected FabricPrivacy fabricPrivacy;
protected ResourceHelper resourceHelper;
protected CommandQueueProvider commandQueue;
protected SP sp;
protected DateUtil dateUtil;
protected PumpDescription pumpDescription = new PumpDescription();
protected ServiceConnection serviceConnection;
protected boolean serviceRunning = false;
protected PumpDriverState pumpState = PumpDriverState.NotInitialized;
protected boolean displayConnectionMessages = false;
protected PumpType pumpType;
protected AapsSchedulers aapsSchedulers;
protected PumpSync pumpSync;
<<<<<<< HEAD
=======
>>>>>>> meallink
protected PumpPluginAbstract(
PluginDescription pluginDescription,
PumpType pumpType,
HasAndroidInjector injector,
ResourceHelper resourceHelper,
AAPSLogger aapsLogger,
CommandQueueProvider commandQueue,
RxBusWrapper rxBus,
ActivePluginProvider activePlugin,
SP sp,
Context context,
FabricPrivacy fabricPrivacy,
DateUtil dateUtil,
AapsSchedulers aapsSchedulers,
PumpSync pumpSync
) {
super(pluginDescription, injector, aapsLogger, resourceHelper, commandQueue);
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
this.activePlugin = activePlugin;
this.context = context;
this.fabricPrivacy = fabricPrivacy;
this.resourceHelper = resourceHelper;
this.sp = sp;
this.commandQueue = commandQueue;
pumpDescription.setPumpDescription(pumpType);
this.pumpType = pumpType;
this.dateUtil = dateUtil;
this.aapsSchedulers = aapsSchedulers;
this.pumpSync = pumpSync;
}
public abstract void initPumpStatusData();
@Override
protected void onStart() {
super.onStart();
initPumpStatusData();
Intent intent = new Intent(context, getServiceClass());
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
serviceRunning = true;
disposable.add(rxBus
.toObservable(EventAppExit.class)
.observeOn(aapsSchedulers.getIo())
.subscribe(event -> context.unbindService(serviceConnection), fabricPrivacy::logException)
);
onStartCustomActions();
}
@Override
protected void onStop() {
aapsLogger.debug(LTag.PUMP, this.deviceID() + " onStop()");
context.unbindService(serviceConnection);
serviceRunning = false;
disposable.clear();
super.onStop();
}
/**
* If we need to run any custom actions in onStart (triggering events, etc)
*/
public abstract void onStartCustomActions();
/**
* Service class (same one you did serviceConnection for)
*
* @return Class
*/
public abstract Class getServiceClass();
public abstract PumpStatus getPumpStatusData();
public boolean isInitialized() {
return pumpState.isInitialized();
}
public boolean isSuspended() {
return pumpState == PumpDriverState.Suspended;
}
public boolean isBusy() {
return pumpState == PumpDriverState.Busy;
}
public boolean isConnected() {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "isConnected [PumpPluginAbstract].");
return pumpState.isConnected();
}
public boolean isConnecting() {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "isConnecting [PumpPluginAbstract].");
return pumpState == PumpDriverState.Connecting;
}
public void connect(@NonNull String reason) {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "connect (reason={}) [PumpPluginAbstract] - default (empty) implementation." + reason);
}
public void disconnect(@NonNull String reason) {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "disconnect (reason={}) [PumpPluginAbstract] - default (empty) implementation." + reason);
}
public void stopConnecting() {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "stopConnecting [PumpPluginAbstract] - default (empty) implementation.");
}
@Override
public boolean isHandshakeInProgress() {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "isHandshakeInProgress [PumpPluginAbstract] - default (empty) implementation.");
return false;
}
@Override
public void finishHandshaking() {
if (displayConnectionMessages)
aapsLogger.debug(LTag.PUMP, "finishHandshaking [PumpPluginAbstract] - default (empty) implementation.");
}
// Upload to pump new basal profile
@NonNull public PumpEnactResult setNewBasalProfile(@NonNull Profile profile) {
aapsLogger.debug(LTag.PUMP, "setNewBasalProfile [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public boolean isThisProfileSet(@NonNull Profile profile) {
aapsLogger.debug(LTag.PUMP, "isThisProfileSet [PumpPluginAbstract] - Not implemented.");
return true;
}
public long lastDataTime() {
aapsLogger.debug(LTag.PUMP, "lastDataTime [PumpPluginAbstract].");
return getPumpStatusData().lastConnection;
}
public double getBaseBasalRate() {
aapsLogger.debug(LTag.PUMP, "getBaseBasalRate [PumpPluginAbstract] - Not implemented.");
return 0.0d;
} // base basal rate, not temp basal
public void stopBolusDelivering() {
aapsLogger.debug(LTag.PUMP, "stopBolusDelivering [PumpPluginAbstract] - Not implemented.");
}
@NonNull @Override
public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@NonNull @Override
public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) {
aapsLogger.debug(LTag.PUMP, "setTempBasalPercent [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@NonNull public PumpEnactResult setExtendedBolus(double insulin, int durationInMinutes) {
aapsLogger.debug(LTag.PUMP, "setExtendedBolus [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
// some pumps might set a very short temp close to 100% as cancelling a temp can be noisy
// when the cancel request is requested by the user (forced), the pump should always do a real cancel
@NonNull public PumpEnactResult cancelTempBasal(boolean enforceNew) {
aapsLogger.debug(LTag.PUMP, "cancelTempBasal [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@NonNull public PumpEnactResult cancelExtendedBolus() {
aapsLogger.debug(LTag.PUMP, "cancelExtendedBolus [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
// Status to be passed to NS
// public JSONObject getJSONStatus(Profile profile, String profileName) {
// return pumpDriver.getJSONStatus(profile, profileName);
// }
public String deviceID() {
aapsLogger.debug(LTag.PUMP, "deviceID [PumpPluginAbstract] - Not implemented.");
return "FakeDevice";
}
// Pump capabilities
@NonNull public PumpDescription getPumpDescription() {
return pumpDescription;
}
// Short info for SMS, Wear etc
public boolean isFakingTempsByExtendedBoluses() {
aapsLogger.debug(LTag.PUMP, "isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.");
return false;
}
@NonNull @Override
public PumpEnactResult loadTDDs() {
aapsLogger.debug(LTag.PUMP, "loadTDDs [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@NonNull @Override
public JSONObject getJSONStatus(@NonNull Profile profile, @NonNull String profileName, @NonNull String version) {
if ((getPumpStatusData().lastConnection + 60 * 60 * 1000L) < System.currentTimeMillis()) {
return new JSONObject();
}
long now = System.currentTimeMillis();
JSONObject pump = new JSONObject();
JSONObject battery = new JSONObject();
JSONObject status = new JSONObject();
JSONObject extended = new JSONObject();
try {
battery.put("percent", getPumpStatusData().batteryRemaining);
status.put("status", getPumpStatusData().pumpStatusType != null ? getPumpStatusData().pumpStatusType.getStatus() : "normal");
extended.put("Version", version);
try {
extended.put("ActiveProfile", profileName);
} catch (Exception ignored) {
}
<<<<<<< HEAD
// TODO fix
TemporaryBasal tb = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis());
=======
PumpSync.PumpState.TemporaryBasal tb = pumpSync.expectedPumpState().getTemporaryBasal();
>>>>>>> meallink
if (tb != null) {
extended.put("TempBasalAbsoluteRate", convertedToAbsolute(tb, now, profile));
extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.getTimestamp()));
extended.put("TempBasalRemaining", getPlannedRemainingMinutes(tb));
}
<<<<<<< HEAD
// TODO fix
ExtendedBolus eb = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis());
=======
PumpSync.PumpState.ExtendedBolus eb = pumpSync.expectedPumpState().getExtendedBolus();
>>>>>>> meallink
if (eb != null) {
extended.put("ExtendedBolusAbsoluteRate", eb.getRate());
extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.getTimestamp()));
extended.put("ExtendedBolusRemaining", getPlannedRemainingMinutes(eb));
}
status.put("timestamp", dateUtil.toISOString(dateUtil.now()));
pump.put("battery", battery);
pump.put("status", status);
pump.put("extended", extended);
pump.put("reservoir", getPumpStatusData().reservoirRemainingUnits);
pump.put("clock", dateUtil.toISOString(dateUtil.now()));
} catch (JSONException e) {
aapsLogger.error("Unhandled exception", e);
}
return pump;
}
// FIXME i18n, null checks: iob, TDD
@NonNull @Override
public String shortStatus(boolean veryShort) {
String ret = "";
if (getPumpStatusData().lastConnection != 0) {
long agoMsec = System.currentTimeMillis() - getPumpStatusData().lastConnection;
int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " min ago\n";
}
if (getPumpStatusData().lastBolusTime != null && getPumpStatusData().lastBolusTime.getTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().lastBolusAmount) + "U @" + //
android.text.format.DateFormat.format("HH:mm", getPumpStatusData().lastBolusTime) + "\n";
}
<<<<<<< HEAD
// TODO fix
TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(System.currentTimeMillis());
=======
PumpSync.PumpState.TemporaryBasal activeTemp = pumpSync.expectedPumpState().getTemporaryBasal();
>>>>>>> meallink
if (activeTemp != null) {
ret += "Temp: " + PumpStateExtensionKt.toStringFull(activeTemp, dateUtil) + "\n";
}
<<<<<<< HEAD
// TODO fix
ExtendedBolus activeExtendedBolus = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(
System.currentTimeMillis());
=======
PumpSync.PumpState.ExtendedBolus activeExtendedBolus = pumpSync.expectedPumpState().getExtendedBolus();
>>>>>>> meallink
if (activeExtendedBolus != null) {
ret += "Extended: " + PumpStateExtensionKt.toStringFull(activeExtendedBolus, dateUtil) + "\n";
}
// if (!veryShort) {
// ret += "TDD: " + DecimalFormatter.to0Decimal(pumpStatus.dailyTotalUnits) + " / "
// + pumpStatus.maxDailyTotalUnits + " U\n";
// }
ret += "IOB: " + getPumpStatusData().iob + "U\n";
ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(getPumpStatusData().reservoirRemainingUnits) + "U\n";
ret += "Batt: " + getPumpStatusData().batteryRemaining + "\n";
return ret;
}
@NonNull @Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
try {
if (detailedBolusInfo.insulin == 0 && detailedBolusInfo.carbs == 0) {
// neither carbs nor bolus requested
aapsLogger.error("deliverTreatment: Invalid input");
return new PumpEnactResult(getInjector()).success(false).enacted(false).bolusDelivered(0d).carbsDelivered(0d)
.comment(R.string.invalidinput);
} else if (detailedBolusInfo.insulin > 0) {
// bolus needed, ask pump to deliver it
return deliverBolus(detailedBolusInfo);
} else {
//if (MedtronicHistoryData.doubleBolusDebug)
// aapsLogger.debug("DoubleBolusDebug: deliverTreatment::(carb only entry)");
// TODO fix
// no bolus required, carb only treatment
activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.INSTANCE;
bolusingEvent.setT(new EventOverviewBolusProgress.Treatment(0, 0, detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB));
bolusingEvent.setPercent(100);
rxBus.send(bolusingEvent);
aapsLogger.debug(LTag.PUMP, "deliverTreatment: Carb only treatment.");
return new PumpEnactResult(getInjector()).success(true).enacted(true).bolusDelivered(0d)
.carbsDelivered(detailedBolusInfo.carbs).comment(R.string.common_resultok);
}
} finally {
triggerUIChange();
}
}
protected void refreshCustomActionsList() {
rxBus.send(new EventCustomActionsChanged());
}
@NonNull public ManufacturerType manufacturer() {
return pumpType.getManufacturer();
}
@NonNull
public PumpType model() {
return pumpType;
}
public PumpType getPumpType() {
return pumpType;
}
public void setPumpType(PumpType pumpType) {
this.pumpType = pumpType;
this.pumpDescription.setPumpDescription(pumpType);
}
public boolean canHandleDST() {
return false;
}
protected abstract PumpEnactResult deliverBolus(DetailedBolusInfo detailedBolusInfo);
protected abstract void triggerUIChange();
private PumpEnactResult getOperationNotSupportedWithCustomText(int resourceId) {
return new PumpEnactResult(getInjector()).success(false).enacted(false).comment(resourceId);
}
// PumpSync
Map<Long, PumpDbEntry> driverHistory = new HashMap<>();
public abstract long generateTempId(long timeMillis);
public boolean addBolusWithTempId(DetailedBolusInfo detailedBolusInfo, boolean writeToInternalHistory) {
long temporaryId = generateTempId(detailedBolusInfo.timestamp);
boolean response = pumpSync.addBolusWithTempId(detailedBolusInfo.timestamp, detailedBolusInfo.insulin,
generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(),
getPumpType(), serialNumber());
if (response && writeToInternalHistory) {
driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo));
}
return response;
}
public void removeTemporaryId(long temporaryId) {
driverHistory.remove(temporaryId);
}
}

View file

@ -1,71 +0,0 @@
package info.nightscout.androidaps.plugins.pump.common.data;
import java.util.Date;
import info.nightscout.androidaps.interfaces.ProfileStore;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.utils.DateUtil;
/**
* Created by andy on 4/28/18.
*/
public abstract class PumpStatus {
// connection
public long lastDataTime;
public long lastConnection = 0L;
public long previousConnection = 0L; // here should be stored last connection of previous session (so needs to be
// read before lastConnection is modified for first time).
// last bolus
public Date lastBolusTime;
public Double lastBolusAmount;
// other pump settings
public String activeProfileName = "0";
public double reservoirRemainingUnits = 0.0d;
public int reservoirFullUnits = 0;
public int batteryRemaining = 0; // percent, so 0-100
public Double batteryVoltage = null;
// iob
public String iob = null;
// TDD
public Double dailyTotalUnits;
public String maxDailyTotalUnits;
public boolean validBasalRateProfileSelectedOnPump = true;
public ProfileStore profileStore;
public String units; // Constants.MGDL or Constants.MMOL
public PumpStatusType pumpStatusType = PumpStatusType.Running;
public Double[] basalsByHour;
public double currentBasal = 0;
public int tempBasalInProgress = 0;
public int tempBasalRatio = 0;
public int tempBasalRemainMin = 0;
public Date tempBasalStart;
public PumpType pumpType;
//protected PumpDescription pumpDescription;
public PumpStatus(PumpType pumpType) {
// public PumpStatus(PumpDescription pumpDescription) {
// this.pumpDescription = pumpDescription;
// this.initSettings();
this.pumpType = pumpType;
}
public abstract void initSettings();
public void setLastCommunicationToNow() {
this.lastDataTime = System.currentTimeMillis();
this.lastConnection = System.currentTimeMillis();
}
public abstract String getErrorInfo();
}

View file

@ -0,0 +1,52 @@
package info.nightscout.androidaps.plugins.pump.common.data
import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import java.util.*
/**
* Created by andy on 4/28/18.
*/
abstract class PumpStatus(var pumpType: PumpType) {
// connection
var lastDataTime: Long = 0
var lastConnection = 0L
var previousConnection = 0L // here should be stored last connection of previous session (so needs to be
// read before lastConnection is modified for first time).
// last bolus
var lastBolusTime: Date? = null
var lastBolusAmount: Double? = null
// other pump settings
var activeProfileName = "0"
var reservoirRemainingUnits = 0.0
var reservoirFullUnits = 0
var batteryRemaining = 0 // percent, so 0-100
var batteryVoltage: Double? = null
// iob
var iob: String? = null
// TDD
var dailyTotalUnits: Double? = null
var maxDailyTotalUnits: String? = null
var units : String? = null // Constants.MGDL or Constants.MMOL
var pumpStatusType = PumpStatusType.Running
var basalsByHour: Array<Double>? = null
var tempBasalStart: Date? = null
var tempBasalAmount: Double? = 0.0
var tempBasalLength: Int? = 0
var tempBasalEnd: Long? = null
abstract fun initSettings()
fun setLastCommunicationToNow() {
lastDataTime = System.currentTimeMillis()
lastConnection = System.currentTimeMillis()
}
abstract val errorInfo: String?
}

View file

@ -220,12 +220,12 @@ class MedtronicFragment : DaggerFragment() {
PumpDeviceState.InvalidConfiguration -> binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) PumpDeviceState.InvalidConfiguration -> binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId)
PumpDeviceState.Active -> { PumpDeviceState.Active -> {
val cmd = medtronicUtil.currentCommand val cmd = medtronicUtil.getCurrentCommand()
if (cmd == null) if (cmd == null)
binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId)
else { else {
aapsLogger.debug(LTag.PUMP, "Command: $cmd") aapsLogger.debug(LTag.PUMP, "Command: $cmd")
val cmdResourceId = cmd.resourceId val cmdResourceId = cmd.resourceId!!
if (cmd == MedtronicCommandType.GetHistoryData) { if (cmd == MedtronicCommandType.GetHistoryData) {
binding.pumpStatusIcon.text = medtronicUtil.frameNumber?.let { binding.pumpStatusIcon.text = medtronicUtil.frameNumber?.let {
resourceHelper.gs(cmdResourceId, medtronicUtil.pageNumber, medtronicUtil.frameNumber) resourceHelper.gs(cmdResourceId, medtronicUtil.pageNumber, medtronicUtil.frameNumber)
@ -233,7 +233,7 @@ class MedtronicFragment : DaggerFragment() {
?: resourceHelper.gs(R.string.medtronic_cmd_desc_get_history_request, medtronicUtil.pageNumber) ?: resourceHelper.gs(R.string.medtronic_cmd_desc_get_history_request, medtronicUtil.pageNumber)
} else { } else {
binding.pumpStatusIcon.text = " " + (cmdResourceId?.let { resourceHelper.gs(it) } binding.pumpStatusIcon.text = " " + (cmdResourceId?.let { resourceHelper.gs(it) }
?: cmd.getCommandDescription()) ?: cmd.commandDescription)
} }
} }
} }
@ -298,34 +298,31 @@ class MedtronicFragment : DaggerFragment() {
val bolus = medtronicPumpStatus.lastBolusAmount val bolus = medtronicPumpStatus.lastBolusAmount
val bolusTime = medtronicPumpStatus.lastBolusTime val bolusTime = medtronicPumpStatus.lastBolusTime
if (bolus != null && bolusTime != null) { if (bolus != null && bolusTime != null) {
val agoMsc = System.currentTimeMillis() - medtronicPumpStatus.lastBolusTime.time val agoMsc = System.currentTimeMillis() - medtronicPumpStatus.lastBolusTime!!.time
val bolusMinAgo = agoMsc.toDouble() / 60.0 / 1000.0 val bolusMinAgo = agoMsc.toDouble() / 60.0 / 1000.0
val unit = resourceHelper.gs(R.string.insulin_unit_shortname) val unit = resourceHelper.gs(R.string.insulin_unit_shortname)
val ago = when { val ago = when {
agoMsc < 60 * 1000 -> resourceHelper.gs(R.string.medtronic_pump_connected_now) agoMsc < 60 * 1000 -> resourceHelper.gs(R.string.medtronic_pump_connected_now)
bolusMinAgo < 60 -> dateUtil.minAgo(resourceHelper, medtronicPumpStatus.lastBolusTime.time) bolusMinAgo < 60 -> dateUtil.minAgo(resourceHelper, medtronicPumpStatus.lastBolusTime!!.time)
else -> dateUtil.hourAgo(medtronicPumpStatus.lastBolusTime.time, resourceHelper) else -> dateUtil.hourAgo(medtronicPumpStatus.lastBolusTime!!.time, resourceHelper)
} }
binding.lastBolus.text = resourceHelper.gs(R.string.mdt_last_bolus, bolus, unit, ago) binding.lastBolus.text = resourceHelper.gs(R.string.mdt_last_bolus, bolus, unit, ago)
} else { } else {
binding.lastBolus.text = "" binding.lastBolus.text = ""
} }
if (true) { // base basal rate
// base basal rate binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") "
binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate))
+ resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate))
binding.tempBasal.text = "??" // TBR
} else { var tbrStr = ""
val pumpState = pumpSync.expectedPumpState() var tbrRemainingTime: Int? = medtronicPumpStatus.tbrRemainingTime
// base basal rate
binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") "
+ resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate))
binding.tempBasal.text = pumpState.temporaryBasal?.toStringFull(dateUtil) if (tbrRemainingTime!=null) {
?: "" tbrStr = resourceHelper.gs(R.string.mdt_tbr_remaining, medtronicPumpStatus.tempBasalAmount, tbrRemainingTime);
} }
binding.tempBasal.text = tbrStr
// battery // battery
if (medtronicPumpStatus.batteryType == BatteryType.None || medtronicPumpStatus.batteryVoltage == null) { if (medtronicPumpStatus.batteryType == BatteryType.None || medtronicPumpStatus.batteryVoltage == null) {

View file

@ -40,6 +40,7 @@ import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.Pump; import info.nightscout.androidaps.interfaces.Pump;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.logging.LTag;
@ -210,19 +211,24 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
return "MedtronicPumpPlugin::"; return "MedtronicPumpPlugin::";
} }
// public PumpDescription getPumpDescription() {
// return super.pumpDescription;
// }
@Override @Override
public void initPumpStatusData() { public void initPumpStatusData() {
medtronicPumpStatus.lastConnection = sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); medtronicPumpStatus.setLastConnection(sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L));
medtronicPumpStatus.lastDataTime = medtronicPumpStatus.lastConnection; medtronicPumpStatus.setLastDataTime(medtronicPumpStatus.getLastConnection());
medtronicPumpStatus.previousConnection = medtronicPumpStatus.lastConnection; medtronicPumpStatus.setPreviousConnection( medtronicPumpStatus.getLastConnection());
//if (rileyLinkMedtronicService != null) rileyLinkMedtronicService.verifyConfiguration(); //if (rileyLinkMedtronicService != null) rileyLinkMedtronicService.verifyConfiguration();
aapsLogger.debug(LTag.PUMP, "initPumpStatusData: " + this.medtronicPumpStatus); aapsLogger.debug(LTag.PUMP, "initPumpStatusData: " + this.medtronicPumpStatus);
// this is only thing that can change, by being configured // this is only thing that can change, by being configured
pumpDescription.setMaxTempAbsolute((medtronicPumpStatus.maxBasal != null) ? medtronicPumpStatus.maxBasal : 35.0d); pumpDescription.setMaxTempAbsolute((medtronicPumpStatus.getMaxBasal() != null) ? medtronicPumpStatus.getMaxBasal() : 35.0d);
// set first Medtronic Pump Start // set first Medtronic Pump Start
if (!sp.contains(MedtronicConst.Statistics.FirstPumpStart)) { if (!sp.contains(MedtronicConst.Statistics.FirstPumpStart)) {
@ -321,15 +327,16 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
return rileyLinkMedtronicService; return rileyLinkMedtronicService;
} }
@Override public RileyLinkPumpInfo getPumpInfo() { @Override
String frequency = resourceHelper.gs(medtronicPumpStatus.pumpFrequency.equals("medtronic_pump_frequency_us_ca") ? R.string.medtronic_pump_frequency_us_ca : R.string.medtronic_pump_frequency_worldwide); public RileyLinkPumpInfo getPumpInfo() {
String model = medtronicPumpStatus.medtronicDeviceType == null ? "???" : "Medtronic " + medtronicPumpStatus.medtronicDeviceType.getPumpModel(); String frequency = resourceHelper.gs(medtronicPumpStatus.getPumpFrequency().equals("medtronic_pump_frequency_us_ca") ? R.string.medtronic_pump_frequency_us_ca : R.string.medtronic_pump_frequency_worldwide);
String serialNumber = medtronicPumpStatus.serialNumber; String model = medtronicPumpStatus.getMedtronicDeviceType() == null ? "???" : "Medtronic " + medtronicPumpStatus.getMedtronicDeviceType().getPumpModel();
String serialNumber = medtronicPumpStatus.getSerialNumber();
return new RileyLinkPumpInfo(frequency, model, serialNumber); return new RileyLinkPumpInfo(frequency, model, serialNumber);
} }
@Override public long getLastConnectionTimeMillis() { @Override public long getLastConnectionTimeMillis() {
return medtronicPumpStatus.lastConnection; return medtronicPumpStatus.getLastConnection();
} }
@Override public void setLastCommunicationToNow() { @Override public void setLastCommunicationToNow() {
@ -580,7 +587,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
if (medtronicUtil.getMedtronicPumpModel() == null) { if (medtronicUtil.getMedtronicPumpModel() == null) {
rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.PumpModel); rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.PumpModel);
} else { } else {
if (medtronicPumpStatus.medtronicDeviceType != medtronicUtil.getMedtronicPumpModel()) { if (medtronicPumpStatus.getMedtronicDeviceType() != medtronicUtil.getMedtronicPumpModel()) {
aapsLogger.warn(LTag.PUMP, getLogPrefix() + "Configured pump is not the same as one detected."); aapsLogger.warn(LTag.PUMP, getLogPrefix() + "Configured pump is not the same as one detected.");
medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, getResourceHelper(), rxBus); medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, getResourceHelper(), rxBus);
} }
@ -643,27 +650,27 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
@Override @Override
public boolean isThisProfileSet(@NonNull Profile profile) { public boolean isThisProfileSet(@NonNull Profile profile) {
aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.basalProfileStatus); aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.getBasalProfileStatus());
if (!isInitialized) if (!isInitialized)
return true; return true;
if (medtronicPumpStatus.basalProfileStatus == BasalProfileStatus.NotInitialized) { if (medtronicPumpStatus.getBasalProfileStatus() == BasalProfileStatus.NotInitialized) {
// this shouldn't happen, but if there was problem we try again // this shouldn't happen, but if there was problem we try again
getBasalProfiles(); getBasalProfiles();
return isProfileSame(profile); return isProfileSame(profile);
} else if (medtronicPumpStatus.basalProfileStatus == BasalProfileStatus.ProfileChanged) { } else if (medtronicPumpStatus.getBasalProfileStatus() == BasalProfileStatus.ProfileChanged) {
return false; return false;
} }
return (medtronicPumpStatus.basalProfileStatus != BasalProfileStatus.ProfileOK) || isProfileSame(profile); return (medtronicPumpStatus.getBasalProfileStatus() != BasalProfileStatus.ProfileOK) || isProfileSame(profile);
} }
private boolean isProfileSame(Profile profile) { private boolean isProfileSame(Profile profile) {
boolean invalid = false; boolean invalid = false;
Double[] basalsByHour = medtronicPumpStatus.basalsByHour; Double[] basalsByHour = medtronicPumpStatus.getBasalsByHour();
aapsLogger.debug(LTag.PUMP, "Current Basals (h): " aapsLogger.debug(LTag.PUMP, "Current Basals (h): "
+ (basalsByHour == null ? "null" : BasalProfile.getProfilesByHourToString(basalsByHour))); + (basalsByHour == null ? "null" : BasalProfile.getProfilesByHourToString(basalsByHour)));
@ -704,8 +711,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
@Override @Override
public long lastDataTime() { public long lastDataTime() {
if (medtronicPumpStatus.lastConnection != 0) { if (medtronicPumpStatus.getLastConnection() != 0) {
return medtronicPumpStatus.lastConnection; return medtronicPumpStatus.getLastConnection();
} }
return System.currentTimeMillis(); return System.currentTimeMillis();
@ -720,13 +727,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
@Override @Override
public double getReservoirLevel() { public double getReservoirLevel() {
return medtronicPumpStatus.reservoirRemainingUnits; return medtronicPumpStatus.getReservoirRemainingUnits();
} }
@Override @Override
public int getBatteryLevel() { public int getBatteryLevel() {
return medtronicPumpStatus.batteryRemaining; return medtronicPumpStatus.getBatteryRemaining();
} }
protected void triggerUIChange() { protected void triggerUIChange() {
@ -778,22 +785,22 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
if (clock == null) if (clock == null)
return; return;
int timeDiff = Math.abs(clock.timeDifference); int timeDiff = Math.abs(clock.getTimeDifference());
if (timeDiff > 20) { if (timeDiff > 20) {
if ((clock.localDeviceTime.getYear() <= 2015) || (timeDiff <= 24 * 60 * 60)) { if ((clock.getLocalDeviceTime().getYear() <= 2015) || (timeDiff <= 24 * 60 * 60)) {
aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Set time on pump.", timeDiff)); aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Set time on pump.", timeDiff));
rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetRealTimeClock); rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetRealTimeClock);
if (clock.timeDifference == 0) { if (clock.getTimeDifference() == 0) {
Notification notification = new Notification(Notification.INSIGHT_DATE_TIME_UPDATED, getResourceHelper().gs(R.string.pump_time_updated), Notification.INFO, 60); Notification notification = new Notification(Notification.INSIGHT_DATE_TIME_UPDATED, getResourceHelper().gs(R.string.pump_time_updated), Notification.INFO, 60);
rxBus.send(new EventNewNotification(notification)); rxBus.send(new EventNewNotification(notification));
} }
} else { } else {
if ((clock.localDeviceTime.getYear() > 2015)) { if ((clock.getLocalDeviceTime().getYear() > 2015)) {
aapsLogger.error(String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference over 24h requested [diff=%d s]. Doing nothing.", timeDiff)); aapsLogger.error(String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference over 24h requested [diff=%d s]. Doing nothing.", timeDiff));
medtronicUtil.sendNotification(MedtronicNotificationType.TimeChangeOver24h, getResourceHelper(), rxBus); medtronicUtil.sendNotification(MedtronicNotificationType.TimeChangeOver24h, getResourceHelper(), rxBus);
} }
@ -814,12 +821,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
setRefreshButtonEnabled(false); setRefreshButtonEnabled(false);
if (detailedBolusInfo.insulin > medtronicPumpStatus.reservoirRemainingUnits) { if (detailedBolusInfo.insulin > medtronicPumpStatus.getReservoirRemainingUnits()) {
return new PumpEnactResult(getInjector()) // return new PumpEnactResult(getInjector()) //
.success(false) // .success(false) //
.enacted(false) // .enacted(false) //
.comment(getResourceHelper().gs(R.string.medtronic_cmd_bolus_could_not_be_delivered_no_insulin, .comment(getResourceHelper().gs(R.string.medtronic_cmd_bolus_could_not_be_delivered_no_insulin,
medtronicPumpStatus.reservoirRemainingUnits, medtronicPumpStatus.getReservoirRemainingUnits(),
detailedBolusInfo.insulin)); detailedBolusInfo.insulin));
} }
@ -857,9 +864,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
// LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery");
MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetBolus, MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetBolus,
detailedBolusInfo.insulin); Arrays.asList(detailedBolusInfo.insulin));
Boolean response = (Boolean) responseTask.returnData; Boolean response = (Boolean) responseTask.getResult();
setRefreshButtonEnabled(true); setRefreshButtonEnabled(true);
@ -894,7 +901,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
} }
// we subtract insulin, exact amount will be visible with next remainingInsulin update. // we subtract insulin, exact amount will be visible with next remainingInsulin update.
medtronicPumpStatus.reservoirRemainingUnits -= detailedBolusInfo.insulin; medtronicPumpStatus.setReservoirRemainingUnits(medtronicPumpStatus.getReservoirRemainingUnits() - detailedBolusInfo.insulin);
incrementStatistics(detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? MedtronicConst.Statistics.SMBBoluses incrementStatistics(detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? MedtronicConst.Statistics.SMBBoluses
: MedtronicConst.Statistics.StandardBoluses); : MedtronicConst.Statistics.StandardBoluses);
@ -1022,7 +1029,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR); MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR);
Boolean response = (Boolean) responseTask2.returnData; Boolean response = (Boolean) responseTask2.getResult();
if (response) { if (response) {
aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled."); aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled.");
@ -1038,17 +1045,17 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
// now start new TBR // now start new TBR
MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetTemporaryBasal, MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetTemporaryBasal,
absoluteRate, durationInMinutes); Arrays.asList(absoluteRate, durationInMinutes));
Boolean response = (Boolean) responseTask.returnData; Boolean response = (Boolean) responseTask.getResult();
aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response); aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response);
if (response) { if (response) {
// FIXME put this into UIPostProcessor // FIXME put this into UIPostProcessor
medtronicPumpStatus.tempBasalStart = new Date(); medtronicPumpStatus.setTempBasalStart(new Date());
medtronicPumpStatus.tempBasalAmount = absoluteRate; medtronicPumpStatus.setTempBasalAmount(absoluteRate);
medtronicPumpStatus.tempBasalLength = durationInMinutes; medtronicPumpStatus.setTempBasalLength(durationInMinutes);
TemporaryBasal tempStart = new TemporaryBasal(getInjector()) // TemporaryBasal tempStart = new TemporaryBasal(getInjector()) //
.date(System.currentTimeMillis()) // .date(System.currentTimeMillis()) //
@ -1122,7 +1129,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1); scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1);
} }
if (this.medtronicPumpStatus.basalProfileStatus != BasalProfileStatus.NotInitialized if (this.medtronicPumpStatus.getBasalProfileStatus() != BasalProfileStatus.NotInitialized
&& medtronicHistoryData.hasBasalProfileChanged()) { && medtronicHistoryData.hasBasalProfileChanged()) {
medtronicHistoryData.processLastBasalProfileChange(pumpDescription.getPumpType(), medtronicPumpStatus); medtronicHistoryData.processLastBasalProfileChange(pumpDescription.getPumpType(), medtronicPumpStatus);
} }
@ -1194,7 +1201,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
} }
} else { } else {
if (debugHistory) if (debugHistory)
aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.gsonInstance.toJson(lastPumpHistoryEntry)); aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.getGsonInstance().toJson(lastPumpHistoryEntry));
medtronicHistoryData.setIsInInit(false); medtronicHistoryData.setIsInInit(false);
// medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime); // medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime);
@ -1204,12 +1211,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
//aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate);
MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetHistoryData, MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetHistoryData,
lastPumpHistoryEntry, targetDate); Arrays.asList(lastPumpHistoryEntry, targetDate));
if (debugHistory) if (debugHistory)
aapsLogger.debug(LTag.PUMP, "HST: After task"); aapsLogger.debug(LTag.PUMP, "HST: After task");
PumpHistoryResult historyResult = (PumpHistoryResult) responseTask2.returnData; PumpHistoryResult historyResult = (PumpHistoryResult) responseTask2.getResult();
if (debugHistory) if (debugHistory)
aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString()); aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString());
@ -1226,7 +1233,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.getAtechDateTime()); sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.getAtechDateTime());
if (debugHistory) if (debugHistory)
aapsLogger.debug(LTag.PUMP, "HST: History: valid=" + historyResult.validEntries.size() + ", unprocessed=" + historyResult.unprocessedEntries.size()); aapsLogger.debug(LTag.PUMP, "HST: History: valid=" + historyResult.getValidEntries().size() + ", unprocessed=" + historyResult.getUnprocessedEntries().size());
this.medtronicHistoryData.addNewHistory(historyResult); this.medtronicHistoryData.addNewHistory(historyResult);
this.medtronicHistoryData.filterNewEntries(); this.medtronicHistoryData.filterNewEntries();
@ -1281,7 +1288,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
switch (refreshType) { switch (refreshType) {
case RemainingInsulin: { case RemainingInsulin: {
double remaining = medtronicPumpStatus.reservoirRemainingUnits; double remaining = medtronicPumpStatus.getReservoirRemainingUnits();
int min; int min;
if (remaining > 50) if (remaining > 50)
min = 4 * 60; min = 4 * 60;
@ -1348,7 +1355,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.ReadTemporaryBasal); MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.ReadTemporaryBasal);
if (responseTask.hasData()) { if (responseTask.hasData()) {
TempBasalPair tbr = (TempBasalPair) responseTask.returnData; TempBasalPair tbr = (TempBasalPair) responseTask.getResult();
// we sometimes get rate returned even if TBR is no longer running // we sometimes get rate returned even if TBR is no longer running
if (tbr.getDurationMinutes() == 0) { if (tbr.getDurationMinutes() == 0) {
@ -1397,7 +1404,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR); MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR);
Boolean response = (Boolean) responseTask2.returnData; Boolean response = (Boolean) responseTask2.getResult();
finishAction("TBR"); finishAction("TBR");
@ -1434,7 +1441,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
@NonNull @Override @NonNull @Override
public String serialNumber() { public String serialNumber() {
return medtronicPumpStatus.serialNumber; return medtronicPumpStatus.getSerialNumber();
} }
@NonNull @Override @NonNull @Override
@ -1465,6 +1472,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
BasalProfile basalProfile = convertProfileToMedtronicProfile(profile); BasalProfile basalProfile = convertProfileToMedtronicProfile(profile);
aapsLogger.debug("Basal Profile: " + basalProfile);
String profileInvalid = isProfileValid(basalProfile); String profileInvalid = isProfileValid(basalProfile);
if (profileInvalid != null) { if (profileInvalid != null) {
@ -1475,9 +1484,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
} }
MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetBasalProfileSTD, MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetBasalProfileSTD,
basalProfile); Arrays.asList(basalProfile));
Boolean response = (Boolean) responseTask.returnData; Boolean response = (Boolean) responseTask.getResult();
aapsLogger.info(LTag.PUMP, getLogPrefix() + "Basal Profile was set: " + response); aapsLogger.info(LTag.PUMP, getLogPrefix() + "Basal Profile was set: " + response);
@ -1494,12 +1503,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
if (medtronicPumpStatus.maxBasal == null) if (medtronicPumpStatus.getMaxBasal() == null)
return null; return null;
for (BasalProfileEntry profileEntry : basalProfile.getEntries()) { for (BasalProfileEntry profileEntry : basalProfile.getEntries()) {
if (profileEntry.getRate() > medtronicPumpStatus.maxBasal) { if (profileEntry.getRate() > medtronicPumpStatus.getMaxBasal()) {
stringBuilder.append(profileEntry.getStartTime().toString("HH:mm")); stringBuilder.append(profileEntry.getStartTime().toString("HH:mm"));
stringBuilder.append("="); stringBuilder.append("=");
stringBuilder.append(profileEntry.getRate()); stringBuilder.append(profileEntry.getRate());

View file

@ -80,8 +80,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
@Inject @Inject
public void onInit() { public void onInit() {
// we can't do this in the constructor, as sp only gets injected after the constructor has returned // we can't do this in the constructor, as sp only gets injected after the constructor has returned
medtronicPumpStatus.previousConnection = sp.getLong( medtronicPumpStatus.setPreviousConnection(sp.getLong(
RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L));
} }
@Override @Override
@ -136,7 +136,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
if (!canPreventTuneUp) { if (!canPreventTuneUp) {
long diff = System.currentTimeMillis() - medtronicPumpStatus.lastConnection; long diff = System.currentTimeMillis() - medtronicPumpStatus.getLastConnection();
if (diff > RILEYLINK_TIMEOUT) { if (diff > RILEYLINK_TIMEOUT) {
serviceTaskExecutor.startTask(new WakeAndTuneTask(injector)); serviceTaskExecutor.startTask(new WakeAndTuneTask(injector));
@ -278,7 +278,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
for (List<Byte> frame : frames) { for (List<Byte> frame : frames) {
byte[] frameData = MedtronicUtil.createByteArray(frame); byte[] frameData = medtronicUtil.createByteArray(frame);
// aapsLogger.debug(LTag.PUMPCOMM,"Frame {} data:\n{}", frameNr, ByteUtil.getCompactString(frameData)); // aapsLogger.debug(LTag.PUMPCOMM,"Frame {} data:\n{}", frameNr, ByteUtil.getCompactString(frameData));
@ -570,7 +570,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
try { try {
PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries));
String check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength); String check = checkResponseContent(response, commandType.getCommandDescription(), commandType.getExpectedLength());
if (check == null) { if (check == null) {
@ -632,11 +632,11 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// PUMP SPECIFIC COMMANDS // PUMP SPECIFIC COMMANDS
public Float getRemainingInsulin() { public Double getRemainingInsulin() {
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin); Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin);
return responseObject == null ? null : (Float) responseObject; return responseObject == null ? null : (Double) responseObject;
} }
@ -677,7 +677,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent())); // aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent()));
// aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData())); // aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData()));
String check = checkResponseContent(response, commandType.commandDescription, 1); String check = checkResponseContent(response, commandType.getCommandDescription(), 1);
byte[] data = null; byte[] data = null;
@ -695,7 +695,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs, // aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs,
// HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData())); // HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData()));
String check2 = checkResponseContent(response, commandType.commandDescription, 1); String check2 = checkResponseContent(response, commandType.getCommandDescription(), 1);
if (check2 == null) { if (check2 == null) {
@ -765,12 +765,12 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
public ClockDTO getPumpTime() { public ClockDTO getPumpTime() {
ClockDTO clockDTO = new ClockDTO(); ClockDTO clockDTO = new ClockDTO();
clockDTO.localDeviceTime = new LocalDateTime(); clockDTO.setLocalDeviceTime(new LocalDateTime());
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock); Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock);
if (responseObject != null) { if (responseObject != null) {
clockDTO.pumpTime = (LocalDateTime) responseObject; clockDTO.setPumpTime((LocalDateTime) responseObject);
return clockDTO; return clockDTO;
} }

View file

@ -58,7 +58,7 @@ class MedtronicConverter @Inject constructor(
} }
MedtronicCommandType.ReadTemporaryBasal -> { MedtronicCommandType.ReadTemporaryBasal -> {
TempBasalPair(aapsLogger, rawContent) // 5 TempBasalPair(aapsLogger, rawContent!!) // 5
} }
MedtronicCommandType.Settings_512 -> { MedtronicCommandType.Settings_512 -> {
@ -112,7 +112,7 @@ class MedtronicConverter @Inject constructor(
batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown
} }
if (rawData.size > 1) { if (rawData.size > 1) {
var d: Double? = null var d: Double? //= null
// if response in 3 bytes then we add additional information // if response in 3 bytes then we add additional information
d = if (rawData.size == 2) { d = if (rawData.size == 2) {
@ -126,7 +126,7 @@ class MedtronicConverter @Inject constructor(
return batteryStatus return batteryStatus
} }
private fun decodeRemainingInsulin(rawData: ByteArray?): Float { private fun decodeRemainingInsulin(rawData: ByteArray?): Double {
var startIdx = 0 var startIdx = 0
val pumpModel = medtronicUtil.medtronicPumpModel val pumpModel = medtronicUtil.medtronicPumpModel
val strokes = pumpModel?.bolusStrokes ?: 10 val strokes = pumpModel?.bolusStrokes ?: 10
@ -134,11 +134,11 @@ class MedtronicConverter @Inject constructor(
startIdx = 2 startIdx = 2
} }
val reqLength = startIdx + 1 val reqLength = startIdx + 1
var value = 0f var value = 0.0
value = if (reqLength >= rawData!!.size) { value = if (reqLength >= rawData!!.size) {
rawData[startIdx] / (1.0f * strokes) rawData[startIdx] / (1.0 * strokes)
} else { } else {
ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0f * strokes) ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0 * strokes)
} }
aapsLogger.debug(LTag.PUMPCOMM, "Remaining insulin: $value") aapsLogger.debug(LTag.PUMPCOMM, "Remaining insulin: $value")
return value return value
@ -208,7 +208,7 @@ class MedtronicConverter @Inject constructor(
rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map) rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map)
addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h", addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h",
PumpConfigurationGroup.General, map) PumpConfigurationGroup.General, map)
if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) {
addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + if (rd[9].toInt() == 0) 50 else 100, PumpConfigurationGroup.Insulin, addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + if (rd[9].toInt() == 0) 50 else 100, PumpConfigurationGroup.Insulin,
map) map)
// LOG.debug("Insulin concentration: " + rd[9]); // LOG.debug("Insulin concentration: " + rd[9]);
@ -249,7 +249,7 @@ class MedtronicConverter @Inject constructor(
addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]),
PumpConfigurationGroup.Other, map) PumpConfigurationGroup.Other, map)
addSettingToMap("CFG_MM_KEYPAD_LOCKED", parseResultEnable(rd[20].toInt()), PumpConfigurationGroup.Other, map) addSettingToMap("CFG_MM_KEYPAD_LOCKED", parseResultEnable(rd[20].toInt()), PumpConfigurationGroup.Other, map)
if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) {
addSettingToMap("PCFG_BOLUS_SCROLL_STEP_SIZE", "" + rd[21], PumpConfigurationGroup.Bolus, map) addSettingToMap("PCFG_BOLUS_SCROLL_STEP_SIZE", "" + rd[21], PumpConfigurationGroup.Bolus, map)
addSettingToMap("PCFG_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22].toInt()), PumpConfigurationGroup.Other, map) addSettingToMap("PCFG_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22].toInt()), PumpConfigurationGroup.Other, map)
addSettingToMap("PCFG_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23].toInt()), PumpConfigurationGroup.Other, map) addSettingToMap("PCFG_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23].toInt()), PumpConfigurationGroup.Other, map)
@ -273,7 +273,7 @@ class MedtronicConverter @Inject constructor(
// 512 // 512
private fun decodeInsulinActionSetting(ai: ByteArray, map: MutableMap<String, PumpSettingDTO>) { private fun decodeInsulinActionSetting(ai: ByteArray, map: MutableMap<String, PumpSettingDTO>) {
if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712)) { if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_512_712)) {
addSettingToMap("PCFG_INSULIN_ACTION_TYPE", if (ai[17].toInt() != 0) "Regular" else "Fast", addSettingToMap("PCFG_INSULIN_ACTION_TYPE", if (ai[17].toInt() != 0) "Regular" else "Fast",
PumpConfigurationGroup.Insulin, map) PumpConfigurationGroup.Insulin, map)
} else { } else {
@ -297,10 +297,10 @@ class MedtronicConverter @Inject constructor(
} }
private val settingIndexMaxBasal: Int private val settingIndexMaxBasal: Int
private get() = if (is523orHigher()) 7 else 6 get() = if (is523orHigher()) 7 else 6
private val settingIndexTimeDisplayFormat: Int private val settingIndexTimeDisplayFormat: Int
private get() = if (is523orHigher()) 9 else 8 get() = if (is523orHigher()) 9 else 8
private fun decodeMaxBolus(ai: ByteArray?): Double { private fun decodeMaxBolus(ai: ByteArray?): Double {
return if (is523orHigher()) decodeBolusInsulin(ByteUtil.toInt(ai!![5], ai[6])) else decodeBolusInsulin(ByteUtil return if (is523orHigher()) decodeBolusInsulin(ByteUtil.toInt(ai!![5], ai[6])) else decodeBolusInsulin(ByteUtil
@ -308,7 +308,7 @@ class MedtronicConverter @Inject constructor(
} }
private fun is523orHigher(): Boolean { private fun is523orHigher(): Boolean {
return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher) return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)
} }
} }

View file

@ -38,8 +38,8 @@ abstract class MedtronicHistoryDecoder<T : MedtronicHistoryEntry?> : MedtronicHi
private fun checkPage(page: RawHistoryPage, partial: Boolean): List<Byte> { private fun checkPage(page: RawHistoryPage, partial: Boolean): List<Byte> {
val byteList: List<Byte> = ArrayList() val byteList: List<Byte> = ArrayList()
if (medtronicUtil!!.medtronicPumpModel == null) { if (medtronicUtil.medtronicPumpModel == null) {
aapsLogger!!.error(LTag.PUMPCOMM, "Device Type is not defined.") aapsLogger.error(LTag.PUMPCOMM, "Device Type is not defined.")
return byteList return byteList
} }
return if (page.data.size != 1024) { return if (page.data.size != 1024) {
@ -82,9 +82,9 @@ abstract class MedtronicHistoryDecoder<T : MedtronicHistoryEntry?> : MedtronicHi
for ((key) in unknownOpCodes!!) { for ((key) in unknownOpCodes!!) {
StringUtil.appendToStringBuilder(sb, "" + key, ", ") StringUtil.appendToStringBuilder(sb, "" + key, ", ")
} }
aapsLogger!!.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE") aapsLogger.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE")
if (unknownOpCodes!!.size > 0) { if (unknownOpCodes!!.size > 0) {
aapsLogger!!.warn(LTag.PUMPCOMM, "Unknown Op Codes: $sb") aapsLogger.warn(LTag.PUMPCOMM, "Unknown Op Codes: $sb")
} }
for ((key, value) in mapStatistics!!) { for ((key, value) in mapStatistics!!) {
sb = StringBuilder() sb = StringBuilder()
@ -94,9 +94,9 @@ abstract class MedtronicHistoryDecoder<T : MedtronicHistoryEntry?> : MedtronicHi
StringUtil.appendToStringBuilder(sb, key1, ", ") StringUtil.appendToStringBuilder(sb, key1, ", ")
} }
val spaces = StringUtils.repeat(" ", 14 - key.name.length) val spaces = StringUtils.repeat(" ", 14 - key.name.length)
aapsLogger!!.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s%s - %d. Elements: %s", key.name, spaces, value.size, sb.toString())) aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s%s - %d. Elements: %s", key.name, spaces, value.size, sb.toString()))
} else { } else {
aapsLogger!!.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s - %d", key.name, value.size)) aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s - %d", key.name, value.size))
} }
} }
} }

View file

@ -82,7 +82,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface {
if (!doNotProcess) { if (!doNotProcess) {
head = ByteArray(headLength - 1) head = ByteArray(headLength - 1)
for (i in 1 until headLength) { for (i in 1 until headLength) {
head!![i - 1] = listRawData!![i]!! head!![i - 1] = listRawData[i]
} }
if (dateTimeLength > 0) { if (dateTimeLength > 0) {
datetime = ByteArray(dateTimeLength) datetime = ByteArray(dateTimeLength)
@ -99,7 +99,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface {
var i = headLength + dateTimeLength var i = headLength + dateTimeLength
var j = 0 var j = 0
while (j < bodyLength) { while (j < bodyLength) {
body!![j] = listRawData!![i]!! body!![j] = listRawData[i]
i++ i++
j++ j++
} }

View file

@ -37,7 +37,7 @@ class RawHistoryPage(private val aapsLogger: AAPSLogger) {
aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Stored CRC (%d) is different than calculated (%d), but ignored for now.", crcStored, aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Stored CRC (%d) is different than calculated (%d), but ignored for now.", crcStored,
crcCalculated)) crcCalculated))
} else { } else {
if (MedtronicUtil.isLowLevelDebug()) aapsLogger.debug(LTag.PUMPBTCOMM, "CRC ok.") if (MedtronicUtil.isLowLevelDebug) aapsLogger.debug(LTag.PUMPBTCOMM, "CRC ok.")
} }
return crcCalculated == crcStored return crcCalculated == crcStored
} }

View file

@ -49,7 +49,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
return outList return outList
} }
do { do {
val opCode: Int = dataClear[counter]!!.toInt() val opCode: Int = dataClear[counter].toInt()
var special = false var special = false
incompletePacket = false incompletePacket = false
var skippedRecords = false var skippedRecords = false
@ -69,7 +69,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
} }
val entryType = getByCode(opCode.toByte()) val entryType = getByCode(opCode.toByte())
val pe = PumpHistoryEntry() val pe = PumpHistoryEntry()
pe.setEntryType(medtronicUtil!!.medtronicPumpModel, entryType!!) pe.setEntryType(medtronicUtil.medtronicPumpModel!!, entryType!!)
pe.offset = counter pe.offset = counter
counter++ counter++
if (counter >= 1022) { if (counter >= 1022) {
@ -91,7 +91,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
} }
special = true special = true
} else { } else {
for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel) - 1) { for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel!!) - 1) {
try { try {
listRawData.add(dataClear[counter]) listRawData.add(dataClear[counter])
counter++ counter++
@ -111,7 +111,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
if (pe.entryType === PumpHistoryEntryType.UnknownBasePacket) { if (pe.entryType === PumpHistoryEntryType.UnknownBasePacket) {
pe.opCode = opCode.toByte() pe.opCode = opCode.toByte()
} }
if (entryType.getHeadLength(medtronicUtil!!.medtronicPumpModel) == 0) special = true if (entryType.getHeadLength(medtronicUtil!!.medtronicPumpModel!!) == 0) special = true
pe.setData(listRawData as List<Byte>, special) pe.setData(listRawData as List<Byte>, special)
val decoded = decodeRecord(pe) val decoded = decodeRecord(pe)
if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) {
@ -235,7 +235,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
val offset = body!![0] * 1000 * 30 * 60 val offset = body!![0] * 1000 * 30 * 60
var rate: Float? = null var rate: Float? = null
val index = entry.head!![0].toInt() val index = entry.head!![0].toInt()
if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) {
rate = body[1] * 0.025f rate = body[1] * 0.025f
} }
@ -254,7 +254,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
val body = entry.body!! val body = entry.body!!
val dto = BolusWizardDTO() val dto = BolusWizardDTO()
var bolusStrokes = 10.0f var bolusStrokes = 10.0f
if (MedtronicDeviceType.isSameDevice(medtronicUtil!!.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { if (MedtronicDeviceType.isSameDevice(medtronicUtil!!.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) {
// https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102 // https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102
bolusStrokes = 40.0f bolusStrokes = 40.0f
dto.carbs = ((body[1] and 0x0c.toByte()).toInt() shl 6) + body[0] dto.carbs = ((body[1] and 0x0c.toByte()).toInt() shl 6) + body[0]
@ -263,19 +263,19 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
// carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) /
// 10.0s // 10.0s
dto.insulinSensitivity = body[4].toFloat() dto.insulinSensitivity = body[4].toFloat()
dto.bgTargetLow = body[5] as Int dto.bgTargetLow = body[5].toInt()
dto.bgTargetHigh = body[14] as Int dto.bgTargetHigh = body[14].toInt()
dto.correctionEstimate = (((body[9] and 0x38).toInt() shl 5) + body[6]) / bolusStrokes dto.correctionEstimate = (((body[9] and 0x38).toInt() shl 5) + body[6]) / bolusStrokes
dto.foodEstimate = ((body[7].toInt() shl 8) + body[8]) / bolusStrokes dto.foodEstimate = ((body[7].toInt() shl 8) + body[8]) / bolusStrokes
dto.unabsorbedInsulin = ((body[10].toInt() shl 8) + body[11]) / bolusStrokes dto.unabsorbedInsulin = ((body[10].toInt() shl 8) + body[11]) / bolusStrokes
dto.bolusTotal = ((body[12].toInt() shl 8) + body[13]) / bolusStrokes dto.bolusTotal = ((body[12].toInt() shl 8) + body[13]) / bolusStrokes
} else { } else {
dto.bloodGlucose = (body.get(1) and 0x0F).toInt() shl 8 or entry.head!!.get(0).toInt() dto.bloodGlucose = (body.get(1) and 0x0F).toInt() shl 8 or entry.head!!.get(0).toInt()
dto.carbs = body.get(0) as Int dto.carbs = body.get(0).toInt()
dto.carbRatio = body.get(2).toFloat() dto.carbRatio = body.get(2).toFloat()
dto.insulinSensitivity = body.get(3).toFloat() dto.insulinSensitivity = body.get(3).toFloat()
dto.bgTargetLow = body.get(4) as Int dto.bgTargetLow = body.get(4).toInt()
dto.bgTargetHigh = body.get(12) as Int dto.bgTargetHigh = body.get(12).toInt()
dto.bolusTotal = body.get(11) / bolusStrokes dto.bolusTotal = body.get(11) / bolusStrokes
dto.foodEstimate = body.get(6) / bolusStrokes dto.foodEstimate = body.get(6) / bolusStrokes
dto.unabsorbedInsulin = body.get(9) / bolusStrokes dto.unabsorbedInsulin = body.get(9) / bolusStrokes
@ -359,7 +359,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
private fun decodeBolus(entry: PumpHistoryEntry) { private fun decodeBolus(entry: PumpHistoryEntry) {
val bolus = BolusDTO() val bolus = BolusDTO()
val data = entry.head!! val data = entry.head!!
if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) {
bolus.requestedAmount = ByteUtil.toInt(data.get(0), data.get(1)) / 40.0 bolus.requestedAmount = ByteUtil.toInt(data.get(0), data.get(1)) / 40.0
bolus.deliveredAmount = ByteUtil.toInt(data.get(2), data.get(3)) / 40.0 bolus.deliveredAmount = ByteUtil.toInt(data.get(2), data.get(3)) / 40.0
bolus.insulinOnBoard = ByteUtil.toInt(data.get(4), data.get(5)) / 40.0 bolus.insulinOnBoard = ByteUtil.toInt(data.get(4), data.get(5)) / 40.0
@ -369,8 +369,8 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
bolus.deliveredAmount = ByteUtil.asUINT8(data.get(1)) / 10.0 bolus.deliveredAmount = ByteUtil.asUINT8(data.get(1)) / 10.0
bolus.duration = ByteUtil.asUINT8(data.get(2)) * 30 bolus.duration = ByteUtil.asUINT8(data.get(2)) * 30
} }
bolus.bolusType = if (bolus.duration != null && bolus.duration > 0) PumpBolusType.Extended else PumpBolusType.Normal bolus.bolusType = if (bolus.duration != null && bolus.duration!! > 0) PumpBolusType.Extended else PumpBolusType.Normal
bolus.setAtechDateTime(entry.atechDateTime!!) bolus.atechDateTime = entry.atechDateTime!!
entry.addDecodedData("Object", bolus) entry.addDecodedData("Object", bolus)
entry.displayableValue = bolus.displayableValue entry.displayableValue = bolus.displayableValue
} }
@ -404,10 +404,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
// tbrDuration.getHead()[0], // tbrDuration.getHead()[0],
// (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0); // (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0);
val tbr = TempBasalPair( val tbr = TempBasalPair(
tbrRate!!.head!!.get(0), tbrRate.head!!.get(0),
tbrRate!!.body!!.get(0), tbrRate.body!!.get(0),
tbrDuration!!.head!!.get(0).toInt(), tbrDuration!!.head!!.get(0).toInt(),
ByteUtil.asUINT8(tbrRate!!.datetime!!.get(4)) shr 3 == 0) ByteUtil.asUINT8(tbrRate.datetime!!.get(4)) shr 3 == 0)
// System.out.println("TBR: amount=" + tbr.getInsulinRate() + ", duration=" + tbr.getDurationMinutes() // System.out.println("TBR: amount=" + tbr.getInsulinRate() + ", duration=" + tbr.getDurationMinutes()
// // + " min. Packed: " + tbr.getValue() // // + " min. Packed: " + tbr.getValue()
@ -464,13 +464,13 @@ class MedtronicPumpHistoryDecoder @Inject constructor(
} }
private fun fix2DigitYear(year: Int): Int { private fun fix2DigitYear(year: Int): Int {
var year = year var yearInternal = year
year += if (year > 90) { yearInternal += if (yearInternal > 90) {
1900 1900
} else { } else {
2000 2000
} }
return year return yearInternal
} }
companion object { companion object {

View file

@ -35,16 +35,16 @@ class PumpHistoryEntry : MedtronicHistoryEntry() {
field = value field = value
} }
fun setEntryType(medtronicDeviceType: MedtronicDeviceType?, entryType: PumpHistoryEntryType) { fun setEntryType(medtronicDeviceType: MedtronicDeviceType, entryType: PumpHistoryEntryType) {
this.entryType = entryType this.entryType = entryType
sizes[0] = entryType.getHeadLength(medtronicDeviceType) sizes[0] = entryType.getHeadLength(medtronicDeviceType)
sizes[1] = entryType.dateLength sizes[1] = entryType.dateLength
sizes[2] = entryType.getBodyLength(medtronicDeviceType) sizes[2] = entryType.getBodyLength(medtronicDeviceType)
if (this.entryType != null && atechDateTime != null) setPumpId() if (this.entryType != null && atechDateTime != null) generatePumpId()
} }
private fun setPumpId() { private fun generatePumpId() : Long {
pumpId = entryType!!.code + atechDateTime!! * 1000L return entryType!!.code + atechDateTime!! * 1000L
} }
override val toStringStart: String override val toStringStart: String
@ -105,7 +105,7 @@ class PumpHistoryEntry : MedtronicHistoryEntry() {
override var pumpId: Long? = null override var pumpId: Long? = null
get() { get() {
setPumpId() field = generatePumpId()
return field return field
} }
set(pumpId) { set(pumpId) {

View file

@ -212,7 +212,7 @@ enum class PumpHistoryEntryType // implements CodeEnum
private constructor(opCode: Byte, group: PumpHistoryEntryGroup) : this(opCode, null, group, 2, 5, 0) {} private constructor(opCode: Byte, group: PumpHistoryEntryGroup) : this(opCode, null, group, 2, 5, 0) {}
private constructor(opCode: Byte, group: PumpHistoryEntryGroup, head: Int, date: Int, body: Int) : this(opCode, null, group, head, date, body) {} private constructor(opCode: Byte, group: PumpHistoryEntryGroup, head: Int, date: Int, body: Int) : this(opCode, null, group, head, date, body) {}
fun getTotalLength(medtronicDeviceType: MedtronicDeviceType?): Int { fun getTotalLength(medtronicDeviceType: MedtronicDeviceType): Int {
return if (hasSpecialRules) { return if (hasSpecialRules) {
getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + dateLength getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + dateLength
} else { } else {
@ -220,10 +220,6 @@ enum class PumpHistoryEntryType // implements CodeEnum
} }
} }
// private fun hasSpecialRules(): Boolean {
// return hasSpecialRules
// }
fun addSpecialRuleHead(rule: SpecialRule) { fun addSpecialRuleHead(rule: SpecialRule) {
if (isEmpty(specialRulesHead)) { if (isEmpty(specialRulesHead)) {
specialRulesHead = ArrayList() specialRulesHead = ArrayList()
@ -244,7 +240,7 @@ enum class PumpHistoryEntryType // implements CodeEnum
// return description ?: name // return description ?: name
// } // }
fun getHeadLength(medtronicDeviceType: MedtronicDeviceType?): Int { fun getHeadLength(medtronicDeviceType: MedtronicDeviceType): Int {
return if (hasSpecialRules) { return if (hasSpecialRules) {
if (isNotEmpty(specialRulesHead)) { if (isNotEmpty(specialRulesHead)) {
determineSizeByRule(medtronicDeviceType, headLength, specialRulesHead) determineSizeByRule(medtronicDeviceType, headLength, specialRulesHead)
@ -256,7 +252,7 @@ enum class PumpHistoryEntryType // implements CodeEnum
} }
} }
fun getBodyLength(medtronicDeviceType: MedtronicDeviceType?): Int { fun getBodyLength(medtronicDeviceType: MedtronicDeviceType): Int {
return if (hasSpecialRules) { return if (hasSpecialRules) {
if (isNotEmpty(specialRulesBody)) { if (isNotEmpty(specialRulesBody)) {
determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody) determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody)
@ -277,7 +273,7 @@ enum class PumpHistoryEntryType // implements CodeEnum
} }
// byte[] dh = { 2, 3 }; // byte[] dh = { 2, 3 };
private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType?, defaultValue: Int, rules: List<SpecialRule>?): Int { private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType, defaultValue: Int, rules: List<SpecialRule>?): Int {
var size = defaultValue var size = defaultValue
for (rule in rules!!) { for (rule in rules!!) {
if (MedtronicDeviceType.isSameDevice(medtronicDeviceType, rule.deviceType)) { if (MedtronicDeviceType.isSameDevice(medtronicDeviceType, rule.deviceType)) {

View file

@ -4,6 +4,7 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import java.util.* import java.util.*
import kotlin.collections.ArrayList
/** /**
* History page contains data, sorted from newest to oldest (0=newest..n=oldest) * History page contains data, sorted from newest to oldest (0=newest..n=oldest)
@ -18,9 +19,11 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis
private val searchEntry: PumpHistoryEntry? = null private val searchEntry: PumpHistoryEntry? = null
private var searchDate: Long? = null private var searchDate: Long? = null
private var searchType = SearchType.None private var searchType = SearchType.None
@JvmField var unprocessedEntries: List<PumpHistoryEntry?>? = null var unprocessedEntries: List<PumpHistoryEntry> = ArrayList()
@JvmField var validEntries: MutableList<PumpHistoryEntry?>? var validEntries: MutableList<PumpHistoryEntry> = ArrayList()
fun addHistoryEntries(entries: List<PumpHistoryEntry?>?, page: Int) {
fun addHistoryEntries(entries: List<PumpHistoryEntry>, page: Int) {
unprocessedEntries = entries unprocessedEntries = entries
//aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries)); //aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries));
processEntries() processEntries()
@ -32,7 +35,7 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis
Collections.reverse(unprocessedEntries) Collections.reverse(unprocessedEntries)
when (searchType) { when (searchType) {
SearchType.None -> //aapsLogger.debug(LTag.PUMPCOMM,"PE. None search"); SearchType.None -> //aapsLogger.debug(LTag.PUMPCOMM,"PE. None search");
validEntries!!.addAll(unprocessedEntries!!) validEntries.addAll(unprocessedEntries)
SearchType.LastEntry -> { SearchType.LastEntry -> {
aapsLogger.debug(LTag.PUMPCOMM, "PE. Last entry search") aapsLogger.debug(LTag.PUMPCOMM, "PE. Last entry search")
@ -40,27 +43,27 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis
//Collections.sort(this.unprocessedEntries, new PumpHistoryEntry.Comparator()); //Collections.sort(this.unprocessedEntries, new PumpHistoryEntry.Comparator());
aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: " + searchEntry!!.atechDateTime) aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: " + searchEntry!!.atechDateTime)
val date = searchEntry.atechDateTime val date = searchEntry.atechDateTime
for (unprocessedEntry in unprocessedEntries!!) { for (unprocessedEntry in unprocessedEntries) {
if (unprocessedEntry!!.equals(searchEntry)) { if (unprocessedEntry.equals(searchEntry)) {
//aapsLogger.debug(LTag.PUMPCOMM,"PE. Item found {}.", unprocessedEntry); //aapsLogger.debug(LTag.PUMPCOMM,"PE. Item found {}.", unprocessedEntry);
isSearchFinished = true isSearchFinished = true
break break
} }
//aapsLogger.debug(LTag.PUMPCOMM,"PE. Entry {} added.", unprocessedEntry); //aapsLogger.debug(LTag.PUMPCOMM,"PE. Entry {} added.", unprocessedEntry);
validEntries!!.add(unprocessedEntry) validEntries.add(unprocessedEntry)
} }
} }
SearchType.Date -> { SearchType.Date -> {
aapsLogger.debug(LTag.PUMPCOMM, "PE. Date search: Search date: " + searchDate) aapsLogger.debug(LTag.PUMPCOMM, "PE. Date search: Search date: " + searchDate)
for (unprocessedEntry in unprocessedEntries!!) { for (unprocessedEntry in unprocessedEntries) {
if (unprocessedEntry!!.atechDateTime == null || unprocessedEntry.atechDateTime == 0L) { if (unprocessedEntry.atechDateTime == null || unprocessedEntry.atechDateTime == 0L) {
aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: Entry with no date: $unprocessedEntry") aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: Entry with no date: $unprocessedEntry")
continue continue
} }
if (unprocessedEntry.isAfter(searchDate!!)) { if (unprocessedEntry.isAfter(searchDate!!)) {
validEntries!!.add(unprocessedEntry) validEntries.add(unprocessedEntry)
} else { } else {
// aapsLogger.debug(LTag.PUMPCOMM,"PE. PumpHistoryResult. Not after.. Unprocessed Entry [year={},entry={}]", // aapsLogger.debug(LTag.PUMPCOMM,"PE. PumpHistoryResult. Not after.. Unprocessed Entry [year={},entry={}]",
// DateTimeUtil.getYear(unprocessedEntry.atechDateTime), unprocessedEntry); // DateTimeUtil.getYear(unprocessedEntry.atechDateTime), unprocessedEntry);
@ -85,35 +88,19 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis
", searchType=" + searchType + // ", searchType=" + searchType + //
", searchFinished=" + isSearchFinished + // ", searchFinished=" + isSearchFinished + //
"]" "]"
}// PumpHistoryEntry pumpHistoryEntry = this.validEntries.get(0); }
//
// if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.EndResultTotals)
// return pumpHistoryEntry;
// else
// return this.validEntries.get(1);
/** /**
* Return latest entry (entry with highest date time) * Return latest entry (entry with highest date time)
*
* @return * @return
*/ */
val latestEntry: PumpHistoryEntry? val latestEntry: PumpHistoryEntry?
get() = if (validEntries == null || validEntries!!.size == 0) null else { get() = if (validEntries.size == 0) null else validEntries[0]
validEntries!![0]
// PumpHistoryEntry pumpHistoryEntry = this.validEntries.get(0);
//
// if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.EndResultTotals)
// return pumpHistoryEntry;
// else
// return this.validEntries.get(1);
}
val isSearchRequired: Boolean
get() = searchType != SearchType.None
fun getValidEntries(): List<PumpHistoryEntry?>? { // val isSearchRequired: Boolean
return validEntries // get() = searchType != SearchType.None
}
internal enum class SearchType { internal enum class SearchType {
None, // None, //
@ -139,6 +126,6 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis
} }
// this.unprocessedEntries = new ArrayList<>(); // this.unprocessedEntries = new ArrayList<>();
validEntries = ArrayList() //validEntries = ArrayList()
} }
} }

View file

@ -67,13 +67,13 @@ class PumpMessage : RLMessage {
override fun getTxData(): ByteArray { override fun getTxData(): ByteArray {
var rval = ByteUtil.concat(byteArrayOf(packetType!!.value), address) var rval = ByteUtil.concat(byteArrayOf(packetType!!.value), address)
rval = ByteUtil.concat(rval, commandType!!.getCommandCode()) rval = ByteUtil.concat(rval, commandType!!.commandCode)
rval = ByteUtil.concat(rval, messageBody!!.txData) rval = ByteUtil.concat(rval, messageBody!!.txData)
return rval return rval
} }
val contents: ByteArray val contents: ByteArray
get() = ByteUtil.concat(byteArrayOf(commandType!!.getCommandCode()), messageBody!!.txData)// length is not always correct so, we check whole array if we have get() = ByteUtil.concat(byteArrayOf(commandType!!.commandCode), messageBody!!.txData)// length is not always correct so, we check whole array if we have
// data, after length // data, after length
// check if displayed length is invalid // check if displayed length is invalid
@ -91,7 +91,7 @@ class PumpMessage : RLMessage {
val data = messageBody!!.txData val data = messageBody!!.txData
var length = ByteUtil.asUINT8(data!![0]) // length is not always correct so, we check whole array if we have var length = ByteUtil.asUINT8(data!![0]) // length is not always correct so, we check whole array if we have
// data, after length // data, after length
val originalLength = length //val originalLength = length
// check if displayed length is invalid // check if displayed length is invalid
if (length > data.size - 1) { if (length > data.size - 1) {

View file

@ -1,58 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
/**
* Created by andy on 6/14/18.
*/
public class MedtronicUIComm {
private final HasAndroidInjector injector;
private final AAPSLogger aapsLogger;
private final MedtronicUtil medtronicUtil;
private final MedtronicCommunicationManager medtronicCommunicationManager;
private final MedtronicUIPostprocessor medtronicUIPostprocessor;
public MedtronicUIComm(
HasAndroidInjector injector,
AAPSLogger aapsLogger,
MedtronicUtil medtronicUtil,
MedtronicUIPostprocessor medtronicUIPostprocessor,
MedtronicCommunicationManager medtronicCommunicationManager
) {
this.injector = injector;
this.aapsLogger = aapsLogger;
this.medtronicUtil = medtronicUtil;
this.medtronicUIPostprocessor = medtronicUIPostprocessor;
this.medtronicCommunicationManager = medtronicCommunicationManager;
}
public synchronized MedtronicUITask executeCommand(MedtronicCommandType commandType, Object... parameters) {
aapsLogger.info(LTag.PUMP, "Execute Command: " + commandType.name());
MedtronicUITask task = new MedtronicUITask(injector, commandType, parameters);
medtronicUtil.setCurrentCommand(commandType);
task.execute(medtronicCommunicationManager);
if (!task.isReceived()) {
aapsLogger.warn(LTag.PUMP, "Reply not received for " + commandType);
}
task.postProcess(medtronicUIPostprocessor);
return task;
}
public int getInvalidResponsesCount() {
return medtronicCommunicationManager.getNotConnectedCount();
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
/**
* Created by andy on 6/14/18.
*/
class MedtronicUIComm(
private val injector: HasAndroidInjector,
private val aapsLogger: AAPSLogger,
private val medtronicUtil: MedtronicUtil,
private val medtronicUIPostprocessor: MedtronicUIPostprocessor,
private val medtronicCommunicationManager: MedtronicCommunicationManager
) {
fun executeCommand(commandType: MedtronicCommandType): MedtronicUITask {
return executeCommand(commandType, null)
}
@Synchronized
fun executeCommand(commandType: MedtronicCommandType, parameters: List<Any>?): MedtronicUITask {
aapsLogger.info(LTag.PUMP, "Execute Command: " + commandType.name)
val task = MedtronicUITask(injector, commandType, parameters)
medtronicUtil.setCurrentCommand(commandType)
task.execute(medtronicCommunicationManager)
if (!task.isReceived) {
aapsLogger.warn(LTag.PUMP, "Reply not received for $commandType")
}
task.postProcess(medtronicUIPostprocessor)
return task
}
val invalidResponsesCount: Int
get() = medtronicCommunicationManager.notConnectedCount
}

View file

@ -1,252 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BatteryStatusDTO;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType;
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
/**
* Created by andy on 6/15/18.
*/
@Singleton
public class MedtronicUIPostprocessor {
private final AAPSLogger aapsLogger;
private final RxBusWrapper rxBus;
private final ResourceHelper resourceHelper;
private final MedtronicUtil medtronicUtil;
private final MedtronicPumpStatus medtronicPumpStatus;
private final MedtronicPumpPlugin medtronicPumpPlugin;
@Inject
public MedtronicUIPostprocessor(
AAPSLogger aapsLogger,
RxBusWrapper rxBus,
ResourceHelper resourceHelper,
MedtronicUtil medtronicUtil,
MedtronicPumpStatus medtronicPumpStatus,
MedtronicPumpPlugin medtronicPumpPlugin) {
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
this.resourceHelper = resourceHelper;
this.medtronicUtil = medtronicUtil;
this.medtronicPumpStatus = medtronicPumpStatus;
this.medtronicPumpPlugin = medtronicPumpPlugin;
}
// this is mostly intended for command that return certain statuses (Remaining Insulin, ...), and
// where responses won't be directly used
void postProcessData(MedtronicUITask uiTask) {
switch (uiTask.commandType) {
case SetBasalProfileSTD: {
Boolean response = (Boolean) uiTask.returnData;
if (response) {
BasalProfile basalProfile = (BasalProfile) uiTask.getParameter(0);
medtronicPumpStatus.basalsByHour = basalProfile.getProfilesByHour(medtronicPumpPlugin.getPumpDescription().getPumpType());
}
}
break;
case GetBasalProfileSTD: {
BasalProfile basalProfile = (BasalProfile) uiTask.returnData;
try {
Double[] profilesByHour = basalProfile.getProfilesByHour(medtronicPumpPlugin.getPumpDescription().getPumpType());
if (profilesByHour != null) {
medtronicPumpStatus.basalsByHour = profilesByHour;
medtronicPumpStatus.basalProfileStatus = BasalProfileStatus.ProfileOK;
} else {
uiTask.responseType = MedtronicUIResponseType.Error;
uiTask.errorDescription = "No profile found.";
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Basal Profile was NOT valid. [%s]", basalProfile.basalProfileToStringError()));
}
} catch (Exception ex) {
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Basal Profile was returned, but was invalid. [%s]", basalProfile.basalProfileToStringError()));
uiTask.responseType = MedtronicUIResponseType.Error;
uiTask.errorDescription = "No profile found.";
}
}
break;
case SetBolus: {
medtronicPumpStatus.lastBolusAmount = uiTask.getDoubleFromParameters(0);
medtronicPumpStatus.lastBolusTime = new Date();
}
break;
case GetRemainingInsulin: {
medtronicPumpStatus.reservoirRemainingUnits = (Float) uiTask.returnData;
}
break;
case CancelTBR: {
medtronicPumpStatus.tempBasalStart = null;
medtronicPumpStatus.tempBasalAmount = null;
medtronicPumpStatus.tempBasalLength = null;
}
break;
case GetRealTimeClock: {
processTime(uiTask);
}
break;
case SetRealTimeClock: {
boolean response = (Boolean) uiTask.returnData;
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "New time was %s set.", response ? "" : "NOT"));
if (response) {
medtronicUtil.getPumpTime().timeDifference = 0;
}
}
break;
case GetBatteryStatus: {
BatteryStatusDTO batteryStatusDTO = (BatteryStatusDTO) uiTask.returnData;
medtronicPumpStatus.batteryRemaining = batteryStatusDTO.getCalculatedPercent(medtronicPumpStatus.batteryType);
if (batteryStatusDTO.voltage != null) {
medtronicPumpStatus.batteryVoltage = batteryStatusDTO.voltage;
}
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "BatteryStatus: %s", batteryStatusDTO.toString()));
}
break;
case PumpModel: {
if (medtronicPumpStatus.medtronicDeviceType != medtronicUtil.getMedtronicPumpModel()) {
aapsLogger.warn(LTag.PUMP, "Configured pump is different then pump detected !");
medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, resourceHelper, rxBus);
}
}
break;
case Settings_512:
case Settings: {
postProcessSettings(uiTask);
}
break;
// no postprocessing
default:
break;
//aapsLogger.error(LTag.PUMP, "Post-processing not implemented for {}.", uiTask.commandType.name());
}
}
private void processTime(MedtronicUITask uiTask) {
ClockDTO clockDTO = (ClockDTO) uiTask.returnData;
Duration dur = new Duration(clockDTO.pumpTime.toDateTime(DateTimeZone.UTC),
clockDTO.localDeviceTime.toDateTime(DateTimeZone.UTC));
clockDTO.timeDifference = (int) dur.getStandardSeconds();
medtronicUtil.setPumpTime(clockDTO);
aapsLogger.debug(LTag.PUMP, "Pump Time: " + clockDTO.localDeviceTime + ", DeviceTime=" + clockDTO.pumpTime + //
", diff: " + dur.getStandardSeconds() + " s");
// if (dur.getStandardMinutes() >= 10) {
// if (isLogEnabled())
// LOG.warn("Pump clock needs update, pump time: " + clockDTO.pumpTime.toString("HH:mm:ss") + " (difference: "
// + dur.getStandardSeconds() + " s)");
// sendNotification(MedtronicNotificationType.PumpWrongTimeUrgent);
// } else if (dur.getStandardMinutes() >= 4) {
// if (isLogEnabled())
// LOG.warn("Pump clock needs update, pump time: " + clockDTO.pumpTime.toString("HH:mm:ss") + " (difference: "
// + dur.getStandardSeconds() + " s)");
// sendNotification(MedtronicNotificationType.PumpWrongTimeNormal);
// }
}
private void postProcessSettings(MedtronicUITask uiTask) {
Map<String, PumpSettingDTO> settings = (Map<String, PumpSettingDTO>) uiTask.returnData;
medtronicUtil.setSettings(settings);
PumpSettingDTO checkValue;
medtronicPumpPlugin.getRileyLinkService().verifyConfiguration();
// check profile
if (!"Yes".equals(settings.get("PCFG_BASAL_PROFILES_ENABLED").value)) {
aapsLogger.error(LTag.PUMP, "Basal profiles are not enabled on pump.");
medtronicUtil.sendNotification(MedtronicNotificationType.PumpBasalProfilesNotEnabled, resourceHelper, rxBus);
} else {
checkValue = settings.get("PCFG_ACTIVE_BASAL_PROFILE");
if (!"STD".equals(checkValue.value)) {
aapsLogger.error("Basal profile set on pump is incorrect (must be STD).");
medtronicUtil.sendNotification(MedtronicNotificationType.PumpIncorrectBasalProfileSelected, resourceHelper, rxBus);
}
}
// TBR
checkValue = settings.get("PCFG_TEMP_BASAL_TYPE");
if (!"Units".equals(checkValue.value)) {
aapsLogger.error("Wrong TBR type set on pump (must be Absolute).");
medtronicUtil.sendNotification(MedtronicNotificationType.PumpWrongTBRTypeSet, resourceHelper, rxBus);
}
// MAXes
checkValue = settings.get("PCFG_MAX_BOLUS");
if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), medtronicPumpStatus.maxBolus)) {
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Wrong Max Bolus set on Pump (current=%s, required=%.2f).", checkValue.value, medtronicPumpStatus.maxBolus));
medtronicUtil.sendNotification(MedtronicNotificationType.PumpWrongMaxBolusSet, resourceHelper, rxBus, medtronicPumpStatus.maxBolus);
}
checkValue = settings.get("PCFG_MAX_BASAL");
if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), medtronicPumpStatus.maxBasal)) {
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Wrong Max Basal set on Pump (current=%s, required=%.2f).", checkValue.value, medtronicPumpStatus.maxBasal));
medtronicUtil.sendNotification(MedtronicNotificationType.PumpWrongMaxBasalSet, resourceHelper, rxBus, medtronicPumpStatus.maxBasal);
}
}
}

View file

@ -0,0 +1,188 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BatteryStatusDTO
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.joda.time.DateTimeZone
import org.joda.time.Duration
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
/**
* Created by andy on 6/15/18.
*/
@Singleton
class MedtronicUIPostprocessor @Inject constructor(
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
private val resourceHelper: ResourceHelper,
private val medtronicUtil: MedtronicUtil,
private val medtronicPumpStatus: MedtronicPumpStatus,
private val medtronicPumpPlugin: MedtronicPumpPlugin) {
// this is mostly intended for command that return certain statuses (Remaining Insulin, ...), and
// where responses won't be directly used
fun postProcessData(uiTask: MedtronicUITask) {
when (uiTask.commandType) {
MedtronicCommandType.SetBasalProfileSTD -> {
val response = uiTask.result as Boolean?
if (response!!) {
val basalProfile = uiTask.getParameter(0) as BasalProfile
aapsLogger.debug("D: basal profile returned after set: $basalProfile")
//var desc: PumpDescription = medtronicPumpPlugin.getP.getPumpDescription()
medtronicPumpStatus.basalsByHour = basalProfile.getProfilesByHour(medtronicPumpPlugin.pumpDescription.pumpType)
}
}
MedtronicCommandType.GetBasalProfileSTD -> {
val basalProfile = uiTask.result as BasalProfile?
//aapsLogger.debug("D: basal profile on read: " + basalProfile);
try {
val profilesByHour = basalProfile!!.getProfilesByHour(medtronicPumpPlugin.pumpDescription.pumpType)
if (profilesByHour != null) {
medtronicPumpStatus.basalsByHour = profilesByHour
medtronicPumpStatus.basalProfileStatus = BasalProfileStatus.ProfileOK
//aapsLogger.debug("D: basal profile on read: basalsByHour: " + BasalProfile.getProfilesByHourToString(medtronicPumpStatus.basalsByHour));
} else {
uiTask.responseType = MedtronicUIResponseType.Error
uiTask.errorDescription = "No profile found."
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Basal Profile was NOT valid. [%s]", basalProfile.basalProfileToStringError()))
}
} catch (ex: Exception) {
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Basal Profile was returned, but was invalid. [%s]", basalProfile!!.basalProfileToStringError()))
uiTask.responseType = MedtronicUIResponseType.Error
uiTask.errorDescription = "No profile found."
}
}
MedtronicCommandType.SetBolus -> {
medtronicPumpStatus.lastBolusAmount = uiTask.getDoubleFromParameters(0)
medtronicPumpStatus.lastBolusTime = Date()
}
MedtronicCommandType.GetRemainingInsulin -> {
medtronicPumpStatus.reservoirRemainingUnits = uiTask.result as Double
}
MedtronicCommandType.CancelTBR -> {
medtronicPumpStatus.tempBasalStart = null
medtronicPumpStatus.tempBasalAmount = null
medtronicPumpStatus.tempBasalLength = null
}
MedtronicCommandType.GetRealTimeClock -> {
processTime(uiTask)
}
MedtronicCommandType.SetRealTimeClock -> {
val response = uiTask.result as Boolean
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "New time was %s set.", if (response) "" else "NOT"))
if (response) {
medtronicUtil.pumpTime!!.timeDifference = 0
}
}
MedtronicCommandType.GetBatteryStatus -> {
val batteryStatusDTO = uiTask.result as BatteryStatusDTO?
medtronicPumpStatus.batteryRemaining = batteryStatusDTO!!.getCalculatedPercent(medtronicPumpStatus.batteryType)
if (batteryStatusDTO.voltage != null) {
medtronicPumpStatus.batteryVoltage = batteryStatusDTO.voltage
}
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "BatteryStatus: %s", batteryStatusDTO.toString()))
}
MedtronicCommandType.PumpModel -> {
if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) {
aapsLogger.warn(LTag.PUMP, "Configured pump is different then pump detected !")
medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, resourceHelper, rxBus)
}
}
MedtronicCommandType.Settings_512,
MedtronicCommandType.Settings -> {
postProcessSettings(uiTask)
}
else -> {
}
}
}
private fun processTime(uiTask: MedtronicUITask) {
val clockDTO = uiTask.result as ClockDTO?
val dur = Duration(clockDTO!!.pumpTime!!.toDateTime(DateTimeZone.UTC),
clockDTO.localDeviceTime!!.toDateTime(DateTimeZone.UTC))
clockDTO.timeDifference = dur.standardSeconds.toInt()
medtronicUtil.pumpTime = clockDTO
aapsLogger.debug(LTag.PUMP, "Pump Time: " + clockDTO.localDeviceTime + ", DeviceTime=" + clockDTO.pumpTime + //
", diff: " + dur.standardSeconds + " s")
// if (dur.getStandardMinutes() >= 10) {
// if (isLogEnabled())
// LOG.warn("Pump clock needs update, pump time: " + clockDTO.pumpTime.toString("HH:mm:ss") + " (difference: "
// + dur.getStandardSeconds() + " s)");
// sendNotification(MedtronicNotificationType.PumpWrongTimeUrgent);
// } else if (dur.getStandardMinutes() >= 4) {
// if (isLogEnabled())
// LOG.warn("Pump clock needs update, pump time: " + clockDTO.pumpTime.toString("HH:mm:ss") + " (difference: "
// + dur.getStandardSeconds() + " s)");
// sendNotification(MedtronicNotificationType.PumpWrongTimeNormal);
// }
}
private fun postProcessSettings(uiTask: MedtronicUITask) {
val settings = uiTask.result as Map<String, PumpSettingDTO>?
medtronicUtil.settings = settings
var checkValue: PumpSettingDTO?
medtronicPumpPlugin.rileyLinkService!!.verifyConfiguration()
// check profile
if ("Yes" != settings!!["PCFG_BASAL_PROFILES_ENABLED"]!!.value) {
aapsLogger.error(LTag.PUMP, "Basal profiles are not enabled on pump.")
medtronicUtil.sendNotification(MedtronicNotificationType.PumpBasalProfilesNotEnabled, resourceHelper, rxBus)
} else {
checkValue = settings["PCFG_ACTIVE_BASAL_PROFILE"]
if ("STD" != checkValue!!.value) {
aapsLogger.error("Basal profile set on pump is incorrect (must be STD).")
medtronicUtil.sendNotification(MedtronicNotificationType.PumpIncorrectBasalProfileSelected, resourceHelper, rxBus)
}
}
// TBR
checkValue = settings["PCFG_TEMP_BASAL_TYPE"]
if ("Units" != checkValue!!.value) {
aapsLogger.error("Wrong TBR type set on pump (must be Absolute).")
medtronicUtil.sendNotification(MedtronicNotificationType.PumpWrongTBRTypeSet, resourceHelper, rxBus)
}
// MAXes
checkValue = settings["PCFG_MAX_BOLUS"]
if (!MedtronicUtil.isSame(checkValue!!.value.toDouble(), medtronicPumpStatus.maxBolus!!)) {
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Wrong Max Bolus set on Pump (current=%s, required=%.2f).", checkValue.value, medtronicPumpStatus.maxBolus))
medtronicUtil.sendNotification(MedtronicNotificationType.PumpWrongMaxBolusSet, resourceHelper, rxBus, medtronicPumpStatus.maxBolus)
}
checkValue = settings["PCFG_MAX_BASAL"]
if (!MedtronicUtil.isSame(checkValue!!.value.toDouble(), medtronicPumpStatus.maxBasal!!)) {
aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Wrong Max Basal set on Pump (current=%s, required=%.2f).", checkValue.value, medtronicPumpStatus.maxBasal))
medtronicUtil.sendNotification(MedtronicNotificationType.PumpWrongMaxBasalSet, resourceHelper, rxBus, medtronicPumpStatus.maxBasal)
}
}
}

View file

@ -1,234 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui;
import org.joda.time.LocalDateTime;
import java.util.Locale;
import javax.inject.Inject;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType;
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
/**
* Created by andy on 6/14/18.
*/
public class MedtronicUITask {
@Inject RxBusWrapper rxBus;
@Inject AAPSLogger aapsLogger;
@Inject MedtronicPumpStatus medtronicPumpStatus;
@Inject MedtronicUtil medtronicUtil;
private final HasAndroidInjector injector;
public MedtronicCommandType commandType;
public Object returnData;
String errorDescription;
// boolean invalid = false;
private Object[] parameters;
// private boolean received;
MedtronicUIResponseType responseType;
public MedtronicUITask(HasAndroidInjector injector, MedtronicCommandType commandType) {
this.injector = injector;
this.injector.androidInjector().inject(this);
this.commandType = commandType;
}
public MedtronicUITask(HasAndroidInjector injector, MedtronicCommandType commandType, Object... parameters) {
this.injector = injector;
this.injector.androidInjector().inject(this);
this.commandType = commandType;
this.parameters = parameters;
}
public void execute(MedtronicCommunicationManager communicationManager) {
aapsLogger.debug(LTag.PUMP, "MedtronicUITask: @@@ In execute. " + commandType);
switch (commandType) {
case PumpModel: {
returnData = communicationManager.getPumpModel();
}
break;
case GetBasalProfileSTD: {
returnData = communicationManager.getBasalProfile();
}
break;
case GetRemainingInsulin: {
returnData = communicationManager.getRemainingInsulin();
}
break;
case GetRealTimeClock: {
returnData = communicationManager.getPumpTime();
medtronicUtil.setPumpTime(null);
}
break;
case SetRealTimeClock: {
returnData = communicationManager.setPumpTime();
}
break;
case GetBatteryStatus: {
returnData = communicationManager.getRemainingBattery();
}
break;
case SetTemporaryBasal: {
TempBasalPair tbr = getTBRSettings();
if (tbr != null) {
returnData = communicationManager.setTBR(tbr);
}
}
break;
case ReadTemporaryBasal: {
returnData = communicationManager.getTemporaryBasal();
}
break;
case Settings:
case Settings_512: {
returnData = communicationManager.getPumpSettings();
}
break;
case SetBolus: {
Double amount = getDoubleFromParameters(0);
if (amount != null)
returnData = communicationManager.setBolus(amount);
}
break;
case CancelTBR: {
returnData = communicationManager.cancelTBR();
}
break;
case SetBasalProfileSTD:
case SetBasalProfileA: {
BasalProfile profile = (BasalProfile) parameters[0];
returnData = communicationManager.setBasalProfile(profile);
}
break;
case GetHistoryData: {
returnData = communicationManager.getPumpHistory((PumpHistoryEntry) parameters[0],
(LocalDateTime) parameters[1]);
}
break;
default: {
aapsLogger.warn(LTag.PUMP, String.format(Locale.ENGLISH, "This commandType is not supported (yet) - %s.", commandType));
// invalid = true;
responseType = MedtronicUIResponseType.Invalid;
}
}
if (responseType == null) {
if (returnData == null) {
errorDescription = communicationManager.getErrorResponse();
this.responseType = MedtronicUIResponseType.Error;
} else {
this.responseType = MedtronicUIResponseType.Data;
}
}
}
private TempBasalPair getTBRSettings() {
return new TempBasalPair(getDoubleFromParameters(0), //
false, //
getIntegerFromParameters(1));
}
private Float getFloatFromParameters(int index) {
return (Float) parameters[index];
}
Double getDoubleFromParameters(int index) {
return (Double) parameters[index];
}
private Integer getIntegerFromParameters(int index) {
return (Integer) parameters[index];
}
public Object getResult() {
return returnData;
}
public boolean isReceived() {
return (returnData != null || errorDescription != null);
}
void postProcess(MedtronicUIPostprocessor postprocessor) {
aapsLogger.debug(LTag.PUMP, "MedtronicUITask: @@@ In execute. " + commandType);
if (responseType == MedtronicUIResponseType.Data) {
postprocessor.postProcessData(this);
}
if (responseType == MedtronicUIResponseType.Invalid) {
rxBus.send(new EventRileyLinkDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating,
"Unsupported command in MedtronicUITask"));
} else if (responseType == MedtronicUIResponseType.Error) {
rxBus.send(new EventRileyLinkDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating,
errorDescription));
} else {
rxBus.send(new EventMedtronicPumpValuesChanged());
medtronicPumpStatus.setLastCommunicationToNow();
}
medtronicUtil.setCurrentCommand(null);
}
public boolean hasData() {
return (responseType == MedtronicUIResponseType.Data);
}
Object getParameter(int index) {
return parameters[index];
}
public MedtronicUIResponseType getResponseType() {
return this.responseType;
}
}

View file

@ -0,0 +1,178 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm.ui
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicUIResponseType
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import org.joda.time.LocalDateTime
import java.util.*
import javax.inject.Inject
/**
* Created by andy on 6/14/18.
*/
class MedtronicUITask {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var medtronicPumpStatus: MedtronicPumpStatus
@Inject lateinit var medtronicUtil: MedtronicUtil
private val injector: HasAndroidInjector
var commandType: MedtronicCommandType
var result: Any? = null
var errorDescription: String? = null
var parameters: List<Any?>? = null
var responseType: MedtronicUIResponseType? = null
constructor(injector: HasAndroidInjector, commandType: MedtronicCommandType) {
this.injector = injector
this.injector.androidInjector().inject(this)
this.commandType = commandType
}
constructor(injector: HasAndroidInjector, commandType: MedtronicCommandType, parameters: List<Any>?) {
this.injector = injector
this.injector.androidInjector().inject(this)
this.commandType = commandType
this.parameters = parameters //as Array<Any>
}
fun execute(communicationManager: MedtronicCommunicationManager) {
aapsLogger.debug(LTag.PUMP, "MedtronicUITask: @@@ In execute. $commandType")
when (commandType) {
MedtronicCommandType.PumpModel -> {
result = communicationManager.pumpModel
}
MedtronicCommandType.GetBasalProfileSTD -> {
result = communicationManager.basalProfile
}
MedtronicCommandType.GetRemainingInsulin -> {
result = communicationManager.remainingInsulin
}
MedtronicCommandType.GetRealTimeClock -> {
result = communicationManager.pumpTime
medtronicUtil.pumpTime = null
}
MedtronicCommandType.SetRealTimeClock -> {
result = communicationManager.setPumpTime()
}
MedtronicCommandType.GetBatteryStatus -> {
result = communicationManager.remainingBattery
}
MedtronicCommandType.SetTemporaryBasal -> {
val tbr = tBRSettings
if (tbr != null) {
result = communicationManager.setTBR(tbr)
}
}
MedtronicCommandType.ReadTemporaryBasal -> {
result = communicationManager.temporaryBasal
}
MedtronicCommandType.Settings, MedtronicCommandType.Settings_512 -> {
result = communicationManager.pumpSettings
}
MedtronicCommandType.SetBolus -> {
val amount = getDoubleFromParameters(0)
if (amount != null) result = communicationManager.setBolus(amount)
}
MedtronicCommandType.CancelTBR -> {
result = communicationManager.cancelTBR()
}
MedtronicCommandType.SetBasalProfileSTD, MedtronicCommandType.SetBasalProfileA -> {
val profile = parameters!![0] as BasalProfile
result = communicationManager.setBasalProfile(profile)
}
MedtronicCommandType.GetHistoryData -> {
result = communicationManager.getPumpHistory(parameters!![0] as PumpHistoryEntry?,
parameters!![1] as LocalDateTime?)
}
else -> {
aapsLogger.warn(LTag.PUMP, String.format(Locale.ENGLISH, "This commandType is not supported (yet) - %s.", commandType))
// invalid = true;
responseType = MedtronicUIResponseType.Invalid
}
}
if (responseType == null) {
if (result == null) {
errorDescription = communicationManager.errorResponse
responseType = MedtronicUIResponseType.Error
} else {
responseType = MedtronicUIResponseType.Data
}
}
}
//
//
private val tBRSettings: TempBasalPair
private get() = TempBasalPair(getDoubleFromParameters(0), //
false, //
getIntegerFromParameters(1))
private fun getFloatFromParameters(index: Int): Float {
return parameters!![index] as Float
}
fun getDoubleFromParameters(index: Int): Double {
return parameters!![index] as Double
}
private fun getIntegerFromParameters(index: Int): Int {
return parameters!![index] as Int
}
val isReceived: Boolean
get() = result != null || errorDescription != null
fun postProcess(postprocessor: MedtronicUIPostprocessor) {
aapsLogger.debug(LTag.PUMP, "MedtronicUITask: @@@ In execute. $commandType")
if (responseType === MedtronicUIResponseType.Data) {
postprocessor.postProcessData(this)
}
if (responseType === MedtronicUIResponseType.Invalid) {
rxBus.send(EventRileyLinkDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating,
"Unsupported command in MedtronicUITask"))
} else if (responseType === MedtronicUIResponseType.Error) {
rxBus.send(EventRileyLinkDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating,
errorDescription))
} else {
rxBus.send(EventMedtronicPumpValuesChanged())
medtronicPumpStatus.setLastCommunicationToNow()
}
medtronicUtil.setCurrentCommand(null)
}
fun hasData(): Boolean {
return responseType === MedtronicUIResponseType.Data
}
fun getParameter(index: Int): Any? {
return parameters!![index]
}
}

View file

@ -580,7 +580,8 @@ public class MedtronicHistoryData {
private void uploadCareportalEvent(long date, DetailedBolusInfo.EventType event) { private void uploadCareportalEvent(long date, DetailedBolusInfo.EventType event) {
pumpSync.insertTherapyEventIfNewWithTimestamp(date, event, null, null, medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber); pumpSync.insertTherapyEventIfNewWithTimestamp(date, event, null, null,
medtronicPumpStatus.getPumpType(), medtronicPumpStatus.getSerialNumber());
} }
private void processTDDs(List<PumpHistoryEntry> tddsIn) { private void processTDDs(List<PumpHistoryEntry> tddsIn) {
@ -972,7 +973,7 @@ public class MedtronicHistoryData {
detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.getAtechDateTime())); detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.getAtechDateTime()));
detailedBolusInfo.setPumpType(PumpType.MEDTRONIC_512_712); // TODO grab real model detailedBolusInfo.setPumpType(PumpType.MEDTRONIC_512_712); // TODO grab real model
detailedBolusInfo.setPumpSerial(medtronicPumpStatus.serialNumber); detailedBolusInfo.setPumpSerial(medtronicPumpStatus.getSerialNumber());
detailedBolusInfo.setBolusPumpId(bolus.getPumpId()); detailedBolusInfo.setBolusPumpId(bolus.getPumpId());
detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount(); detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount();
@ -1046,7 +1047,7 @@ public class MedtronicHistoryData {
if (doubleBolusDebug) if (doubleBolusDebug)
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard)); aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard));
detailedBolusInfo.carbs = bolusWizard.carbs; detailedBolusInfo.carbs = bolusWizard.getCarbs();
} }
} }
@ -1373,7 +1374,7 @@ public class MedtronicHistoryData {
// returns oldest time in history, with calculated time difference between pump and phone, minus 5 minutes // returns oldest time in history, with calculated time difference between pump and phone, minus 5 minutes
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Oldest entry: %d, pumpTimeDifference=%d, newDt=%s, currentTime=%s, differenceMin=%d", dt, aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Oldest entry: %d, pumpTimeDifference=%d, newDt=%s, currentTime=%s, differenceMin=%d", dt,
this.pumpTime.timeDifference, oldestEntryTime, now, minutes.getMinutes())); this.pumpTime.getTimeDifference(), oldestEntryTime, now, minutes.getMinutes()));
return minutes.getMinutes(); return minutes.getMinutes();
} }
@ -1480,7 +1481,7 @@ public class MedtronicHistoryData {
aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. item found, setting new basalProfileLocally: " + newProfile); aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. item found, setting new basalProfileLocally: " + newProfile);
BasalProfile basalProfile = (BasalProfile) newProfile.getDecodedData().get("Object"); BasalProfile basalProfile = (BasalProfile) newProfile.getDecodedData().get("Object");
mdtPumpStatus.basalsByHour = basalProfile.getProfilesByHour(pumpType); mdtPumpStatus.setBasalsByHour( basalProfile.getProfilesByHour(pumpType));
} }
} }

View file

@ -55,18 +55,18 @@ class BasalProfile {
} }
private fun setRawData(data: ByteArray): Boolean { private fun setRawData(data: ByteArray): Boolean {
var data: ByteArray? = data var dataInternal: ByteArray? = data
if (data == null) { if (dataInternal == null) {
aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!")
return false return false
} }
// if we have just one entry through all day it looks like just length 1 // if we have just one entry through all day it looks like just length 1
if (data.size == 1) { if (dataInternal.size == 1) {
data = MedtronicUtil.createByteArray(data[0], 0.toByte(), 0.toByte()) dataInternal = byteArrayOf(dataInternal[0], 0, 0)
} }
if (data!!.size == MAX_RAW_DATA_SIZE) { if (dataInternal.size == MAX_RAW_DATA_SIZE) {
rawData = data rawData = dataInternal
} else { } else {
val len = Math.min(MAX_RAW_DATA_SIZE, data.size) val len = Math.min(MAX_RAW_DATA_SIZE, data.size)
rawData = ByteArray(MAX_RAW_DATA_SIZE) rawData = ByteArray(MAX_RAW_DATA_SIZE)
@ -233,10 +233,10 @@ class BasalProfile {
// return this.mRawData; // return this.mRawData;
} }
fun getProfilesByHour(pumpType: PumpType?): Array<Double?> { fun getProfilesByHour(pumpType: PumpType): Array<Double> {
var entries: List<BasalProfileEntry>? = null var entriesCopy: List<BasalProfileEntry>? = null
try { try {
entries = entries entriesCopy = entries
} catch (ex: Exception) { } catch (ex: Exception) {
aapsLogger.error(LTag.PUMPCOMM, "=============================================================================") aapsLogger.error(LTag.PUMPCOMM, "=============================================================================")
aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: $ex", ex) aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: $ex", ex)
@ -245,40 +245,43 @@ class BasalProfile {
//FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null);
} }
if (entries == null || entries.size == 0) { if (entriesCopy == null || entriesCopy.size == 0) {
val basalByHour = arrayOfNulls<Double>(24) val basalByHour = arrayOfNulls<Double>(24)
for (i in 0..23) { for (i in 0..23) {
basalByHour[i] = 0.0 basalByHour[i] = 0.0
} }
return basalByHour return basalByHour as Array<Double>
} }
val basalByHour = arrayOfNulls<Double>(24) val basalByHour = arrayOfNulls<Double>(24)
for (i in entries.indices) { for (i in entriesCopy.indices) {
val current = entries[i] val current = entriesCopy[i]
var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1 var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1
currentTime = currentTime * 30 / 60 currentTime = currentTime * 30 / 60
var lastHour: Int var lastHour: Int
lastHour = if (i + 1 == entries.size) { lastHour = if (i + 1 == entriesCopy.size) {
24 24
} else { } else {
val basalProfileEntry = entries[i + 1] val basalProfileEntry = entriesCopy[i + 1]
val rawTime = if (basalProfileEntry.startTime_raw % 2 == 0) basalProfileEntry.startTime_raw.toInt() else basalProfileEntry.startTime_raw - 1 val rawTime = if (basalProfileEntry.startTime_raw % 2 == 0) basalProfileEntry.startTime_raw.toInt() else basalProfileEntry.startTime_raw - 1
rawTime * 30 / 60 rawTime * 30 / 60
} }
// System.out.println("Current time: " + currentTime + " Next Time: " + lastHour); // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour);
for (j in currentTime until lastHour) { for (j in currentTime until lastHour) {
if (pumpType == null) basalByHour[j] = current.rate else basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate) if (pumpType == null)
basalByHour[j] = current.rate
else
basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate)
} }
} }
return basalByHour return basalByHour as Array<Double>
} }
override fun toString(): String { override fun toString(): String {
return basalProfileToString() return basalProfileToString()
} }
fun verify(pumpType: PumpType?): Boolean { fun verify(pumpType: PumpType): Boolean {
try { try {
entries entries
} catch (ex: Exception) { } catch (ex: Exception) {

View file

@ -1,60 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import com.google.gson.annotations.Expose;
import androidx.annotation.NonNull;
import java.util.Locale;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType;
/**
* Created by andy on 6/14/18.
*/
public class BatteryStatusDTO {
@Expose
public BatteryStatusType batteryStatusType;
@Expose
public Double voltage;
public boolean extendedDataReceived = false;
public int getCalculatedPercent(BatteryType batteryType) {
if (voltage == null || batteryType == BatteryType.None) {
return (batteryStatusType == BatteryStatusType.Low || batteryStatusType == BatteryStatusType.Unknown) ? 18 : 70;
}
double percent = (voltage - batteryType.lowVoltage) / (batteryType.highVoltage - batteryType.lowVoltage);
int percentInt = (int) (percent * 100.0d);
if (percentInt < 0)
percentInt = 1;
if (percentInt > 100)
percentInt = 100;
return percentInt;
}
@NonNull public String toString() {
return String.format(Locale.ENGLISH, "BatteryStatusDTO [voltage=%.2f, alkaline=%d, lithium=%d, niZn=%d, nimh=%d]",
voltage == null ? 0.0f : voltage,
getCalculatedPercent(BatteryType.Alkaline),
getCalculatedPercent(BatteryType.Lithium),
getCalculatedPercent(BatteryType.NiZn),
getCalculatedPercent(BatteryType.NiMH));
}
public enum BatteryStatusType {
Normal,
Low,
Unknown
}
}

View file

@ -0,0 +1,46 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import com.google.gson.annotations.Expose
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType
import java.util.*
/**
* Created by andy on 6/14/18.
*/
class BatteryStatusDTO {
@Expose
var batteryStatusType: BatteryStatusType? = null
@Expose
var voltage: Double? = null
var extendedDataReceived = false
fun getCalculatedPercent(batteryType: BatteryType): Int {
if (voltage == null || batteryType === BatteryType.None) {
return if (batteryStatusType == BatteryStatusType.Low || batteryStatusType == BatteryStatusType.Unknown) 18 else 70
}
val percent = (voltage!! - batteryType.lowVoltage) / (batteryType.highVoltage - batteryType.lowVoltage)
var percentInt = (percent * 100.0).toInt()
if (percentInt < 0) percentInt = 1
if (percentInt > 100) percentInt = 100
return percentInt
}
override fun toString(): String {
return String.format(Locale.ENGLISH, "BatteryStatusDTO [voltage=%.2f, alkaline=%d, lithium=%d, niZn=%d, nimh=%d]",
if (voltage == null) 0.0f else voltage,
getCalculatedPercent(BatteryType.Alkaline),
getCalculatedPercent(BatteryType.Lithium),
getCalculatedPercent(BatteryType.NiZn),
getCalculatedPercent(BatteryType.NiMH))
}
enum class BatteryStatusType {
Normal,
Low,
Unknown
}
}

View file

@ -1,160 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import com.google.gson.annotations.Expose;
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType;
/**
* Application: GGC - GNU Gluco Control
* Plug-in: Pump Tool (support for Pump devices)
* <p>
* See AUTHORS for copyright information.
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
* version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* <p>
* Filename: BolusDTO Description: Bolus DTO
* <p>
* Author: Andy {andy@atech-software.com}
*/
public class BolusDTO extends PumpTimeStampedRecord {
@Expose
private Double requestedAmount;
@Expose
private Double deliveredAmount;
@Expose
private Double immediateAmount; // when Multiwave this is used
@Expose
private Integer duration;
@Expose
private PumpBolusType bolusType;
private Double insulinOnBoard;
public BolusDTO() {
// this.decimalPrecission = 2;
}
public Double getRequestedAmount() {
return requestedAmount;
}
public void setRequestedAmount(Double requestedAmount) {
this.requestedAmount = requestedAmount;
}
public Double getDeliveredAmount() {
return deliveredAmount;
}
public void setDeliveredAmount(Double deliveredAmount) {
this.deliveredAmount = deliveredAmount;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.duration = duration;
}
public PumpBolusType getBolusType() {
return bolusType;
}
public void setBolusType(PumpBolusType bolusType) {
this.bolusType = bolusType;
}
public Double getInsulinOnBoard() {
return insulinOnBoard;
}
public void setInsulinOnBoard(Double insulinOnBoard) {
this.insulinOnBoard = insulinOnBoard;
}
private String getDurationString() {
int minutes = this.duration;
int h = minutes / 60;
minutes -= (h * 60);
return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2);
}
public String getValue() {
if ((bolusType == PumpBolusType.Normal) || (bolusType == PumpBolusType.Audio)) {
return getFormattedDecimal(this.deliveredAmount);
} else if (bolusType == PumpBolusType.Extended) {
return String.format("AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(this.deliveredAmount),
getDurationString());
} else {
return String.format("AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(this.immediateAmount),
getFormattedDecimal(this.deliveredAmount), getDurationString());
}
}
public String getDisplayableValue() {
String value = getValue();
value = value.replace("AMOUNT_SQUARE=", "Amount Square: ");
value = value.replace("AMOUNT=", "Amount: ");
value = value.replace("DURATION=", "Duration: ");
return value;
}
public Double getImmediateAmount() {
return immediateAmount;
}
public void setImmediateAmount(Double immediateAmount) {
this.immediateAmount = immediateAmount;
}
public String getFormattedDecimal(double value) {
return StringUtil.getFormatedValueUS(value, 2);
}
public String getBolusKey() {
return "Bolus_" + this.bolusType.name();
}
@Override
public String toString() {
return "BolusDTO [type=" + bolusType.name() + ", " + getValue() + "]";
}
}

View file

@ -0,0 +1,90 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import com.google.gson.annotations.Expose
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType
/**
* Application: GGC - GNU Gluco Control
* Plug-in: Pump Tool (support for Pump devices)
*
*
* See AUTHORS for copyright information.
*
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
* version.
*
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Filename: BolusDTO Description: Bolus DTO
*
*
* Author: Andy {andy@atech-software.com}
*/
class BolusDTO : PumpTimeStampedRecord() {
@Expose
var requestedAmount: Double? = null
@Expose
var deliveredAmount: Double? = null
@Expose
var immediateAmount: Double? = null // when Multiwave this is used
@Expose
var duration: Int? = null
@Expose
var bolusType: PumpBolusType? = null
var insulinOnBoard: Double? = null
private val durationString: String
get() {
var minutes = duration!!
val h = minutes / 60
minutes -= h * 60
return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2)
}
val value: String?
get() = if (bolusType === PumpBolusType.Normal || bolusType === PumpBolusType.Audio) {
getFormattedDecimal(deliveredAmount!!)
} else if (bolusType === PumpBolusType.Extended) {
String.format("AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(deliveredAmount!!),
durationString)
} else {
String.format("AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(immediateAmount!!),
getFormattedDecimal(deliveredAmount!!), durationString)
}
val displayableValue: String
get() {
var value = value
value = value!!.replace("AMOUNT_SQUARE=", "Amount Square: ")
value = value.replace("AMOUNT=", "Amount: ")
value = value.replace("DURATION=", "Duration: ")
return value
}
override fun getFormattedDecimal(value: Double): String? {
return StringUtil.getFormatedValueUS(value, 2)
}
val bolusKey: String
get() = "Bolus_" + bolusType!!.name
override fun toString(): String {
return "BolusDTO [type=" + bolusType!!.name + ", " + value + "]"
}
}

View file

@ -1,50 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import java.util.Locale;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
/**
* Created by andy on 18.05.15.
*/
public class BolusWizardDTO extends PumpTimeStampedRecord {
// bloodGlucose and bgTarets are in mg/dL
public Integer bloodGlucose = 0; // mg/dL
public Integer carbs = 0;
public String chUnit = "g";
public Float carbRatio = 0.0f;
public Float insulinSensitivity = 0.0f;
public Integer bgTargetLow = 0;
public Integer bgTargetHigh = 0;
public Float bolusTotal = 0.0f;
public Float correctionEstimate = 0.0f;
public Float foodEstimate = 0.0f;
public Float unabsorbedInsulin = 0.0f;
// public LocalDateTime localDateTime;
// public long atechDateTime;
public String getValue() {
return String.format(Locale.ENGLISH, "BG=%d;CH=%d;CH_UNIT=%s;CH_INS_RATIO=%5.3f;BG_INS_RATIO=%5.3f;"
+ "BG_TARGET_LOW=%d;BG_TARGET_HIGH=%d;BOLUS_TOTAL=%5.3f;"
+ "BOLUS_CORRECTION=%5.3f;BOLUS_FOOD=%5.3f;UNABSORBED_INSULIN=%5.3f", //
bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, //
bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin);
}
public String getDisplayableValue() {
return String.format(Locale.ENGLISH, "Bg=%d, CH=%d %s, Ch/Ins Ratio=%5.3f, Bg/Ins Ratio=%5.3f;"
+ "Bg Target(L/H)=%d/%d, Bolus: Total=%5.3f, "
+ "Correction=%5.3f, Food=%5.3f, IOB=%5.3f", //
bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, //
bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin);
}
public String toString() {
return "BolusWizardDTO [dateTime=" + DateTimeUtil.toString(atechDateTime) + ", " + getValue() + "]";
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import java.util.*
/**
* Created by andy on 18.05.15.
*/
class BolusWizardDTO : PumpTimeStampedRecord() {
// bloodGlucose and bgTarets are in mg/dL
var bloodGlucose = 0 // mg/dL
var carbs = 0
var chUnit = "g"
var carbRatio = 0.0f
var insulinSensitivity = 0.0f
var bgTargetLow = 0
var bgTargetHigh = 0
var bolusTotal = 0.0f
var correctionEstimate = 0.0f
var foodEstimate = 0.0f
var unabsorbedInsulin = 0.0f//
val value: String
get() = String.format(Locale.ENGLISH, "BG=%d;CH=%d;CH_UNIT=%s;CH_INS_RATIO=%5.3f;BG_INS_RATIO=%5.3f;"
+ "BG_TARGET_LOW=%d;BG_TARGET_HIGH=%d;BOLUS_TOTAL=%5.3f;"
+ "BOLUS_CORRECTION=%5.3f;BOLUS_FOOD=%5.3f;UNABSORBED_INSULIN=%5.3f", //
bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, //
bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin)
//
//
val displayableValue: String
get() = String.format(Locale.ENGLISH, "Bg=%d, CH=%d %s, Ch/Ins Ratio=%5.3f, Bg/Ins Ratio=%5.3f;"
+ "Bg Target(L/H)=%d/%d, Bolus: Total=%5.3f, "
+ "Correction=%5.3f, Food=%5.3f, IOB=%5.3f", //
bloodGlucose, carbs, chUnit, carbRatio, insulinSensitivity, bgTargetLow, //
bgTargetHigh, bolusTotal, correctionEstimate, foodEstimate, unabsorbedInsulin)
override fun toString(): String {
return "BolusWizardDTO [dateTime=" + DateTimeUtil.toString(atechDateTime) + ", " + value + "]"
}
}

View file

@ -1,16 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import org.joda.time.LocalDateTime;
/**
* Created by andy on 2/27/19.
*/
public class ClockDTO {
public LocalDateTime localDeviceTime;
public LocalDateTime pumpTime;
public int timeDifference; // s (pump -> local)
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import org.joda.time.LocalDateTime
/**
* Created by andy on 2/27/19.
*/
class ClockDTO {
var localDeviceTime: LocalDateTime? = null
var pumpTime: LocalDateTime? = null
var timeDifference = 0
}

View file

@ -1,255 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import androidx.annotation.NonNull;
import com.google.gson.annotations.Expose;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.Locale;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry;
/**
* Created by andy on 11/3/18.
*/
/**
* NOTE: Decoding is only done for insulin part, everything else is pretty must left undecoded.
*/
public class DailyTotalsDTO {
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs,
// Bolus=1.7, Fodd, Corr, Manual=1.7,
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
private Double bgAvg;
private Double bgLow;
private Double bgHigh;
private Integer bgCount;
private Double sensorAvg;
private Double sensorMin;
private Double sensorMax;
private Integer sensorCalcCount;
private Integer sensorDataCount;
@Expose
private Double insulinTotal = 0.0d;
@Expose
private Double insulinBasal = 0.0d;
@Expose
private Double insulinBolus = 0.0d;
private Double insulinCarbs;
private Double bolusTotal;
private Double bolusFood;
private Double bolusFoodAndCorr;
private Double bolusCorrection;
private Double bolusManual;
private Integer bolusCount;
private Integer bolusCountFoodOrCorr;
// Integer bolusCountCorr;
Integer bolusCountFoodAndCorr;
Integer bolusCountManual;
private Integer bolusCountFood;
private Integer bolusCountCorr;
PumpHistoryEntry entry;
public DailyTotalsDTO(PumpHistoryEntry entry) {
this.entry = entry;
switch (entry.getEntryType()) {
case EndResultTotals:
decodeEndResultsTotals(entry);
break;
case DailyTotals515:
decodeDailyTotals515(entry.getBody());
break;
case DailyTotals522:
decodeDailyTotals522(entry.getBody());
break;
case DailyTotals523:
decodeDailyTotals523(entry.getBody());
break;
default:
break;
}
setDisplayable();
}
private void setDisplayable() {
if (this.insulinBasal == null) {
this.entry.setDisplayableValue("Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2));
} else {
this.entry.setDisplayableValue("Basal Insulin: " + StringUtil.getFormatedValueUS(this.insulinBasal, 2)
+ ", Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2));
}
}
private void decodeEndResultsTotals(PumpHistoryEntry entry) {
double totals = ByteUtil.toInt((int) entry.getHead()[0], (int) entry.getHead()[1], (int) entry.getHead()[2],
(int) entry.getHead()[3], ByteUtil.BitConversion.BIG_ENDIAN) * 0.025d;
this.insulinTotal = totals;
entry.addDecodedData("Totals", totals);
}
private void testDecode(byte[] data) {
// Daily
byte[] body = data; // entry.getBody();
//System.out.println("Totals 522");
for (int i = 0; i < body.length - 2; i++) {
int j = ByteUtil.toInt(body[i], body[i + 1]);
int k = ByteUtil.toInt(body[i], body[i + 1], body[i + 2]);
int j1 = ByteUtil.toInt(body[i + 1], body[i]);
int k1 = ByteUtil.toInt(body[i + 2], body[i + 1], body[i]);
System.out.println(String.format(Locale.ENGLISH,
"index: %d, number=%d, del/40=%.3f, del/10=%.3f, singular=%d, sing_hex=%s", i, j, j / 40.0d, j / 10.0d,
body[i], ByteUtil.shortHexString(body[i])));
System.out.println(String.format(Locale.ENGLISH, " number[k,j1,k1]=%d / %d /%d, del/40=%.3f, del/40=%.3f, del/40=%.3f",
k, j1, k1, k / 40.0d, j1 / 40.0d, k1 / 40.0d));
}
}
private void decodeDailyTotals515(byte[] data) {
// LOG.debug("Can't decode DailyTotals515: Body={}", ByteUtil.getHex(data));
this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d;
this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d;
this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d;
// Delivery Stats: BG AVG: Bg Low/Hi=none,Number BGs=0
// Delivery Stats: INSULIN: Basal 22.30, Bolus=4.20, Catbs = 0g (26.5)
// Delivery Stats: BOLUS: Food=0.00, Corr=0.00, Manual=4.20
// Delivery Stats: NUM BOLUS: Food/Corr=0,Food+Corr=0, Manual=3
//LOG.debug("515: {}", toString());
}
private void decodeDailyTotals522(byte[] data) {
this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d;
this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d;
this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d;
this.bolusTotal = ByteUtil.toInt(data[17], data[18], data[19]) / 40.0d;
this.bolusFood = ByteUtil.toInt(data[21], data[22]) / 40.0d;
this.bolusCorrection = ByteUtil.toInt(data[23], data[24], data[25]) / 40.0d;
this.bolusManual = ByteUtil.toInt(data[26], data[27], data[28]) / 40.0d;
bolusCount = ByteUtil.asUINT8(data[30]);
bolusCountFoodOrCorr = ByteUtil.asUINT8(data[31]);
bolusCountFoodAndCorr = ByteUtil.asUINT8(data[32]);
bolusCountManual = ByteUtil.asUINT8(data[33]);
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs,
// Bolus=1.7[18,19], Fodd, Corr, Manual=1.7[27,28],
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
//LOG.debug("522: {}", toString());
}
private void decodeDailyTotals523(byte[] data) {
this.insulinTotal = ByteUtil.toInt(data[8], data[9]) / 40.0d;
this.insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0d;
this.insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0d;
this.insulinCarbs = ByteUtil.toInt(data[16], data[17]) * 1.0d;
this.bolusFood = ByteUtil.toInt(data[18], data[19]) / 40.0d;
this.bolusCorrection = ByteUtil.toInt(data[20], data[21]) / 40.0d;
this.bolusFoodAndCorr = ByteUtil.toInt(data[22], data[23]) / 40.0d;
this.bolusManual = ByteUtil.toInt(data[24], data[25]) / 40.0d;
this.bolusCountFood = ByteUtil.asUINT8(data[26]);
this.bolusCountCorr = ByteUtil.asUINT8(data[27]);
this.bolusCountFoodAndCorr = ByteUtil.asUINT8(data[28]);
this.bolusCountManual = ByteUtil.asUINT8(data[29]); // +
// Delivery Stats: Carbs=11, Total Insulin=3.850, Basal=2.000
// Delivery Stats: Basal 52,Bolus 1.850, Bolus=48%o
// Delivery Stats: Food only=0.9, Food only#=1, Corr only = 0.0
// Delivery Stats: #Corr_only=0,Food+Corr=0.000, #Food+Corr=0
// Delivery Stats: Manual = 0.95, #Manual=5
//LOG.debug("523: {}", toString());
}
@Override @NonNull
public String toString() {
return new ToStringBuilder(this)
.append("bgAvg", bgAvg)
.append("bgLow", bgLow)
.append("bgHigh", bgHigh)
.append("bgCount", bgCount)
.append("sensorAvg", sensorAvg)
.append("sensorMin", sensorMin)
.append("sensorMax", sensorMax)
.append("sensorCalcCount", sensorCalcCount)
.append("sensorDataCount", sensorDataCount)
.append("insulinTotal", insulinTotal)
.append("insulinBasal", insulinBasal)
.append("insulinBolus", insulinBolus)
.append("insulinCarbs", insulinCarbs)
.append("bolusTotal", bolusTotal)
.append("bolusFood", bolusFood)
.append("bolusFoodAndCorr", bolusFoodAndCorr)
.append("bolusCorrection", bolusCorrection)
.append("bolusManual", bolusManual)
.append("bolusCount", bolusCount)
.append("bolusCountFoodOrCorr", bolusCountFoodOrCorr)
.append("bolusCountFoodAndCorr", bolusCountFoodAndCorr)
.append("bolusCountManual", bolusCountManual)
.append("bolusCountFood", bolusCountFood)
.append("bolusCountCorr", bolusCountCorr)
.append("entry", entry)
.toString();
}
public void setTDD(TDD tdd) {
tdd.date = DateTimeUtil.toMillisFromATD(this.entry.getAtechDateTime());
tdd.basal = insulinBasal;
tdd.bolus = insulinBolus;
tdd.total = insulinTotal;
}
public boolean doesEqual(TDD tdd) {
return tdd.total == this.insulinTotal && tdd.bolus == this.insulinBolus && tdd.basal == this.insulinBasal;
}
}

View file

@ -0,0 +1,202 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import com.google.gson.annotations.Expose
import info.nightscout.androidaps.db.TDD
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType
import org.apache.commons.lang3.builder.ToStringBuilder
import java.util.*
/**
* Created by andy on 11/3/18.
*/
/**
* NOTE: Decoding is only done for insulin part, everything else is pretty must left undecoded.
*/
class DailyTotalsDTO(var entry: PumpHistoryEntry) {
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs,
// Bolus=1.7, Fodd, Corr, Manual=1.7,
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
private val bgAvg: Double? = null
private val bgLow: Double? = null
private val bgHigh: Double? = null
private val bgCount: Int? = null
private val sensorAvg: Double? = null
private val sensorMin: Double? = null
private val sensorMax: Double? = null
private val sensorCalcCount: Int? = null
private val sensorDataCount: Int? = null
@Expose
private var insulinTotal = 0.0
@Expose
private var insulinBasal: Double? = 0.0
@Expose
private var insulinBolus = 0.0
private var insulinCarbs: Double? = null
private var bolusTotal: Double? = null
private var bolusFood: Double? = null
private var bolusFoodAndCorr: Double? = null
private var bolusCorrection: Double? = null
private var bolusManual: Double? = null
private var bolusCount: Int? = null
private var bolusCountFoodOrCorr: Int? = null
// Integer bolusCountCorr;
var bolusCountFoodAndCorr: Int? = null
var bolusCountManual: Int? = null
private var bolusCountFood: Int? = null
private var bolusCountCorr: Int? = null
private fun setDisplayable() {
if (insulinBasal == null) {
entry.displayableValue = "Total Insulin: " + StringUtil.getFormatedValueUS(insulinTotal, 2)
} else {
entry.displayableValue = ("Basal Insulin: " + StringUtil.getFormatedValueUS(insulinBasal, 2)
+ ", Total Insulin: " + StringUtil.getFormatedValueUS(insulinTotal, 2))
}
}
private fun decodeEndResultsTotals(entry: PumpHistoryEntry) {
val totals = ByteUtil.toInt(entry.head!![0].toInt(), entry.head!![1].toInt(), entry.head!![2].toInt(),
entry.head!![3].toInt(), ByteUtil.BitConversion.BIG_ENDIAN) * 0.025
insulinTotal = totals
entry.addDecodedData("Totals", totals)
}
private fun testDecode(data: ByteArray) {
// Daily
//System.out.println("Totals 522");
for (i in 0 until data.size - 2) {
val j = ByteUtil.toInt(data[i], data[i + 1])
val k: Int = ByteUtil.toInt(data[i], data[i + 1], data[i + 2])
val j1 = ByteUtil.toInt(data[i + 1], data[i])
val k1: Int = ByteUtil.toInt(data[i + 2], data[i + 1], data[i])
println(String.format(Locale.ENGLISH,
"index: %d, number=%d, del/40=%.3f, del/10=%.3f, singular=%d, sing_hex=%s", i, j, j / 40.0, j / 10.0,
data[i], ByteUtil.shortHexString(data[i])))
println(String.format(Locale.ENGLISH, " number[k,j1,k1]=%d / %d /%d, del/40=%.3f, del/40=%.3f, del/40=%.3f",
k, j1, k1, k / 40.0, j1 / 40.0, k1 / 40.0))
}
}
private fun decodeDailyTotals515(data: ByteArray?) {
// LOG.debug("Can't decode DailyTotals515: Body={}", ByteUtil.getHex(data));
insulinTotal = ByteUtil.toInt(data!![8], data[9]) / 40.0
insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0
insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0
// Delivery Stats: BG AVG: Bg Low/Hi=none,Number BGs=0
// Delivery Stats: INSULIN: Basal 22.30, Bolus=4.20, Catbs = 0g (26.5)
// Delivery Stats: BOLUS: Food=0.00, Corr=0.00, Manual=4.20
// Delivery Stats: NUM BOLUS: Food/Corr=0,Food+Corr=0, Manual=3
//LOG.debug("515: {}", toString());
}
private fun decodeDailyTotals522(data: ByteArray?) {
insulinTotal = ByteUtil.toInt(data!![8], data[9]) / 40.0
insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0
insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0
bolusTotal = ByteUtil.toInt(data[17], data[18], data[19]) / 40.0
bolusFood = ByteUtil.toInt(data[21], data[22]) / 40.0
bolusCorrection = ByteUtil.toInt(data[23], data[24], data[25]) / 40.0
bolusManual = ByteUtil.toInt(data[26], data[27], data[28]) / 40.0
bolusCount = ByteUtil.asUINT8(data[30])
bolusCountFoodOrCorr = ByteUtil.asUINT8(data[31])
bolusCountFoodAndCorr = ByteUtil.asUINT8(data[32])
bolusCountManual = ByteUtil.asUINT8(data[33])
// bg avg, bg low hi, number Bgs,
// Sen Avg, Sen Lo/Hi, Sens Cal/Data = 0/0,
// Insulin=19.8[8,9], Basal[10,11], Bolus[13,14], Carbs,
// Bolus=1.7[18,19], Fodd, Corr, Manual=1.7[27,28],
// Num bOlus=1, food/corr, Food+corr, manual bolus=1
//LOG.debug("522: {}", toString());
}
private fun decodeDailyTotals523(data: ByteArray?) {
insulinTotal = ByteUtil.toInt(data!![8], data[9]) / 40.0
insulinBasal = ByteUtil.toInt(data[10], data[11]) / 40.0
insulinBolus = ByteUtil.toInt(data[13], data[14]) / 40.0
insulinCarbs = ByteUtil.toInt(data[16], data[17]) * 1.0
bolusFood = ByteUtil.toInt(data[18], data[19]) / 40.0
bolusCorrection = ByteUtil.toInt(data[20], data[21]) / 40.0
bolusFoodAndCorr = ByteUtil.toInt(data[22], data[23]) / 40.0
bolusManual = ByteUtil.toInt(data[24], data[25]) / 40.0
bolusCountFood = ByteUtil.asUINT8(data[26])
bolusCountCorr = ByteUtil.asUINT8(data[27])
bolusCountFoodAndCorr = ByteUtil.asUINT8(data[28])
bolusCountManual = ByteUtil.asUINT8(data[29]) // +
// Delivery Stats: Carbs=11, Total Insulin=3.850, Basal=2.000
// Delivery Stats: Basal 52,Bolus 1.850, Bolus=48%o
// Delivery Stats: Food only=0.9, Food only#=1, Corr only = 0.0
// Delivery Stats: #Corr_only=0,Food+Corr=0.000, #Food+Corr=0
// Delivery Stats: Manual = 0.95, #Manual=5
//LOG.debug("523: {}", toString());
}
override fun toString(): String {
return ToStringBuilder(this)
.append("bgAvg", bgAvg)
.append("bgLow", bgLow)
.append("bgHigh", bgHigh)
.append("bgCount", bgCount)
.append("sensorAvg", sensorAvg)
.append("sensorMin", sensorMin)
.append("sensorMax", sensorMax)
.append("sensorCalcCount", sensorCalcCount)
.append("sensorDataCount", sensorDataCount)
.append("insulinTotal", insulinTotal)
.append("insulinBasal", insulinBasal)
.append("insulinBolus", insulinBolus)
.append("insulinCarbs", insulinCarbs)
.append("bolusTotal", bolusTotal)
.append("bolusFood", bolusFood)
.append("bolusFoodAndCorr", bolusFoodAndCorr)
.append("bolusCorrection", bolusCorrection)
.append("bolusManual", bolusManual)
.append("bolusCount", bolusCount)
.append("bolusCountFoodOrCorr", bolusCountFoodOrCorr)
.append("bolusCountFoodAndCorr", bolusCountFoodAndCorr)
.append("bolusCountManual", bolusCountManual)
.append("bolusCountFood", bolusCountFood)
.append("bolusCountCorr", bolusCountCorr)
.append("entry", entry)
.toString()
}
fun setTDD(tdd: TDD) {
tdd.date = DateTimeUtil.toMillisFromATD(entry.atechDateTime!!)
tdd.basal = insulinBasal!!
tdd.bolus = insulinBolus
tdd.total = insulinTotal
}
fun doesEqual(tdd: TDD): Boolean {
return tdd.total == insulinTotal && tdd.bolus == insulinBolus && tdd.basal == insulinBasal
}
init {
when (entry.entryType) {
PumpHistoryEntryType.EndResultTotals -> decodeEndResultsTotals(entry)
PumpHistoryEntryType.DailyTotals515 -> decodeDailyTotals515(entry.body)
PumpHistoryEntryType.DailyTotals522 -> decodeDailyTotals522(entry.body)
PumpHistoryEntryType.DailyTotals523 -> decodeDailyTotals523(entry.body)
else -> {
}
}
setDisplayable()
}
}

View file

@ -1,29 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup;
/**
* Created by andy on 6/6/18.
*/
public class PumpSettingDTO {
public String key;
public String value;
PumpConfigurationGroup configurationGroup;
public PumpSettingDTO(String key, String value, PumpConfigurationGroup configurationGroup) {
this.key = key;
this.value = value;
this.configurationGroup = configurationGroup;
}
@Override
public String toString() {
return "PumpSettingDTO [key=" + key + ",value=" + value + ",group=" + configurationGroup.name() + "]";
}
}

View file

@ -0,0 +1,14 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup
/**
* Created by andy on 6/6/18.
*/
class PumpSettingDTO(var key: String, var value: String, var configurationGroup: PumpConfigurationGroup) {
override fun toString(): String {
return "PumpSettingDTO [key=" + key + ",value=" + value + ",group=" + configurationGroup.name + "]"
}
}

View file

@ -1,28 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil;
/**
* Created by andy on 6/2/18.
*/
public class PumpTimeStampedRecord {
protected int decimalPrecission = 2;
public long atechDateTime;
public long getAtechDateTime() {
return this.atechDateTime;
}
public void setAtechDateTime(long atechDateTime) {
this.atechDateTime = atechDateTime;
}
public String getFormattedDecimal(double value) {
return StringUtil.getFormatedValueUS(value, this.decimalPrecission);
}
}

View file

@ -0,0 +1,16 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil
/**
* Created by andy on 6/2/18.
*/
open class PumpTimeStampedRecord {
var decimalPrecission = 2
var atechDateTime: Long = 0
open fun getFormattedDecimal(value: Double): String? {
return StringUtil.getFormatedValueUS(value, decimalPrecission)
}
}

View file

@ -1,28 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import org.joda.time.LocalDateTime;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
public class RLHistoryItemMedtronic extends RLHistoryItem {
private final MedtronicCommandType medtronicCommandType;
public RLHistoryItemMedtronic(MedtronicCommandType medtronicCommandType) {
super(new LocalDateTime(), RLHistoryItemSource.MedtronicCommand, RileyLinkTargetDevice.MedtronicPump);
this.medtronicCommandType = medtronicCommandType;
}
@Override
public String getDescription(ResourceHelper resourceHelper) {
if (RLHistoryItemSource.MedtronicCommand.equals(source)) {
return medtronicCommandType.name();
}
return super.getDescription(resourceHelper);
}
}

View file

@ -0,0 +1,18 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.joda.time.LocalDateTime
class RLHistoryItemMedtronic(private val medtronicCommandType: MedtronicCommandType) :
RLHistoryItem(LocalDateTime(), RLHistoryItemSource.MedtronicCommand, RileyLinkTargetDevice.MedtronicPump) {
override fun getDescription(resourceHelper: ResourceHelper): String {
return if (RLHistoryItemSource.MedtronicCommand == source) {
medtronicCommandType.name
} else super.getDescription(resourceHelper)
}
}

View file

@ -1,145 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
/**
* Created by geoff on 5/29/15.
* <p>
* Just need a class to keep the pair together, for parcel transport.
*/
public class TempBasalPair extends info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair {
/**
* This constructor is for use with PumpHistoryDecoder
*
* @param rateByte
* @param startTimeByte
* @param isPercent
*/
public TempBasalPair(byte rateByte, int startTimeByte, boolean isPercent) {
super();
int rateInt = ByteUtil.asUINT8(rateByte);
if (isPercent)
this.setInsulinRate(rateByte);
else
this.setInsulinRate(rateInt * 0.025);
this.setDurationMinutes(startTimeByte * 30);
this.setPercent(isPercent);
}
/**
* This constructor is for use with PumpHistoryDecoder
*
* @param rateByte0
* @param startTimeByte
* @param isPercent
*/
public TempBasalPair(byte rateByte0, byte rateByte1, int startTimeByte, boolean isPercent) {
if (isPercent) {
this.setInsulinRate(rateByte0);
} else {
this.setInsulinRate(ByteUtil.toInt(rateByte1, rateByte0) * 0.025);
}
this.setDurationMinutes(startTimeByte * 30);
this.setPercent(isPercent);
}
public TempBasalPair(AAPSLogger aapsLogger, byte[] response) {
super();
aapsLogger.debug(LTag.PUMPBTCOMM, "Received TempBasal response: " + ByteUtil.getHex(response));
setPercent(response[0] == 1);
if (isPercent()) {
setInsulinRate(response[1]);
} else {
int strokes = MedtronicUtil.makeUnsignedShort(response[2], response[3]);
setInsulinRate(strokes / 40.0d);
}
if (response.length < 6) {
setDurationMinutes(ByteUtil.asUINT8(response[4]));
} else {
setDurationMinutes(MedtronicUtil.makeUnsignedShort(response[4], response[5]));
}
aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "TempBasalPair (with %d byte response): %s", response.length, toString()));
}
public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) {
super(insulinRate, isPercent, durationMinutes);
}
public byte[] getAsRawData() {
List<Byte> list = new ArrayList<>();
list.add((byte) 5);
byte[] insulinRate = MedtronicUtil.getBasalStrokes(this.getInsulinRate(), true);
byte timeMin = (byte) MedtronicUtil.getIntervalFromMinutes(getDurationMinutes());
// list.add((byte) 0); // ?
// list.add((byte) 0); // is_absolute
if (insulinRate.length == 1)
list.add((byte) 0x00);
else
list.add(insulinRate[0]);
list.add(insulinRate[1]);
// list.add((byte) 0); // percent amount
list.add(timeMin); // 3 (time) - OK
if (insulinRate.length == 1)
list.add((byte) 0x00);
else
list.add(insulinRate[0]);
list.add(insulinRate[1]);
return MedtronicUtil.createByteArray(list);
}
public boolean isCancelTBR() {
return (MedtronicUtil.isSame(getInsulinRate(), 0.0d) && getDurationMinutes() == 0);
}
public String getDescription() {
if (isCancelTBR()) {
return "Cancel TBR";
}
if (isPercent()) {
return String.format(Locale.ENGLISH, "Rate: %.0f%%, Duration: %d min", getInsulinRate(), getDurationMinutes());
} else {
return String.format(Locale.ENGLISH, "Rate: %.3f U, Duration: %d min", getInsulinRate(), getDurationMinutes());
}
}
@NonNull @Override
public String toString() {
return "TempBasalPair [" + "Rate=" + getInsulinRate() + ", DurationMinutes=" + getDurationMinutes() + ", IsPercent="
+ isPercent() + "]";
}
}

View file

@ -0,0 +1,110 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.defs.TempBasalPair
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import java.util.*
/**
* Created by geoff on 5/29/15.
*
* Just need a class to keep the pair together, for parcel transport.
*/
class TempBasalPair : TempBasalPair {
/**
* This constructor is for use with PumpHistoryDecoder
*
* @param rateByte
* @param startTimeByte
* @param isPercent
*/
constructor(rateByte: Byte, startTimeByte: Int, isPercent: Boolean) : super() {
val rateInt = ByteUtil.asUINT8(rateByte)
if (isPercent) insulinRate = rateByte.toDouble() else insulinRate = rateInt * 0.025
durationMinutes = startTimeByte * 30
this.isPercent = isPercent
}
/**
* This constructor is for use with PumpHistoryDecoder
*
* @param rateByte0
* @param startTimeByte
* @param isPercent
*/
constructor(rateByte0: Byte, rateByte1: Byte, startTimeByte: Int, isPercent: Boolean) {
if (isPercent) {
insulinRate = rateByte0.toDouble()
} else {
insulinRate = ByteUtil.toInt(rateByte1.toInt(), rateByte0.toInt()) * 0.025
}
durationMinutes = startTimeByte * 30
this.isPercent = isPercent
}
constructor(aapsLogger: AAPSLogger, response: ByteArray) : super() {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received TempBasal response: " + ByteUtil.getHex(response))
isPercent = response[0] == 1.toByte()
insulinRate = if (isPercent) {
response[1].toDouble()
} else {
val strokes = MedtronicUtil.makeUnsignedShort(response[2].toInt(), response[3].toInt())
strokes / 40.0
}
durationMinutes = if (response.size < 6) {
ByteUtil.asUINT8(response[4])
} else {
MedtronicUtil.makeUnsignedShort(response[4].toInt(), response[5].toInt())
}
aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "TempBasalPair (with %d byte response): %s", response.size, toString()))
}
constructor(insulinRate: Double, isPercent: Boolean, durationMinutes: Int) : super(insulinRate, isPercent, durationMinutes) {}
// list.add((byte) 0); // ?
// list.add((byte) 0); // is_absolute
// list.add((byte) 0); // percent amount
// 3 (time) - OK
val asRawData: ByteArray
get() {
val list: MutableList<Byte> = ArrayList()
list.add(5.toByte())
val insulinRate = MedtronicUtil.getBasalStrokes(insulinRate, true)
val timeMin = MedtronicUtil.getIntervalFromMinutes(durationMinutes).toByte()
// list.add((byte) 0); // ?
// list.add((byte) 0); // is_absolute
if (insulinRate.size == 1) list.add(0x00.toByte()) else list.add(insulinRate[0])
list.add(insulinRate[1])
// list.add((byte) 0); // percent amount
list.add(timeMin) // 3 (time) - OK
if (insulinRate.size == 1) list.add(0x00.toByte()) else list.add(insulinRate[0])
list.add(insulinRate[1])
return MedtronicUtil.createByteArray(list)
}
val isCancelTBR: Boolean
get() = MedtronicUtil.isSame(insulinRate, 0.0) && durationMinutes == 0
val description: String
get() {
if (isCancelTBR) {
return "Cancel TBR"
}
return if (isPercent) {
String.format(Locale.ENGLISH, "Rate: %.0f%%, Duration: %d min", insulinRate, durationMinutes)
} else {
String.format(Locale.ENGLISH, "Rate: %.3f U, Duration: %d min", insulinRate, durationMinutes)
}
}
override fun toString(): String {
return ("TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent="
+ isPercent + "]")
}
}

View file

@ -1,31 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry;
public class TempBasalProcessDTO {
public PumpHistoryEntry itemOne;
public PumpHistoryEntry itemTwo;
public Operation processOperation = Operation.None;
public int getDuration() {
if (itemTwo == null) {
TempBasalPair tbr = (TempBasalPair) itemOne.getDecodedDataEntry("Object");
return tbr.getDurationMinutes();
} else {
int difference = DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne.getAtechDateTime(), itemTwo.getAtechDateTime());
return difference;
}
}
public enum Operation {
None,
Add,
Edit
}
}

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry
class TempBasalProcessDTO {
@JvmField var itemOne: PumpHistoryEntry? = null
@JvmField var itemTwo: PumpHistoryEntry? = null
@JvmField var processOperation = Operation.None
val duration: Int
get() = if (itemTwo == null) {
val tbr = itemOne!!.getDecodedDataEntry("Object") as TempBasalPair?
tbr!!.durationMinutes
} else {
DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne!!.atechDateTime, itemTwo!!.atechDateTime)
}
enum class Operation {
None, Add, Edit
}
}

View file

@ -1,14 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
/**
* Created by andy on 1/20/19.
*/
public enum BasalProfileStatus {
NotInitialized, //
ProfileOK, //
ProfileChanged, //
;
}

View file

@ -0,0 +1,12 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
/**
* Created by andy on 1/20/19.
*/
enum class BasalProfileStatus {
NotInitialized, //
ProfileOK, //
ProfileChanged
//
}

View file

@ -1,34 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import androidx.annotation.StringRes;
import java.util.HashMap;
import java.util.Map;
import info.nightscout.androidaps.plugins.pump.medtronic.R;
/**
* Created by andy on 6/4/18.
*/
public enum BatteryType {
None(R.string.key_medtronic_pump_battery_no, 0, 0),
Alkaline(R.string.key_medtronic_pump_battery_alkaline, 1.20d, 1.47d), //
Lithium(R.string.key_medtronic_pump_battery_lithium, 1.22d, 1.64d), //
NiZn(R.string.key_medtronic_pump_battery_nizn, 1.40d, 1.70d), //
NiMH(R.string.key_medtronic_pump_battery_nimh, 1.10d, 1.40d) //
;
public final @StringRes int description;
public final double lowVoltage;
public final double highVoltage;
BatteryType(int resId, double lowVoltage, double highVoltage) {
this.description = resId;
this.lowVoltage = lowVoltage;
this.highVoltage = highVoltage;
}
}

View file

@ -0,0 +1,18 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
import androidx.annotation.StringRes
import info.nightscout.androidaps.plugins.pump.medtronic.R
/**
* Created by andy on 6/4/18.
*/
enum class BatteryType(@field:StringRes val description: Int, val lowVoltage: Double, val highVoltage: Double) {
None(R.string.key_medtronic_pump_battery_no, 0.0, 0.0),
Alkaline(R.string.key_medtronic_pump_battery_alkaline, 1.20, 1.47), //
Lithium(R.string.key_medtronic_pump_battery_lithium, 1.22, 1.64), //
NiZn(R.string.key_medtronic_pump_battery_nizn, 1.40, 1.70), //
NiMH(R.string.key_medtronic_pump_battery_nimh, 1.10, 1.40 //
);
}

View file

@ -1,33 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType;
/**
* Created by andy on 4/5/19.
*/
public enum CommandValueDefinitionMDTType implements CommandValueDefinitionType {
GetModel, //
TuneUp, //
GetProfile, //
GetTBR, //
;
@Override
public String getName() {
return this.name();
}
@Override
public String getDescription() {
return null;
}
@Override
public String commandAction() {
return null;
}
}

View file

@ -1,393 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import info.nightscout.androidaps.plugins.pump.medtronic.R;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.MessageBody;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpAckMessageBody;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.UnknownMessageBody;
/**
* Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net)
* <p>
* Description: Medtronic Commands (Pump and CGMS) for all 512 and later models (just 5xx)
* <p>
* Link to original/unmodified file:
* https://sourceforge.net/p/ggc/code/HEAD/tree/trunk/ggc-plugins/ggc-plugins-base/src/
* main/java/ggc/plugin/device/impl/minimed/enums/MinimedCommandType.java
* <p>
* A lot of stuff has been removed because it is not needed anymore (historical stuff from CareLink
* and Carelink USB communication.
* <p>
* Author: Andy {andy@atech-software.com}
*/
public enum MedtronicCommandType implements Serializable // , MinimedCommandTypeInterface
{
InvalidCommand(0, "Invalid Command", null, null), //
// Pump Responses (9)
CommandACK(0x06, "ACK - Acknowledge", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
CommandNAK(0x15, "NAK - Not Acknowledged", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
// All (8)
PushAck(91, "Push ACK", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(2)), //
PushEsc(91, "Push Esc", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1)), //
PushButton(0x5b, "Push Button", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 91
RFPowerOn(93, "RF Power On", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(
1, 10)), //
RFPowerOff(93, "RF Power Off", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(
0, 0)), //
// SetSuspend(77, "Set Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All,
// MinimedCommandParameterType.FixedParameters, getByteArray(1)), //
// CancelSuspend(77, "Cancel Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All,
// MinimedCommandParameterType.FixedParameters, getByteArray(0)), //
PumpState(131, "Pump State", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
ReadPumpErrorStatus(117, "Pump Error Status", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
// 511 (InitCommand = 2, Config 7, Data = 1(+3)
// DetectBolus(75, "Detect Bolus", MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray(
// 0, 0, 0)), //
// RemoteControlIds(118, "Remote Control Ids", MinimedTargetType.PumpConfiguration_NA, MedtronicDeviceType.All,
// MinimedCommandParameterType.NoParameters), //
// FirmwareVersion(116, "Firmware Version", MinimedTargetType.InitCommand, MedtronicDeviceType.All,
// MinimedCommandParameterType.NoParameters), //
// PumpId(113, "Pump Id", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All,
// MinimedCommandParameterType.NoParameters), // init
SetRealTimeClock(0x40, "Set Pump Time", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, //
0), //
GetRealTimeClock(112, "Get Pump Time", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, //
7, R.string.medtronic_cmd_desc_get_time), // 0x70
GetBatteryStatus(0x72, "Get Battery Status", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
// GetBattery((byte) 0x72), //
GetRemainingInsulin(0x73, "Read Remaining Insulin", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2), // 115
SetBolus(0x42, "Set Bolus", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, //
0, R.string.medtronic_cmd_desc_set_bolus), // 66
// 512
ReadTemporaryBasal(0x98, "Read Temporary Basal", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
5, R.string.medtronic_cmd_desc_get_tbr), // 152
SetTemporaryBasal(76, "Set Temporay Basal", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
0, R.string.medtronic_cmd_desc_set_tbr),
// 512 Config
PumpModel(141, "Pump Model", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
5, R.string.medtronic_cmd_desc_get_model), // 0x8D
// BGTargets_512(140, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512_712,
// MinimedCommandParameterType.NoParameters), //
// BGUnits(137, "BG Units", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher,
// MinimedCommandParameterType.NoParameters), //
// Language(134, "Language", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher,
// MinimedCommandParameterType.NoParameters), //
Settings_512(145, "Configuration", MedtronicDeviceType.Medtronic_512_712, MinimedCommandParameterType.NoParameters, //
64, 1, 18, R.string.medtronic_cmd_desc_get_settings), //
// BGAlarmClocks(142, "BG Alarm Clocks", MinimedTargetType.PumpConfiguration,
// MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), //
// BGAlarmEnable(151, "BG Alarm Enable", MinimedTargetType.PumpConfiguration,
// MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), //
// BGReminderEnable(144, "BG Reminder Enable", MinimedTargetType.PumpConfiguration,
// MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), //
// ReadInsulinSensitivities(0x8b, "Read Insulin Sensitivities", MinimedTargetType.PumpConfiguration,
// MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // 139
// 512 Data
GetHistoryData(128, "Get History", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.SubCommands, //
1024, 16, 1024, R.string.medtronic_cmd_desc_get_history), // 0x80
GetBasalProfileSTD(146, "Get Profile Standard", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), // 146
GetBasalProfileA(147, "Get Profile A", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile),
GetBasalProfileB(148, "Get Profile B", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), // 148
SetBasalProfileSTD(0x6f, "Set Profile Standard", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 111
SetBasalProfileA(0x30, "Set Profile A", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 48
SetBasalProfileB(0x31, "Set Profile B", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 49
// 515
PumpStatus(206, "Pump Status", MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // PumpConfiguration
Settings(192, "Configuration", MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters, //
64, 1, 21, R.string.medtronic_cmd_desc_get_settings), //
// 522
SensorSettings_522(153, "Sensor Configuration", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.NoParameters), //
GlucoseHistory(154, "Glucose History", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0, null), //
// 523
SensorSettings(207, "Sensor Configuration", MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
// 553
// 554
// var MESSAGES = {
// READ_TIME : 0x70,
// READ_BATTERY_STATUS: 0x72,
// READ_HISTORY : 0x80,
// READ_CARB_RATIOS : 0x8A,
// READ_INSULIN_SENSITIVITIES: 0x8B,
// READ_MODEL : 0x8D,
// READ_PROFILE_STD : 0x92,
// READ_PROFILE_A : 0x93,
// READ_PROFILE_B : 0x94,
// READ_CBG_HISTORY: 0x9A,
// READ_ISIG_HISTORY: 0x9B,
// READ_CURRENT_PAGE : 0x9D,
// READ_BG_TARGETS : 0x9F,
// READ_SETTINGS : 0xC0, 192
// READ_CURRENT_CBG_PAGE : 0xCD
// };
// Fake Commands
CancelTBR(),
;
static Map<Byte, MedtronicCommandType> mapByCode;
static {
MedtronicCommandType.RFPowerOn.maxAllowedTime = 17000;
MedtronicCommandType.RFPowerOn.allowedRetries = 0;
MedtronicCommandType.RFPowerOn.recordLength = 0;
MedtronicCommandType.RFPowerOn.minimalBufferSizeToStartReading = 1;
mapByCode = new HashMap<>();
for (MedtronicCommandType medtronicCommandType : values()) {
mapByCode.put(medtronicCommandType.getCommandCode(), medtronicCommandType);
}
}
public byte commandCode = 0;
public String commandDescription = "";
public byte[] commandParameters = null;
public int commandParametersCount = 0;
public int maxRecords = 1;
private Integer resourceId;
public int command_type = 0;
public int allowedRetries = 2;
public int maxAllowedTime = 2000;
public MinimedCommandParameterType parameterType;
public int minimalBufferSizeToStartReading = 14;
public int expectedLength = 0;
//MinimedTargetType targetType;
MedtronicDeviceType devices;
private int recordLength = 64;
MedtronicCommandType() {
// this is for "fake" commands needed by AAPS MedtronicUITask
}
MedtronicCommandType(int code, String description, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, byte[] cmd_params) {
this(code, description, devices, parameterType, 0, 1, 0, 0, 11, 0);
this.commandParameters = cmd_params;
this.commandParametersCount = cmd_params.length;
}
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType) {
this(code, description, devices, parameterType, 64, 1, 0, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int expectedLength) {
this(code, description, devices, parameterType, 64, 1, expectedLength, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int expectedLength, int resourceId) {
this(code, description, devices, parameterType, 64, 1, expectedLength, resourceId);
}
// NEW
MedtronicCommandType(int code, String description,
MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int expectedLength,
Integer resourceId) {
this.commandCode = (byte) code;
this.commandDescription = description;
this.devices = devices;
this.recordLength = recordLength;
this.maxRecords = max_recs;
this.resourceId = resourceId;
this.commandParametersCount = 0;
this.allowedRetries = 2;
this.parameterType = parameterType;
this.expectedLength = expectedLength;
if (this.parameterType == MinimedCommandParameterType.SubCommands) {
this.minimalBufferSizeToStartReading = 200;
}
}
@Deprecated
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int addy, //
int addy_len, int cmd_type, int expectedLength) {
this.commandCode = (byte) code;
this.commandDescription = description;
//this.targetType = targetType;
this.devices = devices;
this.recordLength = recordLength;
this.maxRecords = max_recs;
this.command_type = cmd_type;
this.commandParametersCount = 0;
this.allowedRetries = 2;
this.parameterType = parameterType;
this.expectedLength = expectedLength;
if (this.parameterType == MinimedCommandParameterType.SubCommands) {
this.minimalBufferSizeToStartReading = 200;
}
}
private static HashMap<MedtronicDeviceType, String> getDeviceTypesArray(MedtronicDeviceType... types) {
HashMap<MedtronicDeviceType, String> hashMap = new HashMap<MedtronicDeviceType, String>();
for (MedtronicDeviceType type : types) {
hashMap.put(type, null);
}
return hashMap;
}
private static byte[] getByteArray(int... data) {
byte[] array = new byte[data.length];
for (int i = 0; i < data.length; i++) {
array[i] = (byte) data[i];
}
return array;
}
private static int[] getIntArray(int... data) {
return data;
}
public static MedtronicCommandType getByCode(byte code) {
if (mapByCode.containsKey(code)) {
return mapByCode.get(code);
} else {
return MedtronicCommandType.InvalidCommand;
}
}
public static MessageBody constructMessageBody(MedtronicCommandType messageType, byte[] bodyData) {
switch (messageType) {
case CommandACK:
return new PumpAckMessageBody(bodyData);
default:
return new UnknownMessageBody(bodyData);
}
}
public static MedtronicCommandType getSettings(MedtronicDeviceType medtronicPumpModel) {
if (MedtronicDeviceType.isSameDevice(medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712))
return MedtronicCommandType.Settings_512;
else
return MedtronicCommandType.Settings;
}
/**
* Get Full Command Description
*
* @return command description
*/
public String getFullCommandDescription() {
return "Command [name=" + this.name() + ", id=" + this.commandCode + ",description=" + this.commandDescription
+ "] ";
}
public byte getCommandCode() {
return commandCode;
}
public int getCommandParametersCount() {
if (this.commandParameters == null) {
return 0;
} else {
return this.commandParameters.length;
}
}
public String toString() {
return name();
}
public String getCommandDescription() {
return this.commandDescription;
}
public Integer getResourceId() {
return resourceId;
}
public enum MinimedCommandParameterType {
NoParameters, //
FixedParameters, //
SubCommands //
}
}

View file

@ -0,0 +1,285 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
import info.nightscout.androidaps.plugins.pump.medtronic.R
import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.MessageBody
import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpAckMessageBody
import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.UnknownMessageBody
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType.Companion.isSameDevice
import java.io.Serializable
import java.util.*
/**
* Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net)
*
*
* Description: Medtronic Commands (Pump and CGMS) for all 512 and later models (just 5xx)
*
*
* Link to original/unmodified file:
* https://sourceforge.net/p/ggc/code/HEAD/tree/trunk/ggc-plugins/ggc-plugins-base/src/
* main/java/ggc/plugin/device/impl/minimed/enums/MinimedCommandType.java
*
*
* A lot of stuff has been removed because it is not needed anymore (historical stuff from CareLink
* and Carelink USB communication.
*
*
* Author: Andy {andy@atech-software.com}
*/
enum class MedtronicCommandType
{
InvalidCommand(0, "Invalid Command", null, null), //
// Pump Responses (9)
CommandACK(0x06, "ACK - Acknowledge", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
CommandNAK(0x15, "NAK - Not Acknowledged", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
// All (8)
PushAck(91, "Push ACK", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, byteArrayOf(2)), //
PushEsc(91, "Push Esc", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, byteArrayOf(1)), //
PushButton(0x5b, "Push Button", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 91
RFPowerOn(93, "RF Power On", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, byteArrayOf(1, 10)), //
RFPowerOff(93, "RF Power Off", MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, byteArrayOf(0, 0)), //
// SetSuspend(77, "Set Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1)), //
// CancelSuspend(77, "Cancel Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All,MinimedCommandParameterType.FixedParameters, getByteArray(0)), //
PumpState(131, "Pump State", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
ReadPumpErrorStatus(117, "Pump Error Status", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
// 511 (InitCommand = 2, Config 7, Data = 1(+3)
// DetectBolus(75, "Detect Bolus", MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray(
// 0, 0, 0)), //
// RemoteControlIds(118, "Remote Control Ids", MinimedTargetType.PumpConfiguration_NA, MedtronicDeviceType.All,MinimedCommandParameterType.NoParameters), //
// FirmwareVersion(116, "Firmware Version", MinimedTargetType.InitCommand, MedtronicDeviceType.All,MinimedCommandParameterType.NoParameters), //
// PumpId(113, "Pump Id", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All,MinimedCommandParameterType.NoParameters), // init
SetRealTimeClock(0x40, "Set Pump Time", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, //
0, R.string.medtronic_cmd_desc_set_time), //
GetRealTimeClock(112, "Get Pump Time", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, //
7, R.string.medtronic_cmd_desc_get_time), // 0x70
GetBatteryStatus(0x72, "Get Battery Status", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters,
0, R.string.medtronic_cmd_desc_get_battery_status), //
GetRemainingInsulin(0x73, "Read Remaining Insulin", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2), // 115
SetBolus(0x42, "Set Bolus", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, //
0, R.string.medtronic_cmd_desc_set_bolus), // 66
// 512
ReadTemporaryBasal(0x98, "Read Temporary Basal", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
5, R.string.medtronic_cmd_desc_get_tbr), // 152
SetTemporaryBasal(76, "Set Temporay Basal", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
0, R.string.medtronic_cmd_desc_set_tbr), // 512 Config
PumpModel(141, "Pump Model", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
5, R.string.medtronic_cmd_desc_get_model), // 0x8D
// BGTargets_512(140, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512_712,
// MinimedCommandParameterType.NoParameters), //
// BGUnits(137, "BG Units", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher,
// MinimedCommandParameterType.NoParameters), //
// Language(134, "Language", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher,
// MinimedCommandParameterType.NoParameters), //
Settings_512(145, "Configuration", MedtronicDeviceType.Medtronic_512_712, MinimedCommandParameterType.NoParameters, //
64, 1, 18, R.string.medtronic_cmd_desc_get_settings), //
// 512 Data
GetHistoryData(128, "Get History", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.SubCommands, //
1024, 16, 1024, R.string.medtronic_cmd_desc_get_history), // 0x80
GetBasalProfileSTD(146, "Get Profile Standard", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), // 146
GetBasalProfileA(147, "Get Profile A", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile),
GetBasalProfileB(148, "Get Profile B", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_get_basal_profile), // 148
SetBasalProfileSTD(0x6f, "Set Profile Standard", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 111
SetBasalProfileA(0x30, "Set Profile A", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 48
SetBasalProfileB(0x31, "Set Profile B", MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, //
64, 3, 192, R.string.medtronic_cmd_desc_set_basal_profile), // 49
// 515
PumpStatus(206, "Pump Status", MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // PumpConfiguration
Settings(192, "Configuration", MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters, //
64, 1, 21, R.string.medtronic_cmd_desc_get_settings), //
// 522
SensorSettings_522(153, "Sensor Configuration", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.NoParameters), //
GlucoseHistory(154, "Glucose History", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0, null), //
// 523
SensorSettings(207, "Sensor Configuration", MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
// 553
// 554
// var MESSAGES = {
// READ_TIME : 0x70,
// READ_BATTERY_STATUS: 0x72,
// READ_HISTORY : 0x80,
// READ_CARB_RATIOS : 0x8A,
// READ_INSULIN_SENSITIVITIES: 0x8B,
// READ_MODEL : 0x8D,
// READ_PROFILE_STD : 0x92,
// READ_PROFILE_A : 0x93,
// READ_PROFILE_B : 0x94,
// READ_CBG_HISTORY: 0x9A,
// READ_ISIG_HISTORY: 0x9B,
// READ_CURRENT_PAGE : 0x9D,
// READ_BG_TARGETS : 0x9F,
// READ_SETTINGS : 0xC0, 192
// READ_CURRENT_CBG_PAGE : 0xCD
// };
// Fake Commands
CancelTBR;
companion object {
var mapByCode: MutableMap<Byte, MedtronicCommandType> = HashMap()
private fun getDeviceTypesArray(vararg types: MedtronicDeviceType): HashMap<MedtronicDeviceType, String?> {
val hashMap = HashMap<MedtronicDeviceType, String?>()
for (type in types) {
hashMap[type] = null
}
return hashMap
}
// @JvmStatic
// fun getByteArray(vararg data: Int): ByteArray {
// val array = ByteArray(data.size)
// for (i in 0 until data.size) {
// array[i] = data[i].toByte()
// }
// return array
// }
// private fun getByteArray(vararg data: Int): ByteArray {
// val array = ByteArray(data.size)
// for (i in 0 until data.size) {
// array[i] = data[i].toByte()
// }
// return array
// }
private fun getIntArray(vararg data: Int): IntArray {
return data
}
fun getByCode(code: Byte): MedtronicCommandType? {
return if (mapByCode.containsKey(code)) {
mapByCode[code]
} else {
InvalidCommand
}
}
fun constructMessageBody(messageType: MedtronicCommandType?, bodyData: ByteArray?): MessageBody {
return when (messageType) {
CommandACK -> PumpAckMessageBody(bodyData)
else -> UnknownMessageBody(bodyData!!)
}
}
@JvmStatic
fun getSettings(medtronicPumpModel: MedtronicDeviceType?): MedtronicCommandType {
return if (isSameDevice(medtronicPumpModel!!, MedtronicDeviceType.Medtronic_512_712)) Settings_512 else Settings
}
init {
RFPowerOn.maxAllowedTime = 17000
RFPowerOn.allowedRetries = 0
RFPowerOn.recordLength = 0
RFPowerOn.minimalBufferSizeToStartReading = 1
for (medtronicCommandType in values()) {
mapByCode[medtronicCommandType.commandCode] = medtronicCommandType
}
}
}
var commandCode: Byte = 0
var commandDescription = ""
var commandParameters: ByteArray? = null
var commandParametersCount = 0
var maxRecords = 1
var resourceId: Int? = null
private set
var command_type = 0
var allowedRetries = 2
var maxAllowedTime = 2000
var parameterType: MinimedCommandParameterType? = null
var minimalBufferSizeToStartReading = 14
var expectedLength = 0
var devices: MedtronicDeviceType? = null
private var recordLength = 64
constructor() {
// this is for "fake" commands needed by AAPS MedtronicUITask
}
constructor(code: Int, description: String, devices: MedtronicDeviceType?,
parameterType: MinimedCommandParameterType?, cmd_params: ByteArray) : this(code, description, devices, parameterType, 0, 1, 0, 0, 11, 0) {
commandParameters = cmd_params
commandParametersCount = cmd_params.size
}
// NEW
constructor(code: Int, description: String, devices: MedtronicDeviceType?, //
parameterType: MinimedCommandParameterType?, expectedLength: Int) : this(code, description, devices, parameterType, 64, 1, expectedLength, null) {
}
// NEW
constructor(code: Int, description: String, devices: MedtronicDeviceType?, //
parameterType: MinimedCommandParameterType?, expectedLength: Int, resourceId: Int) : this(code, description, devices, parameterType, 64, 1, expectedLength, resourceId) {
}
// NEW
constructor(code: Int, description: String,
devices: MedtronicDeviceType?, //
parameterType: MinimedCommandParameterType?, recordLength: Int = 64, max_recs: Int = 1, expectedLength: Int = 0,
resourceId: Int? = null) {
commandCode = code.toByte()
commandDescription = description
this.devices = devices
this.recordLength = recordLength
maxRecords = max_recs
this.resourceId = resourceId
commandParametersCount = 0
allowedRetries = 2
this.parameterType = parameterType
this.expectedLength = expectedLength
if (this.parameterType == MinimedCommandParameterType.SubCommands) {
minimalBufferSizeToStartReading = 200
}
}
@Deprecated("")
constructor(code: Int, description: String, devices: MedtronicDeviceType?, //
parameterType: MinimedCommandParameterType?, recordLength: Int, max_recs: Int, addy: Int, //
addy_len: Int, cmd_type: Int, expectedLength: Int) {
commandCode = code.toByte()
commandDescription = description
//this.targetType = targetType;
this.devices = devices
this.recordLength = recordLength
maxRecords = max_recs
command_type = cmd_type
commandParametersCount = 0
allowedRetries = 2
this.parameterType = parameterType
this.expectedLength = expectedLength
if (this.parameterType == MinimedCommandParameterType.SubCommands) {
minimalBufferSizeToStartReading = 200
}
}
override fun toString(): String {
return name
}
enum class MinimedCommandParameterType {
NoParameters, //
FixedParameters, //
SubCommands //
}
}

View file

@ -1,20 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
/**
* Created by andy on 11/3/18.
*/
public enum MedtronicCustomActionType implements CustomActionType {
WakeUpAndTune(), //
ClearBolusBlock(), //
ResetRileyLinkConfiguration(), //
;
@Override
public String getKey() {
return this.name();
}
}

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType
/**
* Created by andy on 11/3/18.
*/
enum class MedtronicCustomActionType : CustomActionType {
WakeUpAndTune, //
ClearBolusBlock, //
ResetRileyLinkConfiguration;
//
override fun getKey(): String {
return name
}
}

View file

@ -1,140 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import java.util.HashMap;
import java.util.Map;
/**
* Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net)
* <p>
* Author: Andy {andy@atech-software.com}
*/
public enum MedtronicDeviceType {
Unknown_Device, //
// Pump
Medtronic_511("511"), //
Medtronic_512("512"), //
Medtronic_712("712"), //
Medtronic_512_712(Medtronic_512, Medtronic_712), //
Medtronic_515("515"), //
Medtronic_715("715"), //
Medtronic_515_715(Medtronic_515, Medtronic_715), //
Medtronic_522("522"), //
Medtronic_722("722"), //
Medtronic_522_722(Medtronic_522, Medtronic_722), //
Medtronic_523_Revel("523"), //
Medtronic_723_Revel("723"), //
Medtronic_554_Veo("554"), //
Medtronic_754_Veo("754"), //
Medtronic_512andHigher(Medtronic_512, Medtronic_712, Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, //
Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_515andHigher(Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, //
Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_522andHigher(Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, //
Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_523andHigher(Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, //
Medtronic_754_Veo), //
Medtronic_554andHigher(Medtronic_554_Veo, Medtronic_754_Veo), //
//
All;
static Map<String, MedtronicDeviceType> mapByDescription;
static {
mapByDescription = new HashMap<>();
for (MedtronicDeviceType minimedDeviceType : values()) {
if (!minimedDeviceType.isFamily) {
mapByDescription.put(minimedDeviceType.pumpModel, minimedDeviceType);
}
}
}
private String pumpModel;
private final boolean isFamily;
private MedtronicDeviceType[] familyMembers = null;
MedtronicDeviceType(String pumpModel) {
this.isFamily = false;
this.pumpModel = pumpModel;
}
MedtronicDeviceType(MedtronicDeviceType... familyMembers) {
this.familyMembers = familyMembers;
this.isFamily = true;
}
public static boolean isSameDevice(MedtronicDeviceType deviceWeCheck, MedtronicDeviceType deviceSources) {
if (deviceSources.isFamily) {
for (MedtronicDeviceType mdt : deviceSources.familyMembers) {
if (mdt == deviceWeCheck)
return true;
}
} else {
return (deviceWeCheck == deviceSources);
}
return false;
}
public static MedtronicDeviceType getByDescription(String desc) {
if (mapByDescription.containsKey(desc)) {
return mapByDescription.get(desc);
} else {
return MedtronicDeviceType.Unknown_Device;
}
}
// public static boolean isLargerFormat(MedtronicDeviceType model) {
// return isSameDevice(model, Medtronic_523andHigher);
// }
public boolean isFamily() {
return isFamily;
}
public MedtronicDeviceType[] getFamilyMembers() {
return familyMembers;
}
// public boolean isLargerFormat() {
// return isSameDevice(this, Medtronic_523andHigher);
// }
public boolean isMedtronic_523orHigher() {
return isSameDevice(this, Medtronic_523andHigher);
}
public int getBolusStrokes() {
return (isMedtronic_523orHigher()) ? 40 : 10;
}
public String getPumpModel() {
return pumpModel;
}
}

View file

@ -0,0 +1,100 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
import java.util.*
/**
* Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net)
*
*
* Author: Andy {andy@atech-software.com}
*/
enum class MedtronicDeviceType {
Unknown_Device, //
// Pump
Medtronic_511("511"), //
Medtronic_512("512"), //
Medtronic_712("712"), //
Medtronic_512_712(Medtronic_512, Medtronic_712), //
Medtronic_515("515"), //
Medtronic_715("715"), //
Medtronic_515_715(Medtronic_515, Medtronic_715), //
Medtronic_522("522"), //
Medtronic_722("722"), //
Medtronic_522_722(Medtronic_522, Medtronic_722), //
Medtronic_523_Revel("523"), //
Medtronic_723_Revel("723"), //
Medtronic_554_Veo("554"), //
Medtronic_754_Veo("754"), //
Medtronic_512andHigher(Medtronic_512, Medtronic_712, Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_515andHigher(Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_522andHigher(Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_523andHigher(Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo), //
Medtronic_554andHigher(Medtronic_554_Veo, Medtronic_754_Veo), //
//
All;
companion object {
var mapByDescription: MutableMap<String, MedtronicDeviceType>? = null
@JvmStatic
fun isSameDevice(deviceWeCheck: MedtronicDeviceType, deviceSources: MedtronicDeviceType): Boolean {
if (deviceSources.isFamily) {
for (mdt in deviceSources.familyMembers!!) {
if (mdt == deviceWeCheck) return true
}
} else {
return deviceWeCheck == deviceSources
}
return false
}
fun getByDescription(desc: String): MedtronicDeviceType {
return if (mapByDescription==null) {
Unknown_Device
} else if (mapByDescription!!.containsKey(desc)) {
mapByDescription!![desc]!!
} else {
Unknown_Device
}
}
init {
mapByDescription = HashMap()
for (minimedDeviceType in values()) {
if (!minimedDeviceType.isFamily) {
mapByDescription!![minimedDeviceType.pumpModel!!] = minimedDeviceType
}
}
}
}
var pumpModel: String? = null
private set
// public static boolean isLargerFormat(MedtronicDeviceType model) {
// return isSameDevice(model, Medtronic_523andHigher);
// }
val isFamily: Boolean
var familyMembers: Array<MedtronicDeviceType>? = null
private set
constructor(pumpModel: String?) {
isFamily = false
this.pumpModel = pumpModel
}
constructor(vararg familyMembers: MedtronicDeviceType) {
this.familyMembers = familyMembers as Array<MedtronicDeviceType>?
isFamily = true
}
val isMedtronic_523orHigher: Boolean
get() = isSameDevice(this, Medtronic_523andHigher)
val bolusStrokes: Int
get() = if (isMedtronic_523orHigher) 40 else 10
}

View file

@ -1,65 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
import info.nightscout.androidaps.plugins.pump.medtronic.R;
/**
* Created by andy on 10/15/18.
*/
public enum MedtronicNotificationType {
PumpUnreachable(Notification.RILEYLINK_CONNECTION, R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL), //
PumpTypeNotSame(R.string.medtronic_error_pump_type_set_differs_from_detected, Notification.NORMAL), //
PumpBasalProfilesNotEnabled(R.string.medtronic_error_pump_basal_profiles_not_enabled, Notification.URGENT), //
PumpIncorrectBasalProfileSelected(R.string.medtronic_error_pump_incorrect_basal_profile_selected, Notification.URGENT), //
PumpWrongTBRTypeSet(R.string.medtronic_error_pump_wrong_tbr_type_set, Notification.URGENT), //
PumpWrongMaxBolusSet(R.string.medtronic_error_pump_wrong_max_bolus_set, Notification.NORMAL), //
PumpWrongMaxBasalSet(R.string.medtronic_error_pump_wrong_max_basal_set, Notification.NORMAL), //
PumpWrongTimeUrgent(R.string.medtronic_notification_check_time_date, Notification.URGENT),
PumpWrongTimeNormal(R.string.medtronic_notification_check_time_date, Notification.NORMAL),
TimeChangeOver24h(Notification.OVER_24H_TIME_CHANGE_REQUESTED, R.string.medtronic_error_pump_24h_time_change_requested, Notification.URGENT),
//
;
private int notificationType;
private final int resourceId;
private final int notificationUrgency;
MedtronicNotificationType(int resourceId, int notificationUrgency) {
this(Notification.MEDTRONIC_PUMP_ALARM, resourceId, notificationUrgency);
}
MedtronicNotificationType(int notificationType, int resourceId, int notificationUrgency) {
this.notificationType = notificationType;
this.resourceId = resourceId;
this.notificationUrgency = notificationUrgency;
}
public int getNotificationType() {
return notificationType;
}
public void setNotificationType(int notificationType) {
this.notificationType = notificationType;
}
public int getResourceId() {
return resourceId;
}
public int getNotificationUrgency() {
return notificationUrgency;
}
// Notification.MEDTRONIC_PUMP_ALARM R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL
}

View file

@ -0,0 +1,23 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.pump.medtronic.R
/**
* Created by andy on 10/15/18.
*/
enum class MedtronicNotificationType(var notificationType: Int,
val resourceId: Int,
val notificationUrgency: Int) {
PumpUnreachable(Notification.RILEYLINK_CONNECTION, R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL), //
PumpTypeNotSame(R.string.medtronic_error_pump_type_set_differs_from_detected, Notification.NORMAL), //
PumpBasalProfilesNotEnabled(R.string.medtronic_error_pump_basal_profiles_not_enabled, Notification.URGENT), //
PumpIncorrectBasalProfileSelected(R.string.medtronic_error_pump_incorrect_basal_profile_selected, Notification.URGENT), //
PumpWrongTBRTypeSet(R.string.medtronic_error_pump_wrong_tbr_type_set, Notification.URGENT), //
PumpWrongMaxBolusSet(R.string.medtronic_error_pump_wrong_max_bolus_set, Notification.NORMAL), //
PumpWrongMaxBasalSet(R.string.medtronic_error_pump_wrong_max_basal_set, Notification.NORMAL), //
PumpWrongTimeUrgent(R.string.medtronic_notification_check_time_date, Notification.URGENT), PumpWrongTimeNormal(R.string.medtronic_notification_check_time_date, Notification.NORMAL), TimeChangeOver24h(Notification.OVER_24H_TIME_CHANGE_REQUESTED, R.string.medtronic_error_pump_24h_time_change_requested, Notification.URGENT);
constructor(resourceId: Int, notificationUrgency: Int) : this(Notification.MEDTRONIC_PUMP_ALARM, resourceId, notificationUrgency) {}
}

View file

@ -1,37 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
/**
* Created by andy on 6/28/18.
*/
public enum MedtronicStatusRefreshType {
PumpHistory(5, null), //
Configuration(0, null), //
RemainingInsulin(-1, MedtronicCommandType.GetRemainingInsulin), //
BatteryStatus(55, MedtronicCommandType.GetBatteryStatus), //
PumpTime(60, MedtronicCommandType.GetRealTimeClock) //
;
private final int refreshTime;
private final MedtronicCommandType commandType;
MedtronicStatusRefreshType(int refreshTime, MedtronicCommandType commandType) {
this.refreshTime = refreshTime;
this.commandType = commandType;
}
public int getRefreshTime() {
return refreshTime;
}
public MedtronicCommandType getCommandType(MedtronicDeviceType medtronicDeviceType) {
if (this == Configuration) {
return MedtronicCommandType.getSettings(medtronicDeviceType);
} else
return commandType;
}
}

View file

@ -0,0 +1,23 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
/**
* Created by andy on 6/28/18.
*/
enum class MedtronicStatusRefreshType(val refreshTime: Int,
private val commandType: MedtronicCommandType?) {
PumpHistory(5, null), //
Configuration(0, null), //
RemainingInsulin(-1, MedtronicCommandType.GetRemainingInsulin), //
BatteryStatus(55, MedtronicCommandType.GetBatteryStatus), //
PumpTime(60, MedtronicCommandType.GetRealTimeClock //
);
fun getCommandType(medtronicDeviceType: MedtronicDeviceType?): MedtronicCommandType? {
return if (this == Configuration) {
MedtronicCommandType.getSettings(medtronicDeviceType)
} else
commandType
}
}

View file

@ -1,13 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
/**
* Created by andy on 10/18/18.
*/
public enum MedtronicUIResponseType {
Data,
Error,
Invalid
}

View file

@ -0,0 +1,9 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
/**
* Created by andy on 10/18/18.
*/
enum class MedtronicUIResponseType {
Data, Error, Invalid
}

View file

@ -1,129 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
import java.util.HashMap;
/**
* Application: GGC - GNU Gluco Control
* Plug-in: Pump Tool (support for Pump devices)
* <p>
* See AUTHORS for copyright information.
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
* version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* <p>
* Filename: PumpBolusType Description: Pump Bolus Types
* <p>
* Author: Andy {andy@atech-software.com}
*/
public enum PumpBolusType // implements CodeEnumWithTranslation
{
None(0, "NONE"), //
Normal(1, "BOLUS_STANDARD"), //
Audio(2, "BOLUS_AUDIO"), //
Extended(3, "BOLUS_SQUARE", "AMOUNT_SQUARE=%s;DURATION=%s"), //
Multiwave(4, "BOLUS_MULTIWAVE", "AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s");
static String[] descriptions;
// static HashMap<String, CodeEnumWithTranslation> translationMapping = new HashMap<String,
// CodeEnumWithTranslation>();
static HashMap<Integer, PumpBolusType> codeMapping = new HashMap<Integer, PumpBolusType>();
private static boolean translated;
static {
for (PumpBolusType pbt : values()) {
codeMapping.put(pbt.code, pbt);
}
}
// public static void translateKeywords(I18nControlAbstract ic)
// {
// if (translated)
// return;
//
// for (PumpBolusType pbt : values())
// {
// pbt.setTranslation(ic.getMessage(pbt.i18nKey));
// translationMapping.put(pbt.getTranslation(), pbt);
// }
//
// String[] bolusDescriptions = { ic.getMessage("SELECT_BOLUS_TYPE"), //
// ic.getMessage("BOLUS_STANDARD"), //
// ic.getMessage("BOLUS_AUDIO"), //
// ic.getMessage("BOLUS_SQUARE"), //
// ic.getMessage("BOLUS_MULTIWAVE"), };
//
// descriptions = bolusDescriptions;
//
// translated = true;
// }
int code;
String i18nKey;
String translation;
String valueTemplate;
PumpBolusType(int code, String i18nKey) {
this.code = code;
this.i18nKey = i18nKey;
}
PumpBolusType(int code, String i18nKey, String valueTemplate) {
this.code = code;
this.i18nKey = i18nKey;
this.valueTemplate = valueTemplate;
}
public static PumpBolusType getByCode(int code) {
if (codeMapping.containsKey(code)) {
return codeMapping.get(code);
} else {
return PumpBolusType.None;
}
}
/**
* Get Descriptions (array)
*
* @return array of strings with description
*/
public static String[] getDescriptions() {
return descriptions;
}
public String getTranslation() {
return translation;
}
public void setTranslation(String translation) {
this.translation = translation;
}
public int getCode() {
return code;
}
public String getI18nKey() {
return i18nKey;
}
public String getName() {
return this.name();
}
}

View file

@ -0,0 +1,54 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
import java.util.*
/**
* This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes
* management and modified/extended for AAPS.
*
*
* Author: Andy {andy.rozman@gmail.com}
*/
enum class PumpBolusType {
None(0, "NONE"), //
Normal(1, "BOLUS_STANDARD"), //
Audio(2, "BOLUS_AUDIO"), //
Extended(3, "BOLUS_SQUARE", "AMOUNT_SQUARE=%s;DURATION=%s"), //
Multiwave(4, "BOLUS_MULTIWAVE", "AMOUNT=%s;AMOUNT_SQUARE=%s;DURATION=%s");
companion object {
var codeMapping = HashMap<Int, PumpBolusType?>()
fun getByCode(code: Int): PumpBolusType? {
return if (codeMapping.containsKey(code)) {
codeMapping[code]
} else {
None
}
}
init {
for (pbt in values()) {
codeMapping[pbt.code] = pbt
}
}
}
var code: Int
var i18nKey: String
var valueTemplate: String? = null
constructor(code: Int, i18nKey: String) {
this.code = code
this.i18nKey = i18nKey
}
constructor(code: Int, i18nKey: String, valueTemplate: String?) {
this.code = code
this.i18nKey = i18nKey
this.valueTemplate = valueTemplate
}
//override val name: String
}

View file

@ -1,58 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs;
/**
* Created by andy on 27.02.15.
*/
public enum PumpConfigurationGroup {
General(1, "GROUP_GENERAL"), //
Device(2, "GROUP_DEVICE"), //
Insulin(3, "GROUP_INSULIN"), //
Basal(4, "GROUP_BASAL"), //
Bolus(5, "GROUP_BOLUS"), //
Sound(6, "GROUP_SOUND"), //
Other(20, "GROUP_OTHER"), //
UnknownGroup(21, "GROUP_UNKNOWN"), //
; //
static boolean translated;
int code;
String i18nKey;
String translation;
PumpConfigurationGroup(int code, String i18nKey) {
this.code = code;
this.i18nKey = i18nKey;
}
public String getTranslation() {
return translation;
}
public void setTranslation(String translation) {
this.translation = translation;
}
public int getCode() {
return code;
}
public String getI18nKey() {
return i18nKey;
}
public String getName() {
return this.name();
}
}

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.plugins.pump.medtronic.defs
/**
* This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes
* management and modified/extended for AAPS.
*
* Author: Andy {andy.rozman@gmail.com}
*/
enum class PumpConfigurationGroup(var code: Int) {
General(1), //
Device(2), //
Insulin(3), //
Basal(4), //
Bolus(5), //
Sound(6), //
Other(20), //
UnknownGroup(21);
}

View file

@ -1,180 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.driver;
import androidx.annotation.NonNull;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
* Created by andy on 4/28/18.
*/
@Singleton
public class MedtronicPumpStatus extends info.nightscout.androidaps.plugins.pump.common.data.PumpStatus {
private final ResourceHelper resourceHelper;
private final SP sp;
private final RileyLinkUtil rileyLinkUtil;
private final RxBusWrapper rxBus;
public String errorDescription = null;
public String serialNumber;
public String pumpFrequency = null;
public Double maxBolus;
public Double maxBasal;
// statuses
private PumpDeviceState pumpDeviceState = PumpDeviceState.NeverContacted;
public MedtronicDeviceType medtronicDeviceType = null;
public Date tempBasalStart;
public Double tempBasalAmount = 0.0d;
// fixme
public Integer tempBasalLength = 0;
private Map<String, PumpType> medtronicPumpMap = null;
private Map<String, MedtronicDeviceType> medtronicDeviceTypeMap = null;
public BasalProfileStatus basalProfileStatus = BasalProfileStatus.NotInitialized;
public BatteryType batteryType = BatteryType.None;
@Inject
public MedtronicPumpStatus(ResourceHelper resourceHelper,
SP sp,
RxBusWrapper rxBus,
RileyLinkUtil rileyLinkUtil
) {
super(PumpType.MEDTRONIC_522_722);
this.resourceHelper = resourceHelper;
this.sp = sp;
this.rxBus = rxBus;
this.rileyLinkUtil = rileyLinkUtil;
initSettings();
}
public void initSettings() {
this.activeProfileName = "STD";
this.reservoirRemainingUnits = 75d;
this.batteryRemaining = 75;
if (this.medtronicPumpMap == null)
createMedtronicPumpMap();
if (this.medtronicDeviceTypeMap == null)
createMedtronicDeviceTypeMap();
this.lastConnection = sp.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L);
this.lastDataTime = this.lastConnection;
}
private void createMedtronicDeviceTypeMap() {
medtronicDeviceTypeMap = new HashMap<>();
medtronicDeviceTypeMap.put("512", MedtronicDeviceType.Medtronic_512);
medtronicDeviceTypeMap.put("712", MedtronicDeviceType.Medtronic_712);
medtronicDeviceTypeMap.put("515", MedtronicDeviceType.Medtronic_515);
medtronicDeviceTypeMap.put("715", MedtronicDeviceType.Medtronic_715);
medtronicDeviceTypeMap.put("522", MedtronicDeviceType.Medtronic_522);
medtronicDeviceTypeMap.put("722", MedtronicDeviceType.Medtronic_722);
medtronicDeviceTypeMap.put("523", MedtronicDeviceType.Medtronic_523_Revel);
medtronicDeviceTypeMap.put("723", MedtronicDeviceType.Medtronic_723_Revel);
medtronicDeviceTypeMap.put("554", MedtronicDeviceType.Medtronic_554_Veo);
medtronicDeviceTypeMap.put("754", MedtronicDeviceType.Medtronic_754_Veo);
}
private void createMedtronicPumpMap() {
medtronicPumpMap = new HashMap<>();
medtronicPumpMap.put("512", PumpType.MEDTRONIC_512_712);
medtronicPumpMap.put("712", PumpType.MEDTRONIC_512_712);
medtronicPumpMap.put("515", PumpType.MEDTRONIC_515_715);
medtronicPumpMap.put("715", PumpType.MEDTRONIC_515_715);
medtronicPumpMap.put("522", PumpType.MEDTRONIC_522_722);
medtronicPumpMap.put("722", PumpType.MEDTRONIC_522_722);
medtronicPumpMap.put("523", PumpType.MEDTRONIC_523_723_REVEL);
medtronicPumpMap.put("723", PumpType.MEDTRONIC_523_723_REVEL);
medtronicPumpMap.put("554", PumpType.MEDTRONIC_554_754_VEO);
medtronicPumpMap.put("754", PumpType.MEDTRONIC_554_754_VEO);
}
public Map<String, PumpType> getMedtronicPumpMap() {
return medtronicPumpMap;
}
public Map<String, MedtronicDeviceType> getMedtronicDeviceTypeMap() {
return medtronicDeviceTypeMap;
}
public double getBasalProfileForHour() {
if (basalsByHour != null) {
GregorianCalendar c = new GregorianCalendar();
int hour = c.get(Calendar.HOUR_OF_DAY);
return basalsByHour[hour];
}
return 0;
}
// Battery type
private Map<String, BatteryType> mapByDescription;
public BatteryType getBatteryTypeByDescription(String batteryTypeStr) {
if (mapByDescription == null) {
mapByDescription = new HashMap<>();
for (BatteryType value : BatteryType.values()) {
mapByDescription.put(resourceHelper.gs(value.description), value);
}
}
if (mapByDescription.containsKey(batteryTypeStr)) {
return mapByDescription.get(batteryTypeStr);
}
return BatteryType.None;
}
@NonNull
public String getErrorInfo() {
return (errorDescription == null) ? "-" : errorDescription;
}
public PumpDeviceState getPumpDeviceState() {
return pumpDeviceState;
}
public void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
this.pumpDeviceState = pumpDeviceState;
rileyLinkUtil.getRileyLinkHistory().add(new RLHistoryItem(pumpDeviceState, RileyLinkTargetDevice.MedtronicPump));
rxBus.send(new EventRileyLinkDeviceStatusChange(pumpDeviceState));
}
}

View file

@ -0,0 +1,139 @@
package info.nightscout.androidaps.plugins.pump.medtronic.driver
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BasalProfileStatus
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
/**
* Created by andy on 4/28/18.
*/
@Singleton
class MedtronicPumpStatus @Inject constructor(private val resourceHelper: ResourceHelper,
private val sp: SP,
private val rxBus: RxBusWrapper,
private val rileyLinkUtil: RileyLinkUtil
) : PumpStatus(PumpType.MEDTRONIC_522_722) {
var errorDescription: String? = null
var serialNumber: String? = null
var pumpFrequency: String? = null
var maxBolus: Double? = null
var maxBasal: Double? = null
// statuses
var pumpDeviceState = PumpDeviceState.NeverContacted
set(pumpDeviceState) {
field = pumpDeviceState
rileyLinkUtil.rileyLinkHistory.add(RLHistoryItem(pumpDeviceState, RileyLinkTargetDevice.MedtronicPump))
rxBus.send(EventRileyLinkDeviceStatusChange(pumpDeviceState))
}
var medtronicDeviceType: MedtronicDeviceType? = null
// fixme
var medtronicPumpMap: MutableMap<String, PumpType> = HashMap()
var medtronicDeviceTypeMap: MutableMap<String, MedtronicDeviceType> = HashMap()
var basalProfileStatus = BasalProfileStatus.NotInitialized
var batteryType = BatteryType.None
override fun initSettings() {
activeProfileName = "STD"
reservoirRemainingUnits = 75.0
batteryRemaining = 75
if (medtronicPumpMap.isEmpty()) createMedtronicPumpMap()
if (medtronicDeviceTypeMap.isEmpty()) createMedtronicDeviceTypeMap()
lastConnection = sp.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L)
lastDataTime = lastConnection
}
private fun createMedtronicDeviceTypeMap() {
medtronicDeviceTypeMap["512"] = MedtronicDeviceType.Medtronic_512
medtronicDeviceTypeMap["712"] = MedtronicDeviceType.Medtronic_712
medtronicDeviceTypeMap["515"] = MedtronicDeviceType.Medtronic_515
medtronicDeviceTypeMap["715"] = MedtronicDeviceType.Medtronic_715
medtronicDeviceTypeMap["522"] = MedtronicDeviceType.Medtronic_522
medtronicDeviceTypeMap["722"] = MedtronicDeviceType.Medtronic_722
medtronicDeviceTypeMap["523"] = MedtronicDeviceType.Medtronic_523_Revel
medtronicDeviceTypeMap["723"] = MedtronicDeviceType.Medtronic_723_Revel
medtronicDeviceTypeMap["554"] = MedtronicDeviceType.Medtronic_554_Veo
medtronicDeviceTypeMap["754"] = MedtronicDeviceType.Medtronic_754_Veo
}
private fun createMedtronicPumpMap() {
medtronicPumpMap = HashMap()
medtronicPumpMap["512"] = PumpType.MEDTRONIC_512_712
medtronicPumpMap["712"] = PumpType.MEDTRONIC_512_712
medtronicPumpMap["515"] = PumpType.MEDTRONIC_515_715
medtronicPumpMap["715"] = PumpType.MEDTRONIC_515_715
medtronicPumpMap["522"] = PumpType.MEDTRONIC_522_722
medtronicPumpMap["722"] = PumpType.MEDTRONIC_522_722
medtronicPumpMap["523"] = PumpType.MEDTRONIC_523_723_REVEL
medtronicPumpMap["723"] = PumpType.MEDTRONIC_523_723_REVEL
medtronicPumpMap["554"] = PumpType.MEDTRONIC_554_754_VEO
medtronicPumpMap["754"] = PumpType.MEDTRONIC_554_754_VEO
}
val basalProfileForHour: Double
get() {
if (basalsByHour != null) {
val c = GregorianCalendar()
val hour = c[Calendar.HOUR_OF_DAY]
return basalsByHour!![hour]
}
return 0.0
}
// Battery type
private var mapByDescription: MutableMap<String, BatteryType?> = HashMap()
fun getBatteryTypeByDescription(batteryTypeStr: String?): BatteryType? {
if (mapByDescription.size == 0) {
for (value in BatteryType.values()) {
mapByDescription[resourceHelper.gs(value.description)] = value
}
}
return if (mapByDescription.containsKey(batteryTypeStr)) {
mapByDescription[batteryTypeStr]
} else BatteryType.None
}
override val errorInfo: String
get() = if (errorDescription == null) "-" else errorDescription!!
val tbrRemainingTime: Int?
get() {
if (tempBasalStart == null) return null
if (tempBasalEnd == null) {
val startTime = tempBasalStart!!.time
tempBasalEnd = startTime + tempBasalLength!! * 60 * 1000
}
if (System.currentTimeMillis() > tempBasalEnd!!) {
tempBasalStart = null
tempBasalEnd = null
tempBasalLength = null
tempBasalAmount = null
return null
}
val timeMinutes = (tempBasalEnd!! - System.currentTimeMillis()) / (1000 * 60)
return timeMinutes.toInt()
}
init {
initSettings()
}
}

View file

@ -1,388 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.service;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.IBinder;
import javax.inject.Inject;
import javax.inject.Singleton;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.R;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUIComm;
import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUIPostprocessor;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.BatteryType;
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
/**
* RileyLinkMedtronicService is intended to stay running when the gui-app is closed.
*/
@Singleton
public class RileyLinkMedtronicService extends RileyLinkService {
@Inject MedtronicPumpPlugin medtronicPumpPlugin;
@Inject MedtronicUtil medtronicUtil;
@Inject MedtronicUIPostprocessor medtronicUIPostprocessor;
@Inject MedtronicPumpStatus medtronicPumpStatus;
@Inject RFSpy rfSpy;
@Inject MedtronicCommunicationManager medtronicCommunicationManager;
private MedtronicUIComm medtronicUIComm;
private final IBinder mBinder = new LocalBinder();
private boolean serialChanged = false;
private String[] frequencies;
private String rileyLinkAddress = null;
private boolean rileyLinkAddressChanged = false;
private RileyLinkEncodingType encodingType;
private boolean encodingChanged = false;
private boolean inPreInit = true;
// This empty constructor must be kept, otherwise dagger injection might break!
@Inject
public RileyLinkMedtronicService() {
}
@Override public void onCreate() {
super.onCreate();
aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly created");
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
aapsLogger.warn(LTag.PUMPCOMM, "onConfigurationChanged");
super.onConfigurationChanged(newConfig);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public RileyLinkEncodingType getEncoding() {
return RileyLinkEncodingType.FourByteSixByteLocal;
}
/**
* If you have customized RileyLinkServiceData you need to override this
*/
public void initRileyLinkServiceData() {
frequencies = new String[2];
frequencies[0] = resourceHelper.gs(R.string.key_medtronic_pump_frequency_us_ca);
frequencies[1] = resourceHelper.gs(R.string.key_medtronic_pump_frequency_worldwide);
rileyLinkServiceData.targetDevice = RileyLinkTargetDevice.MedtronicPump;
setPumpIDString(sp.getString(MedtronicConst.Prefs.PumpSerial, "000000"));
// get most recently used RileyLink address and name
rileyLinkServiceData.rileyLinkAddress = sp.getString(RileyLinkConst.Prefs.RileyLinkAddress, "");
rileyLinkServiceData.rileyLinkName = sp.getString(RileyLinkConst.Prefs.RileyLinkName, "");
rfspy.startReader();
medtronicUIComm = new MedtronicUIComm(injector, aapsLogger, medtronicUtil, medtronicUIPostprocessor, medtronicCommunicationManager);
aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly constructed");
}
public MedtronicCommunicationManager getDeviceCommunicationManager() {
return this.medtronicCommunicationManager;
}
@Override
public void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
this.medtronicPumpStatus.setPumpDeviceState(pumpDeviceState);
}
public MedtronicUIComm getMedtronicUIComm() {
return medtronicUIComm;
}
public void setPumpIDString(String pumpID) {
if (pumpID.length() != 6) {
aapsLogger.error("setPumpIDString: invalid pump id string: " + pumpID);
return;
}
byte[] pumpIDBytes = ByteUtil.fromHexString(pumpID);
if (pumpIDBytes == null) {
aapsLogger.error("Invalid pump ID? - PumpID is null.");
rileyLinkServiceData.setPumpID("000000", new byte[]{0, 0, 0});
} else if (pumpIDBytes.length != 3) {
aapsLogger.error("Invalid pump ID? " + ByteUtil.shortHexString(pumpIDBytes));
rileyLinkServiceData.setPumpID("000000", new byte[]{0, 0, 0});
} else if (pumpID.equals("000000")) {
aapsLogger.error("Using pump ID " + pumpID);
rileyLinkServiceData.setPumpID(pumpID, new byte[]{0, 0, 0});
} else {
aapsLogger.info(LTag.PUMPBTCOMM, "Using pump ID " + pumpID);
String oldId = rileyLinkServiceData.pumpID;
rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes);
if (oldId != null && !oldId.equals(pumpID)) {
medtronicUtil.setMedtronicPumpModel(null); // if we change pumpId, model probably changed too
}
return;
}
medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.InvalidConfiguration);
// LOG.info("setPumpIDString: saved pumpID " + idString);
}
public class LocalBinder extends Binder {
public RileyLinkMedtronicService getServiceInstance() {
return RileyLinkMedtronicService.this;
}
}
/* private functions */
// PumpInterface - REMOVE
public boolean isInitialized() {
return rileyLinkServiceData.rileyLinkServiceState.isReady();
}
public boolean verifyConfiguration(boolean forceRileyLinkAddressRenewal) {
try {
String regexSN = "[0-9]{6}";
String regexMac = "([\\da-fA-F]{1,2}(?::|$)){6}";
medtronicPumpStatus.errorDescription = "-";
String serialNr = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null);
if (serialNr == null) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_serial_not_set);
return false;
} else {
if (!serialNr.matches(regexSN)) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_serial_invalid);
return false;
} else {
if (!serialNr.equals(medtronicPumpStatus.serialNumber)) {
medtronicPumpStatus.serialNumber = serialNr;
serialChanged = true;
}
}
}
String pumpTypePref = sp.getStringOrNull(MedtronicConst.Prefs.PumpType, null);
if (pumpTypePref == null) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_type_not_set);
return false;
} else {
String pumpTypePart = pumpTypePref.substring(0, 3);
if (!pumpTypePart.matches("[0-9]{3}")) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_type_invalid);
return false;
} else {
PumpType pumpType = medtronicPumpStatus.getMedtronicPumpMap().get(pumpTypePart);
medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.getMedtronicDeviceTypeMap().get(pumpTypePart);
medtronicPumpPlugin.setPumpType(pumpType);
if (pumpTypePart.startsWith("7"))
medtronicPumpStatus.reservoirFullUnits = 300;
else
medtronicPumpStatus.reservoirFullUnits = 176;
}
}
String pumpFrequency = sp.getStringOrNull(MedtronicConst.Prefs.PumpFrequency, null);
if (pumpFrequency == null) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_frequency_not_set);
return false;
} else {
if (!pumpFrequency.equals(frequencies[0]) && !pumpFrequency.equals(frequencies[1])) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_frequency_invalid);
return false;
} else {
medtronicPumpStatus.pumpFrequency = pumpFrequency;
boolean isFrequencyUS = pumpFrequency.equals(frequencies[0]);
RileyLinkTargetFrequency newTargetFrequency = isFrequencyUS ? //
RileyLinkTargetFrequency.Medtronic_US
: RileyLinkTargetFrequency.Medtronic_WorldWide;
if (rileyLinkServiceData.rileyLinkTargetFrequency != newTargetFrequency) {
rileyLinkServiceData.rileyLinkTargetFrequency = newTargetFrequency;
}
}
}
String rileyLinkAddress = sp.getStringOrNull(RileyLinkConst.Prefs.RileyLinkAddress, null);
if (rileyLinkAddress == null) {
aapsLogger.debug(LTag.PUMP, "RileyLink address invalid: null");
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_rileylink_address_invalid);
return false;
} else {
if (!rileyLinkAddress.matches(regexMac)) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_rileylink_address_invalid);
aapsLogger.debug(LTag.PUMP, "RileyLink address invalid: %s", rileyLinkAddress);
} else {
if (!rileyLinkAddress.equals(this.rileyLinkAddress)) {
this.rileyLinkAddress = rileyLinkAddress;
rileyLinkAddressChanged = true;
}
}
}
double maxBolusLcl = checkParameterValue(MedtronicConst.Prefs.MaxBolus, "25.0", 25.0d);
if (medtronicPumpStatus.maxBolus == null || !medtronicPumpStatus.maxBolus.equals(maxBolusLcl)) {
medtronicPumpStatus.maxBolus = maxBolusLcl;
//LOG.debug("Max Bolus from AAPS settings is " + maxBolus);
}
double maxBasalLcl = checkParameterValue(MedtronicConst.Prefs.MaxBasal, "35.0", 35.0d);
if (medtronicPumpStatus.maxBasal == null || !medtronicPumpStatus.maxBasal.equals(maxBasalLcl)) {
medtronicPumpStatus.maxBasal = maxBasalLcl;
//LOG.debug("Max Basal from AAPS settings is " + maxBasal);
}
String encodingTypeStr = sp.getStringOrNull(MedtronicConst.Prefs.Encoding, null);
if (encodingTypeStr == null) {
return false;
}
RileyLinkEncodingType newEncodingType = RileyLinkEncodingType.getByDescription(encodingTypeStr, resourceHelper);
if (encodingType == null) {
encodingType = newEncodingType;
} else if (encodingType != newEncodingType) {
encodingType = newEncodingType;
encodingChanged = true;
}
String batteryTypeStr = sp.getStringOrNull(MedtronicConst.Prefs.BatteryType, null);
if (batteryTypeStr == null)
return false;
BatteryType batteryType = medtronicPumpStatus.getBatteryTypeByDescription(batteryTypeStr);
if (medtronicPumpStatus.batteryType != batteryType) {
medtronicPumpStatus.batteryType = batteryType;
}
//String bolusDebugEnabled = sp.getStringOrNull(MedtronicConst.Prefs.BolusDebugEnabled, null);
//boolean bolusDebug = bolusDebugEnabled != null && bolusDebugEnabled.equals(resourceHelper.gs(R.string.common_on));
//MedtronicHistoryData.doubleBolusDebug = bolusDebug;
rileyLinkServiceData.showBatteryLevel = sp.getBoolean(RileyLinkConst.Prefs.ShowBatteryLevel, false);
reconfigureService(forceRileyLinkAddressRenewal);
return true;
} catch (Exception ex) {
medtronicPumpStatus.errorDescription = ex.getMessage();
aapsLogger.error(LTag.PUMP, "Error on Verification: " + ex.getMessage(), ex);
return false;
}
}
private boolean reconfigureService(boolean forceRileyLinkAddressRenewal) {
if (!inPreInit) {
if (serialChanged) {
setPumpIDString(medtronicPumpStatus.serialNumber); // short operation
serialChanged = false;
}
if (rileyLinkAddressChanged || forceRileyLinkAddressRenewal) {
rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkNewAddressSet, this);
rileyLinkAddressChanged = false;
}
if (encodingChanged) {
changeRileyLinkEncoding(encodingType);
encodingChanged = false;
}
}
// if (targetFrequencyChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
// RileyLinkUtil.setRileyLinkTargetFrequency(targetFrequency);
// // RileyLinkUtil.getRileyLinkCommunicationManager().refreshRileyLinkTargetFrequency();
// targetFrequencyChanged = false;
// }
return (!rileyLinkAddressChanged && !serialChanged && !encodingChanged); // && !targetFrequencyChanged);
}
private double checkParameterValue(int key, String defaultValue, double defaultValueDouble) {
double val;
String value = sp.getString(key, defaultValue);
try {
val = Double.parseDouble(value);
} catch (Exception ex) {
aapsLogger.error("Error parsing setting: %s, value found %s", key, value);
val = defaultValueDouble;
}
if (val > defaultValueDouble) {
sp.putString(key, defaultValue);
val = defaultValueDouble;
}
return val;
}
public boolean setNotInPreInit() {
this.inPreInit = false;
return reconfigureService(false);
}
}

View file

@ -0,0 +1,289 @@
package info.nightscout.androidaps.plugins.pump.medtronic.service
import android.content.Intent
import android.content.res.Configuration
import android.os.Binder
import android.os.IBinder
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin
import info.nightscout.androidaps.plugins.pump.medtronic.R
import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager
import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUIComm
import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUIPostprocessor
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import javax.inject.Inject
import javax.inject.Singleton
/**
* RileyLinkMedtronicService is intended to stay running when the gui-app is closed.
*/
@Singleton
class RileyLinkMedtronicService // This empty constructor must be kept, otherwise dagger injection might break!
@Inject constructor() : RileyLinkService() {
@Inject lateinit var medtronicPumpPlugin: MedtronicPumpPlugin
@Inject lateinit var medtronicUtil: MedtronicUtil
@Inject lateinit var medtronicUIPostprocessor: MedtronicUIPostprocessor
@Inject lateinit var medtronicPumpStatus: MedtronicPumpStatus
@Inject lateinit var rfSpy: RFSpy
@Inject lateinit var medtronicCommunicationManager: MedtronicCommunicationManager
var medtronicUIComm: MedtronicUIComm? = null
private set
private val mBinder: IBinder = LocalBinder()
private var serialChanged = false
private var frequencies: Array<String?>? = null
private var rileyLinkAddress: String? = null
private var rileyLinkAddressChanged = false
private var encodingType: RileyLinkEncodingType? = null
private var encodingChanged = false
private var inPreInit = true
override fun onCreate() {
super.onCreate()
aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly created")
}
override fun onConfigurationChanged(newConfig: Configuration) {
aapsLogger.warn(LTag.PUMPCOMM, "onConfigurationChanged")
super.onConfigurationChanged(newConfig)
}
override fun onBind(intent: Intent): IBinder {
return mBinder
}
override fun getEncoding(): RileyLinkEncodingType {
return RileyLinkEncodingType.FourByteSixByteLocal
}
/**
* If you have customized RileyLinkServiceData you need to override this
*/
override fun initRileyLinkServiceData() {
frequencies = arrayOfNulls(2)
frequencies!![0] = resourceHelper.gs(R.string.key_medtronic_pump_frequency_us_ca)
frequencies!![1] = resourceHelper.gs(R.string.key_medtronic_pump_frequency_worldwide)
rileyLinkServiceData.targetDevice = RileyLinkTargetDevice.MedtronicPump
setPumpIDString(sp.getString(MedtronicConst.Prefs.PumpSerial, "000000"))
// get most recently used RileyLink address and name
rileyLinkServiceData.rileyLinkAddress = sp.getString(RileyLinkConst.Prefs.RileyLinkAddress, "")
rileyLinkServiceData.rileyLinkName = sp.getString(RileyLinkConst.Prefs.RileyLinkName, "")
rfspy.startReader()
medtronicUIComm = MedtronicUIComm(injector, aapsLogger, medtronicUtil, medtronicUIPostprocessor, medtronicCommunicationManager)
aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly constructed")
}
override fun getDeviceCommunicationManager(): MedtronicCommunicationManager {
return medtronicCommunicationManager
}
override fun setPumpDeviceState(pumpDeviceState: PumpDeviceState) {
medtronicPumpStatus.pumpDeviceState = pumpDeviceState
}
fun setPumpIDString(pumpID: String) {
if (pumpID.length != 6) {
aapsLogger.error("setPumpIDString: invalid pump id string: $pumpID")
return
}
val pumpIDBytes = ByteUtil.fromHexString(pumpID)
if (pumpIDBytes == null) {
aapsLogger.error("Invalid pump ID? - PumpID is null.")
rileyLinkServiceData.setPumpID("000000", byteArrayOf(0, 0, 0))
} else if (pumpIDBytes.size != 3) {
aapsLogger.error("Invalid pump ID? " + ByteUtil.shortHexString(pumpIDBytes))
rileyLinkServiceData.setPumpID("000000", byteArrayOf(0, 0, 0))
} else if (pumpID == "000000") {
aapsLogger.error("Using pump ID $pumpID")
rileyLinkServiceData.setPumpID(pumpID, byteArrayOf(0, 0, 0))
} else {
aapsLogger.info(LTag.PUMPBTCOMM, "Using pump ID $pumpID")
val oldId = rileyLinkServiceData.pumpID
rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes)
if (oldId != null && oldId != pumpID) {
medtronicUtil.medtronicPumpModel = null // if we change pumpId, model probably changed too
}
return
}
medtronicPumpStatus.pumpDeviceState = PumpDeviceState.InvalidConfiguration
// LOG.info("setPumpIDString: saved pumpID " + idString);
}
inner class LocalBinder : Binder() {
val serviceInstance: RileyLinkMedtronicService
get() = this@RileyLinkMedtronicService
}
/* private functions */ // PumpInterface - REMOVE
val isInitialized: Boolean
get() = rileyLinkServiceData.rileyLinkServiceState.isReady
override fun verifyConfiguration(forceRileyLinkAddressRenewal: Boolean): Boolean {
return try {
val regexSN = "[0-9]{6}"
val regexMac = "([\\da-fA-F]{1,2}(?::|$)){6}"
medtronicPumpStatus.errorDescription = "-"
val serialNr = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null)
if (serialNr == null) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_serial_not_set)
return false
} else {
if (!serialNr.matches(regexSN.toRegex())) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_serial_invalid)
return false
} else {
if (serialNr != medtronicPumpStatus.serialNumber) {
medtronicPumpStatus.serialNumber = serialNr
serialChanged = true
}
}
}
val pumpTypePref = sp.getStringOrNull(MedtronicConst.Prefs.PumpType, null)
if (pumpTypePref == null) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_type_not_set)
return false
} else {
val pumpTypePart = pumpTypePref.substring(0, 3)
if (!pumpTypePart.matches("[0-9]{3}".toRegex())) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_type_invalid)
return false
} else {
val pumpType = medtronicPumpStatus.medtronicPumpMap[pumpTypePart]
medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.medtronicDeviceTypeMap[pumpTypePart]
medtronicPumpPlugin.pumpType = pumpType
if (pumpTypePart.startsWith("7")) medtronicPumpStatus.reservoirFullUnits = 300 else medtronicPumpStatus.reservoirFullUnits = 176
}
}
val pumpFrequency = sp.getStringOrNull(MedtronicConst.Prefs.PumpFrequency, null)
if (pumpFrequency == null) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_frequency_not_set)
return false
} else {
if (pumpFrequency != frequencies!![0] && pumpFrequency != frequencies!![1]) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_frequency_invalid)
return false
} else {
medtronicPumpStatus.pumpFrequency = pumpFrequency
val isFrequencyUS = pumpFrequency == frequencies!![0]
val newTargetFrequency = if (isFrequencyUS) //
RileyLinkTargetFrequency.Medtronic_US else RileyLinkTargetFrequency.Medtronic_WorldWide
if (rileyLinkServiceData.rileyLinkTargetFrequency != newTargetFrequency) {
rileyLinkServiceData.rileyLinkTargetFrequency = newTargetFrequency
}
}
}
val rileyLinkAddress = sp.getStringOrNull(RileyLinkConst.Prefs.RileyLinkAddress, null)
if (rileyLinkAddress == null) {
aapsLogger.debug(LTag.PUMP, "RileyLink address invalid: null")
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_rileylink_address_invalid)
return false
} else {
if (!rileyLinkAddress.matches(regexMac.toRegex())) {
medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_rileylink_address_invalid)
aapsLogger.debug(LTag.PUMP, "RileyLink address invalid: %s", rileyLinkAddress)
} else {
if (rileyLinkAddress != this.rileyLinkAddress) {
this.rileyLinkAddress = rileyLinkAddress
rileyLinkAddressChanged = true
}
}
}
val maxBolusLcl = checkParameterValue(MedtronicConst.Prefs.MaxBolus, "25.0", 25.0)
if (medtronicPumpStatus.maxBolus == null || medtronicPumpStatus.maxBolus != maxBolusLcl) {
medtronicPumpStatus.maxBolus = maxBolusLcl
//LOG.debug("Max Bolus from AAPS settings is " + maxBolus);
}
val maxBasalLcl = checkParameterValue(MedtronicConst.Prefs.MaxBasal, "35.0", 35.0)
if (medtronicPumpStatus.maxBasal == null || medtronicPumpStatus.maxBasal != maxBasalLcl) {
medtronicPumpStatus.maxBasal = maxBasalLcl
//LOG.debug("Max Basal from AAPS settings is " + maxBasal);
}
val encodingTypeStr = sp.getStringOrNull(MedtronicConst.Prefs.Encoding, null)
?: return false
val newEncodingType = RileyLinkEncodingType.getByDescription(encodingTypeStr, resourceHelper)
if (encodingType == null) {
encodingType = newEncodingType
} else if (encodingType != newEncodingType) {
encodingType = newEncodingType
encodingChanged = true
}
val batteryTypeStr = sp.getStringOrNull(MedtronicConst.Prefs.BatteryType, null)
?: return false
val batteryType = medtronicPumpStatus.getBatteryTypeByDescription(batteryTypeStr)
if (medtronicPumpStatus.batteryType !== batteryType) {
medtronicPumpStatus.batteryType = batteryType!!
}
//String bolusDebugEnabled = sp.getStringOrNull(MedtronicConst.Prefs.BolusDebugEnabled, null);
//boolean bolusDebug = bolusDebugEnabled != null && bolusDebugEnabled.equals(resourceHelper.gs(R.string.common_on));
//MedtronicHistoryData.doubleBolusDebug = bolusDebug;
rileyLinkServiceData.showBatteryLevel = sp.getBoolean(RileyLinkConst.Prefs.ShowBatteryLevel, false)
reconfigureService(forceRileyLinkAddressRenewal)
true
} catch (ex: Exception) {
medtronicPumpStatus.errorDescription = ex.message
aapsLogger.error(LTag.PUMP, "Error on Verification: " + ex.message, ex)
false
}
}
private fun reconfigureService(forceRileyLinkAddressRenewal: Boolean): Boolean {
if (!inPreInit) {
if (serialChanged) {
setPumpIDString(medtronicPumpStatus.serialNumber!!) // short operation
serialChanged = false
}
if (rileyLinkAddressChanged || forceRileyLinkAddressRenewal) {
rileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkNewAddressSet, this)
rileyLinkAddressChanged = false
}
if (encodingChanged) {
changeRileyLinkEncoding(encodingType)
encodingChanged = false
}
}
// if (targetFrequencyChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
// RileyLinkUtil.setRileyLinkTargetFrequency(targetFrequency);
// // RileyLinkUtil.getRileyLinkCommunicationManager().refreshRileyLinkTargetFrequency();
// targetFrequencyChanged = false;
// }
return !rileyLinkAddressChanged && !serialChanged && !encodingChanged // && !targetFrequencyChanged);
}
private fun checkParameterValue(key: Int, defaultValue: String, defaultValueDouble: Double): Double {
var `val`: Double
val value = sp.getString(key, defaultValue)
`val` = try {
value.toDouble()
} catch (ex: Exception) {
aapsLogger.error("Error parsing setting: %s, value found %s", key, value)
defaultValueDouble
}
if (`val` > defaultValueDouble) {
sp.putString(key, defaultValue)
`val` = defaultValueDouble
}
return `val`
}
fun setNotInPreInit(): Boolean {
inPreInit = false
return reconfigureService(false)
}
}

View file

@ -1,40 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.util;
import info.nightscout.androidaps.plugins.pump.medtronic.R;
/**
* Created by andy on 5/12/18.
*/
public class MedtronicConst {
static final String Prefix = "AAPS.Medtronic.";
public static class Prefs {
public static final int PumpSerial = R.string.key_medtronic_serial;
public static final int PumpType = R.string.key_medtronic_pump_type;
public static final int PumpFrequency = R.string.key_medtronic_frequency;
public static final int MaxBolus = R.string.key_medtronic_max_bolus;
public static final int MaxBasal = R.string.key_medtronic_max_basal;
public static final int BolusDelay = R.string.key_medtronic_bolus_delay;
public static final int Encoding = R.string.key_medtronic_encoding;
public static final int BatteryType = R.string.key_medtronic_battery_type;
public static final int BolusDebugEnabled = R.string.key_medtronic_bolus_debug;
}
public static class Statistics {
public static final String StatsPrefix = "medtronic_";
public static final String FirstPumpStart = Prefix + "first_pump_use";
public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime";
public static final String LastGoodPumpFrequency = Prefix + "LastGoodPumpFrequency";
public static final String TBRsSet = StatsPrefix + "tbrs_set";
public static final String StandardBoluses = StatsPrefix + "std_boluses_delivered";
public static final String SMBBoluses = StatsPrefix + "smb_boluses_delivered";
public static final String LastPumpHistoryEntry = StatsPrefix + "pump_history_entry";
public static final String LastPrime = StatsPrefix + "last_sent_prime";
public static final String LastRewind = StatsPrefix + "last_sent_rewind";
public static final String InternalTemporaryDatabase = StatsPrefix + "temporary_entries";
}
}

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps.plugins.pump.medtronic.util
import info.nightscout.androidaps.plugins.pump.medtronic.R
/**
* Created by andy on 5/12/18.
*/
object MedtronicConst {
const val Prefix = "AAPS.Medtronic."
object Prefs {
@JvmField val PumpSerial = R.string.key_medtronic_serial
@JvmField val PumpType = R.string.key_medtronic_pump_type
@JvmField val PumpFrequency = R.string.key_medtronic_frequency
@JvmField val MaxBolus = R.string.key_medtronic_max_bolus
@JvmField val MaxBasal = R.string.key_medtronic_max_basal
@JvmField val BolusDelay = R.string.key_medtronic_bolus_delay
@JvmField val Encoding = R.string.key_medtronic_encoding
@JvmField val BatteryType = R.string.key_medtronic_battery_type
val BolusDebugEnabled = R.string.key_medtronic_bolus_debug
}
object Statistics {
const val StatsPrefix = "medtronic_"
const val FirstPumpStart = Prefix + "first_pump_use"
const val LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime"
const val LastGoodPumpFrequency = Prefix + "LastGoodPumpFrequency"
const val TBRsSet = StatsPrefix + "tbrs_set"
const val StandardBoluses = StatsPrefix + "std_boluses_delivered"
const val SMBBoluses = StatsPrefix + "smb_boluses_delivered"
const val LastPumpHistoryEntry = StatsPrefix + "pump_history_entry"
const val LastPrime = StatsPrefix + "last_sent_prime"
const val LastRewind = StatsPrefix + "last_sent_rewind"
const val InternalTemporaryDatabase = StatsPrefix + "temporary_entries"
}
}

View file

@ -1,456 +0,0 @@
package info.nightscout.androidaps.plugins.pump.medtronic.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.joda.time.LocalTime;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
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.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.events.EventRileyLinkDeviceStatusChange;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.RLHistoryItemMedtronic;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
/**
* Created by andy on 5/9/18.
*/
@Singleton
public class MedtronicUtil {
private final int ENVELOPE_SIZE = 4; // 0xA7 S1 S2 S3 CMD PARAM_COUNT [PARAMS]
private static final boolean lowLevelDebug = true;
//private MedtronicDeviceType medtronicPumpModel;
private MedtronicCommandType currentCommand;
private Map<String, PumpSettingDTO> settings;
private final int BIG_FRAME_LENGTH = 65;
private final int doneBit = 1 << 7;
private ClockDTO pumpTime;
public Gson gsonInstance = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
private final AAPSLogger aapsLogger;
private final RxBusWrapper rxBus;
private final RileyLinkUtil rileyLinkUtil;
private final MedtronicPumpStatus medtronicPumpStatus;
@Inject
public MedtronicUtil(
AAPSLogger aapsLogger,
RxBusWrapper rxBus,
RileyLinkUtil rileyLinkUtil,
MedtronicPumpStatus medtronicPumpStatus
) {
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
this.rileyLinkUtil = rileyLinkUtil;
this.medtronicPumpStatus = medtronicPumpStatus;
}
public LocalTime getTimeFrom30MinInterval(int interval) {
if (interval % 2 == 0) {
return new LocalTime(interval / 2, 0);
} else {
return new LocalTime((interval - 1) / 2, 30);
}
}
public static int getIntervalFromMinutes(int minutes) {
return minutes / 30;
}
public static int makeUnsignedShort(int b2, int b1) {
int k = (b2 & 0xff) << 8 | b1 & 0xff;
return k;
}
public static byte[] getByteArrayFromUnsignedShort(int shortValue, boolean returnFixedSize) {
byte highByte = (byte) (shortValue >> 8 & 0xFF);
byte lowByte = (byte) (shortValue & 0xFF);
if (highByte > 0) {
return createByteArray(highByte, lowByte);
} else {
return returnFixedSize ? createByteArray(highByte, lowByte) : createByteArray(lowByte);
}
}
public static byte[] createByteArray(byte... data) {
return data;
}
public static byte[] createByteArray(List<Byte> data) {
byte[] array = new byte[data.size()];
for (int i = 0; i < data.size(); i++) {
array[i] = data.get(i);
}
return array;
}
public double decodeBasalInsulin(int i, int j) {
return decodeBasalInsulin(makeUnsignedShort(i, j));
}
public double decodeBasalInsulin(int i) {
return (double) i / 40.0d;
}
public byte[] getBasalStrokes(double amount) {
return getBasalStrokes(amount, false);
}
public static byte[] getBasalStrokes(double amount, boolean returnFixedSize) {
return getStrokes(amount, 40, returnFixedSize);
}
public int getBasalStrokesInt(double amount) {
return getStrokesInt(amount, 40);
}
public byte[] getBolusStrokes(double amount) {
int strokesPerUnit = medtronicPumpStatus.medtronicDeviceType.getBolusStrokes();
int length;
int scrollRate;
if (strokesPerUnit >= 40) {
length = 2;
// 40-stroke pumps scroll faster for higher unit values
if (amount > 10)
scrollRate = 4;
else if (amount > 1)
scrollRate = 2;
else
scrollRate = 1;
} else {
length = 1;
scrollRate = 1;
}
int strokes = (int) (amount * ((strokesPerUnit * 1.0d) / (scrollRate * 1.0d))) * scrollRate;
byte[] body = ByteUtil.fromHexString(String.format("%02x%0" + (2 * length) + "x", length, strokes));
return body;
}
public byte[] createCommandBody(byte[] input) {
return ByteUtil.concat((byte) input.length, input);
}
public static byte[] getStrokes(double amount, int strokesPerUnit, boolean returnFixedSize) {
int strokes = getStrokesInt(amount, strokesPerUnit);
return getByteArrayFromUnsignedShort(strokes, returnFixedSize);
}
public static int getStrokesInt(double amount, int strokesPerUnit) {
int length = 1;
int scrollRate = 1;
if (strokesPerUnit >= 40) {
length = 2;
// 40-stroke pumps scroll faster for higher unit values
if (amount > 10)
scrollRate = 4;
else if (amount > 1)
scrollRate = 2;
}
int strokes = (int) (amount * (strokesPerUnit / (scrollRate * 1.0d)));
strokes *= scrollRate;
return strokes;
}
public void sendNotification(MedtronicNotificationType notificationType, ResourceHelper resourceHelper, RxBusWrapper rxBus) {
Notification notification = new Notification( //
notificationType.getNotificationType(), //
resourceHelper.gs(notificationType.getResourceId()), //
notificationType.getNotificationUrgency());
rxBus.send(new EventNewNotification(notification));
}
public void sendNotification(MedtronicNotificationType notificationType, ResourceHelper resourceHelper, RxBusWrapper rxBus, Object... parameters) {
Notification notification = new Notification( //
notificationType.getNotificationType(), //
resourceHelper.gs(notificationType.getResourceId(), parameters), //
notificationType.getNotificationUrgency());
rxBus.send(new EventNewNotification(notification));
}
public void dismissNotification(MedtronicNotificationType notificationType, RxBusWrapper rxBus) {
rxBus.send(new EventDismissNotification(notificationType.getNotificationType()));
}
// public byte[] buildCommandPayload(MessageType commandType, byte[] parameters) {
// return buildCommandPayload(commandType.getValue(), parameters);
// }
public byte[] buildCommandPayload(RileyLinkServiceData rileyLinkServiceData, MedtronicCommandType commandType, byte[] parameters) {
return buildCommandPayload(rileyLinkServiceData, commandType.commandCode, parameters);
}
public byte[] buildCommandPayload(RileyLinkServiceData rileyLinkServiceData, byte commandType, byte[] parameters) {
// A7 31 65 51 C0 00 52
byte commandLength = (byte) (parameters == null ? 2 : 2 + parameters.length);
ByteBuffer sendPayloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + commandLength); // + CRC_SIZE
sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN);
byte[] serialNumberBCD = rileyLinkServiceData.pumpIDBytes;
sendPayloadBuffer.put((byte) 0xA7);
sendPayloadBuffer.put(serialNumberBCD[0]);
sendPayloadBuffer.put(serialNumberBCD[1]);
sendPayloadBuffer.put(serialNumberBCD[2]);
sendPayloadBuffer.put(commandType);
if (parameters == null) {
sendPayloadBuffer.put((byte) 0x00);
} else {
sendPayloadBuffer.put((byte) parameters.length); // size
for (byte val : parameters) {
sendPayloadBuffer.put(val);
}
}
byte[] payload = sendPayloadBuffer.array();
aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "buildCommandPayload [%s]", ByteUtil.shortHexString(payload)));
// int crc = computeCRC8WithPolynomial(payload, 0, payload.length - 1);
// LOG.info("crc: " + crc);
// sendPayloadBuffer.put((byte) crc);
return sendPayloadBuffer.array();
}
// Note: at the moment supported only for 24 items, if you will use it for more than
// that you will need to add
public List<List<Byte>> getBasalProfileFrames(byte[] data) {
boolean done = false;
int start = 0;
int frame = 1;
List<List<Byte>> frames = new ArrayList<>();
boolean lastFrame = false;
do {
int frameLength = BIG_FRAME_LENGTH - 1;
if (start + frameLength > data.length) {
frameLength = data.length - start;
}
// System.out.println("Framelength: " + frameLength);
byte[] substring = ByteUtil.substring(data, start, frameLength);
// System.out.println("Subarray: " + ByteUtil.getCompactString(substring));
// System.out.println("Subarray Lenths: " + substring.length);
List<Byte> frameData = ByteUtil.getListFromByteArray(substring);
if (isEmptyFrame(frameData)) {
byte b = (byte) frame;
// b |= 0x80;
b |= 0b1000_0000;
// b |= doneBit;
frameData.add(0, b);
checkAndAppenLastFrame(frameData);
lastFrame = true;
done = true;
} else {
frameData.add(0, (byte) frame);
}
// System.out.println("Subarray: " + ByteUtil.getCompactString(substring));
frames.add(frameData);
frame++;
start += (BIG_FRAME_LENGTH - 1);
if (start == data.length) {
done = true;
}
} while (!done);
if (!lastFrame) {
List<Byte> frameData = new ArrayList<>();
byte b = (byte) frame;
b |= 0b1000_0000;
// b |= doneBit;
frameData.add(b);
checkAndAppenLastFrame(frameData);
}
return frames;
}
private void checkAndAppenLastFrame(List<Byte> frameData) {
if (frameData.size() == BIG_FRAME_LENGTH)
return;
int missing = BIG_FRAME_LENGTH - frameData.size();
for (int i = 0; i < missing; i++) {
frameData.add((byte) 0x00);
}
}
private boolean isEmptyFrame(List<Byte> frameData) {
for (Byte frameDateEntry : frameData) {
if (frameDateEntry != 0x00) {
return false;
}
}
return true;
}
public static boolean isLowLevelDebug() {
return lowLevelDebug;
}
public boolean isModelSet() {
return medtronicPumpStatus.medtronicDeviceType != null;
}
public MedtronicDeviceType getMedtronicPumpModel() {
return medtronicPumpStatus.medtronicDeviceType;
}
public void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) {
this.medtronicPumpStatus.medtronicDeviceType = medtronicPumpModel;
}
public MedtronicCommandType getCurrentCommand() {
return this.currentCommand;
}
public void setCurrentCommand(MedtronicCommandType currentCommand) {
this.currentCommand = currentCommand;
if (currentCommand != null)
rileyLinkUtil.getRileyLinkHistory().add(new RLHistoryItemMedtronic(currentCommand));
}
public int pageNumber;
public Integer frameNumber;
public void setCurrentCommand(MedtronicCommandType currentCommand, int pageNumber_, Integer frameNumber_) {
pageNumber = pageNumber_;
frameNumber = frameNumber_;
if (this.currentCommand != currentCommand) {
setCurrentCommand(currentCommand);
}
rxBus.send(new EventRileyLinkDeviceStatusChange(medtronicPumpStatus.getPumpDeviceState()));
}
public static boolean isSame(Double d1, Double d2) {
double diff = d1 - d2;
return (Math.abs(diff) <= 0.000001);
}
public Map<String, PumpSettingDTO> getSettings() {
return settings;
}
public void setSettings(Map<String, PumpSettingDTO> settings) {
this.settings = settings;
}
public void setPumpTime(ClockDTO pumpTime) {
this.pumpTime = pumpTime;
}
public ClockDTO getPumpTime() {
return this.pumpTime;
}
}

View file

@ -0,0 +1,314 @@
package info.nightscout.androidaps.plugins.pump.medtronic.util
import com.google.gson.GsonBuilder
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.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.events.EventRileyLinkDeviceStatusChange
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.PumpSettingDTO
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.RLHistoryItemMedtronic
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.utils.resources.ResourceHelper
import org.joda.time.LocalTime
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.experimental.or
/**
* Created by andy on 5/9/18.
*/
@Singleton
class MedtronicUtil @Inject constructor(
private val aapsLogger: AAPSLogger,
private val rxBus: RxBusWrapper,
private val rileyLinkUtil: RileyLinkUtil,
private val medtronicPumpStatus: MedtronicPumpStatus
) {
private val ENVELOPE_SIZE = 4 // 0xA7 S1 S2 S3 CMD PARAM_COUNT [PARAMS]
//private MedtronicDeviceType medtronicPumpModel;
private var currentCommand: MedtronicCommandType? = null
var settings: Map<String, PumpSettingDTO>? = null
private val BIG_FRAME_LENGTH = 65
private val doneBit = 1 shl 7
var pumpTime: ClockDTO? = null
var gsonInstance = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()
fun getTimeFrom30MinInterval(interval: Int): LocalTime {
return if (interval % 2 == 0) {
LocalTime(interval / 2, 0)
} else {
LocalTime((interval - 1) / 2, 30)
}
}
fun decodeBasalInsulin(i: Int, j: Int): Double {
return decodeBasalInsulin(makeUnsignedShort(i, j))
}
fun decodeBasalInsulin(i: Int): Double {
return i.toDouble() / 40.0
}
fun getBasalStrokes(amount: Double): ByteArray {
return getBasalStrokes(amount, false)
}
fun getBasalStrokesInt(amount: Double): Int {
return getStrokesInt(amount, 40)
}
fun getBolusStrokes(amount: Double): ByteArray {
val strokesPerUnit = medtronicPumpStatus.medtronicDeviceType!!.bolusStrokes
val length: Int
val scrollRate: Int
if (strokesPerUnit >= 40) {
length = 2
// 40-stroke pumps scroll faster for higher unit values
scrollRate = if (amount > 10) 4 else if (amount > 1) 2 else 1
} else {
length = 1
scrollRate = 1
}
val strokes = (amount * (strokesPerUnit * 1.0 / (scrollRate * 1.0))).toInt() * scrollRate
return ByteUtil.fromHexString(String.format("%02x%0" + 2 * length + "x", length, strokes))
}
fun createCommandBody(input: ByteArray): ByteArray {
return ByteUtil.concat(input.size.toByte(), input)
}
fun sendNotification(notificationType: MedtronicNotificationType, resourceHelper: ResourceHelper, rxBus: RxBusWrapper) {
val notification = Notification( //
notificationType.notificationType, //
resourceHelper.gs(notificationType.resourceId), //
notificationType.notificationUrgency)
rxBus.send(EventNewNotification(notification))
}
fun sendNotification(notificationType: MedtronicNotificationType, resourceHelper: ResourceHelper, rxBus: RxBusWrapper, vararg parameters: Any?) {
val notification = Notification( //
notificationType.notificationType, //
resourceHelper.gs(notificationType.resourceId, *parameters), //
notificationType.notificationUrgency)
rxBus.send(EventNewNotification(notification))
}
fun dismissNotification(notificationType: MedtronicNotificationType, rxBus: RxBusWrapper) {
rxBus.send(EventDismissNotification(notificationType.notificationType))
}
fun buildCommandPayload(rileyLinkServiceData: RileyLinkServiceData, commandType: MedtronicCommandType, parameters: ByteArray?): ByteArray {
return buildCommandPayload(rileyLinkServiceData, commandType.commandCode, parameters)
}
fun buildCommandPayload(rileyLinkServiceData: RileyLinkServiceData, commandType: Byte, parameters: ByteArray?): ByteArray {
// A7 31 65 51 C0 00 52
val commandLength = (if (parameters == null) 2 else 2 + parameters.size).toByte()
val sendPayloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + commandLength) // + CRC_SIZE
sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN)
val serialNumberBCD = rileyLinkServiceData.pumpIDBytes
sendPayloadBuffer.put(0xA7.toByte())
sendPayloadBuffer.put(serialNumberBCD[0])
sendPayloadBuffer.put(serialNumberBCD[1])
sendPayloadBuffer.put(serialNumberBCD[2])
sendPayloadBuffer.put(commandType)
if (parameters == null) {
sendPayloadBuffer.put(0x00.toByte())
} else {
sendPayloadBuffer.put(parameters.size.toByte()) // size
for (`val` in parameters) {
sendPayloadBuffer.put(`val`)
}
}
val payload = sendPayloadBuffer.array()
aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "buildCommandPayload [%s]", ByteUtil.shortHexString(payload)))
// int crc = computeCRC8WithPolynomial(payload, 0, payload.length - 1);
// LOG.info("crc: " + crc);
// sendPayloadBuffer.put((byte) crc);
return sendPayloadBuffer.array()
}
// Note: at the moment supported only for 24 items, if you will use it for more than
// that you will need to add
fun getBasalProfileFrames(data: ByteArray): List<List<Byte>> {
var done = false
var start = 0
var frame = 1
val frames: MutableList<List<Byte>> = ArrayList()
var lastFrame = false
do {
var frameLength = BIG_FRAME_LENGTH - 1
if (start + frameLength > data.size) {
frameLength = data.size - start
}
// System.out.println("Framelength: " + frameLength);
val substring = ByteUtil.substring(data, start, frameLength)
// System.out.println("Subarray: " + ByteUtil.getCompactString(substring));
// System.out.println("Subarray Lenths: " + substring.length);
val frameData = ByteUtil.getListFromByteArray(substring)
if (isEmptyFrame(frameData)) {
var b = frame.toByte()
// b |= 0x80;
b = b or 128.toByte()
// b |= doneBit;
frameData.add(0, b)
checkAndAppenLastFrame(frameData)
lastFrame = true
done = true
} else {
frameData.add(0, frame.toByte())
}
// System.out.println("Subarray: " + ByteUtil.getCompactString(substring));
frames.add(frameData)
frame++
start += BIG_FRAME_LENGTH - 1
if (start == data.size) {
done = true
}
} while (!done)
if (!lastFrame) {
val frameData: MutableList<Byte> = ArrayList()
var b = frame.toByte()
b = b or 128.toByte()
// b |= doneBit;
frameData.add(b)
checkAndAppenLastFrame(frameData)
}
return frames
}
private fun checkAndAppenLastFrame(frameData: MutableList<Byte>) {
if (frameData.size == BIG_FRAME_LENGTH) return
val missing = BIG_FRAME_LENGTH - frameData.size
for (i in 0 until missing) {
frameData.add(0x00.toByte())
}
}
private fun isEmptyFrame(frameData: List<Byte>): Boolean {
for (frameDateEntry in frameData) {
if (frameDateEntry.toInt() != 0x00) {
return false
}
}
return true
}
val isModelSet: Boolean
get() = medtronicPumpStatus.medtronicDeviceType != null
var medtronicPumpModel: MedtronicDeviceType?
get() = medtronicPumpStatus.medtronicDeviceType
set(medtronicPumpModel) {
medtronicPumpStatus.medtronicDeviceType = medtronicPumpModel
}
fun getCurrentCommand(): MedtronicCommandType? {
return currentCommand
}
fun setCurrentCommand(currentCommandIn: MedtronicCommandType?) {
this.currentCommand = currentCommandIn
if (currentCommand != null) rileyLinkUtil.rileyLinkHistory.add(RLHistoryItemMedtronic(currentCommandIn!!))
}
var pageNumber = 0
var frameNumber: Int? = null
fun setCurrentCommand(currentCommand: MedtronicCommandType, pageNumber_: Int, frameNumber_: Int?) {
pageNumber = pageNumber_
frameNumber = frameNumber_
if (this.currentCommand !== currentCommand) {
setCurrentCommand(currentCommand)
}
rxBus.send(EventRileyLinkDeviceStatusChange(medtronicPumpStatus.pumpDeviceState))
}
companion object {
const val isLowLevelDebug = true
fun getIntervalFromMinutes(minutes: Int): Int {
return minutes / 30
}
fun makeUnsignedShort(b2: Int, b1: Int): Int {
return b2 and 0xff shl 8 or b1 and 0xff
}
@JvmStatic
fun getByteArrayFromUnsignedShort(shortValue: Int, returnFixedSize: Boolean): ByteArray {
val highByte = (shortValue shr 8 and 0xFF).toByte()
val lowByte = (shortValue and 0xFF).toByte()
return if (highByte > 0) {
createByteArray(highByte, lowByte)
} else {
if (returnFixedSize) createByteArray(highByte, lowByte) else createByteArray(lowByte)
}
}
fun createByteArray(vararg data: Byte): ByteArray {
return data
}
@JvmStatic
fun createByteArray(data: List<Byte>): ByteArray {
val array = ByteArray(data.size)
for (i in data.indices) {
array[i] = data[i]
}
return array
}
fun getBasalStrokes(amount: Double, returnFixedSize: Boolean): ByteArray {
return getStrokes(amount, 40, returnFixedSize)
}
fun getStrokes(amount: Double, strokesPerUnit: Int, returnFixedSize: Boolean): ByteArray {
val strokes = getStrokesInt(amount, strokesPerUnit)
return getByteArrayFromUnsignedShort(strokes, returnFixedSize)
}
fun getStrokesInt(amount: Double, strokesPerUnit: Int): Int {
var length = 1
var scrollRate = 1
if (strokesPerUnit >= 40) {
length = 2
// 40-stroke pumps scroll faster for higher unit values
if (amount > 10) scrollRate = 4 else if (amount > 1) scrollRate = 2
}
var strokes = (amount * (strokesPerUnit / (scrollRate * 1.0))).toInt()
strokes *= scrollRate
return strokes
}
@JvmStatic
fun isSame(d1: Double, d2: Double): Boolean {
val diff = d1 - d2
return Math.abs(diff) <= 0.000001
}
}
}

View file

@ -95,6 +95,9 @@
<string name="medtronic_cmd_desc_get_history">Get History - Page %1$d (%2$d/16)</string> <string name="medtronic_cmd_desc_get_history">Get History - Page %1$d (%2$d/16)</string>
<string name="medtronic_cmd_desc_get_history_request">Get History - Page %1$d</string> <string name="medtronic_cmd_desc_get_history_request">Get History - Page %1$d</string>
<string name="medtronic_cmd_desc_get_time">Get Pump Time</string> <string name="medtronic_cmd_desc_get_time">Get Pump Time</string>
<string name="medtronic_cmd_desc_set_time">Set Pump Time</string>
<string name="medtronic_cmd_desc_get_battery_status">Get Battery Status</string>
<string name="medtronic_cmd_desc_get_settings">Get Settings</string> <string name="medtronic_cmd_desc_get_settings">Get Settings</string>
<string name="medtronic_cmd_desc_get_model">Get Pump Model</string> <string name="medtronic_cmd_desc_get_model">Get Pump Model</string>
<string name="medtronic_cmd_desc_get_basal_profile">Get Basal Profile</string> <string name="medtronic_cmd_desc_get_basal_profile">Get Basal Profile</string>
@ -115,8 +118,7 @@
<string name="key_set_neutral_temps" translatable="false">set_neutral_temps</string> <string name="key_set_neutral_temps" translatable="false">set_neutral_temps</string>
<string name="set_neutral_temps_title">Set neutral temp basals</string> <string name="set_neutral_temps_title">Set neutral temp basals</string>
<string name="set_neutral_temps_summary">If enabled, it will cancel a temporary basal before the end of each hour. This method can help stop some pumps beeping/vibrating on the hour.</string> <string name="set_neutral_temps_summary">If enabled, it will cancel a temporary basal before the end of each hour. This method can help stop some pumps beeping/vibrating on the hour.</string>
<string name="mdt_tbr_remaining">%1$.1f U/h (%2$d min remaining)</string>
<string name="sixdigitnumber" translatable="false">^\\d{6}</string> <string name="sixdigitnumber" translatable="false">^\\d{6}</string>
</resources> </resources>

View file

@ -186,22 +186,6 @@ public class ByteUtil {
} }
// public static byte[] fromByteList(List<Byte> byteArray) {
// byte[] rval = new byte[byteArray.size()];
// for (int i = 0; i < byteArray.size(); i++) {
// rval[i] = byteArray.get(i);
// }
// return rval;
// }
// public static List<Byte> toByteList(byte[] data) {
// ArrayList<Byte> rval = new ArrayList<>(data.length);
// for (int i = 0; i < data.length; i++) {
// rval.add(i, new Byte(data[i]));
// }
// return rval;
// }
public static List<Byte> getListFromByteArray(byte[] array) { public static List<Byte> getListFromByteArray(byte[] array) {
List<Byte> listOut = new ArrayList<Byte>(); List<Byte> listOut = new ArrayList<Byte>();
@ -340,6 +324,9 @@ public class ByteUtil {
return toInt(b1, b2, b3, null, BitConversion.BIG_ENDIAN); return toInt(b1, b2, b3, null, BitConversion.BIG_ENDIAN);
} }
public static int toInt(Byte b1, Byte b2, Byte b3) {
return toInt(b1, b2, b3, null, BitConversion.BIG_ENDIAN);
}
public static int toInt(int b1, int b2, BitConversion flag) { public static int toInt(int b1, int b2, BitConversion flag) {
return toInt(b1, b2, null, null, flag); return toInt(b1, b2, null, null, flag);