From bcc767211686496b87202fc6d48268e3de47ec5f Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 14 Apr 2021 16:06:33 +0100 Subject: [PATCH 01/39] - starting pumpSync changes --- .../pump/common/PumpPluginAbstract.java | 39 ++++++++++++++++++- .../plugins/pump/common/data/PumpDbEntry.java | 21 ++++++++++ .../pump/medtronic/MedtronicPumpPlugin.java | 27 ++++++++++--- 3 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java index b6bc68a47a..b9e1f4f387 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java @@ -10,6 +10,8 @@ import org.json.JSONException; import org.json.JSONObject; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.core.R; @@ -27,11 +29,13 @@ 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; @@ -69,6 +73,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI protected boolean displayConnectionMessages = false; protected PumpType pumpType; protected AapsSchedulers aapsSchedulers; + protected PumpSync pumpSync; protected PumpPluginAbstract( @@ -84,7 +89,8 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI Context context, FabricPrivacy fabricPrivacy, DateUtil dateUtil, - AapsSchedulers aapsSchedulers + AapsSchedulers aapsSchedulers, + PumpSync pumpSync ) { super(pluginDescription, injector, aapsLogger, resourceHelper, commandQueue); @@ -101,6 +107,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI this.pumpType = pumpType; this.dateUtil = dateUtil; this.aapsSchedulers = aapsSchedulers; + this.pumpSync = pumpSync; } @@ -335,6 +342,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI } catch (Exception ignored) { } + // TODO fix TemporaryBasal tb = activePlugin.getActiveTreatments().getTempBasalFromHistory(System.currentTimeMillis()); if (tb != null) { extended.put("TempBasalAbsoluteRate", @@ -343,6 +351,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes()); } + // TODO fix ExtendedBolus eb = activePlugin.getActiveTreatments().getExtendedBolusFromHistory(System.currentTimeMillis()); if (eb != null) { extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate()); @@ -377,10 +386,12 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().lastBolusAmount) + "U @" + // android.text.format.DateFormat.format("HH:mm", getPumpStatusData().lastBolusTime) + "\n"; } + // TODO fix TemporaryBasal activeTemp = activePlugin.getActiveTreatments().getRealTempBasalFromHistory(System.currentTimeMillis()); if (activeTemp != null) { ret += "Temp: " + activeTemp.toStringFull() + "\n"; } + // TODO fix ExtendedBolus activeExtendedBolus = activePlugin.getActiveTreatments().getExtendedBolusFromHistory( System.currentTimeMillis()); if (activeExtendedBolus != null) { @@ -413,6 +424,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI //if (MedtronicHistoryData.doubleBolusDebug) // aapsLogger.debug("DoubleBolusDebug: deliverTreatment::(carb only entry)"); + // TODO fix // no bolus required, carb only treatment activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true); @@ -471,4 +483,29 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements PumpI private PumpEnactResult getOperationNotSupportedWithCustomText(int resourceId) { return new PumpEnactResult(getInjector()).success(false).enacted(false).comment(resourceId); } + + // PumpSync + + Map 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); + } + + } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java new file mode 100644 index 0000000000..f67a9741f8 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.plugins.pump.common.data; + +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; + +public class PumpDbEntry { + + long temporaryId; + PumpType pumpType; + String serialNumber; + DetailedBolusInfo detailedBolusInfo; + + public PumpDbEntry(long temporaryId, PumpType pumpType, String serialNumber, DetailedBolusInfo detailedBolusInfo) { + this.temporaryId = temporaryId; + this.pumpType = pumpType; + this.serialNumber = serialNumber; + this.detailedBolusInfo = detailedBolusInfo; + } + + +} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java index 48cdc84322..efc0a8c117 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -40,6 +40,7 @@ import info.nightscout.androidaps.interfaces.CommandQueueProvider; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.PumpInterface; +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; @@ -98,7 +99,6 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP; @Singleton public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInterface, RileyLinkPumpDevice { - private final SP sp; private final MedtronicUtil medtronicUtil; private final MedtronicPumpStatus medtronicPumpStatus; private final MedtronicHistoryData medtronicHistoryData; @@ -117,7 +117,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter public static boolean isBusy = false; private final List busyTimestamps = new ArrayList<>(); private boolean hasTimeDateOrTimeZoneChanged = false; - + private boolean usePumpSync = false; @Inject public MedtronicPumpPlugin( @@ -136,7 +136,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter RileyLinkServiceData rileyLinkServiceData, ServiceTaskExecutor serviceTaskExecutor, DateUtil dateUtil, - AapsSchedulers aapsSchedulers + AapsSchedulers aapsSchedulers, + PumpSync pumpSync ) { super(new PluginDescription() // @@ -148,11 +149,10 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter .preferencesId(R.xml.pref_medtronic) .description(R.string.description_pump_medtronic), // PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later - injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers + injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync ); this.medtronicUtil = medtronicUtil; - this.sp = sp; this.medtronicPumpStatus = medtronicPumpStatus; this.medtronicHistoryData = medtronicHistoryData; this.rileyLinkServiceData = rileyLinkServiceData; @@ -733,6 +733,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter rxBus.send(new EventMedtronicPumpValuesChanged()); } + @Override public long generateTempId(long timeMillis) { + return 0; + } + + @Override public String getSerial() { + return null; + } + private BolusDeliveryType bolusDeliveryType = BolusDeliveryType.Idle; private enum BolusDeliveryType { @@ -878,7 +886,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter detailedBolusInfo.timestamp = now; detailedBolusInfo.deliverAtTheLatest = now; // not sure about that one - activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true); + // TODO fix + if (usePumpSync) { + addBolusWithTempId(detailedBolusInfo, true); + } else { + activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true); + } // we subtract insulin, exact amount will be visible with next remainingInsulin update. medtronicPumpStatus.reservoirRemainingUnits -= detailedBolusInfo.insulin; @@ -1044,6 +1057,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter .absolute(absoluteRate) // .source(Source.USER); + // TODO fix activePlugin.getActiveTreatments().addToHistoryTempBasal(tempStart); incrementStatistics(MedtronicConst.Statistics.TBRsSet); @@ -1391,6 +1405,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter .duration(0) // .source(Source.USER); + // TODO fix activePlugin.getActiveTreatments().addToHistoryTempBasal(tempBasal); return new PumpEnactResult(getInjector()).success(true).enacted(true) // From 769ab218d4c5228093883efeb9f7057697533cd9 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Fri, 16 Apr 2021 17:11:00 +0100 Subject: [PATCH 02/39] - kotlinizing mdt --- .../pump/common/PumpPluginAbstract.java.orig | 535 +++++++++++++ .../comm/history/MedtronicHistoryDecoder.java | 182 ----- .../comm/history/MedtronicHistoryDecoder.kt | 132 ++++ .../MedtronicHistoryDecoderInterface.java | 15 - .../MedtronicHistoryDecoderInterface.kt | 10 + .../comm/history/MedtronicHistoryEntry.java | 316 -------- .../comm/history/MedtronicHistoryEntry.kt | 222 ++++++ .../MedtronicHistoryEntryInterface.java | 16 - .../history/MedtronicHistoryEntryInterface.kt | 11 + .../comm/history/RawHistoryPage.java | 87 --- .../medtronic/comm/history/RawHistoryPage.kt | 61 ++ .../comm/history/RecordDecodeStatus.java | 30 - .../comm/history/RecordDecodeStatus.kt | 19 + .../comm/history/cgms/CGMSHistoryEntry.java | 92 --- .../comm/history/cgms/CGMSHistoryEntry.kt | 55 ++ .../history/cgms/CGMSHistoryEntryType.java | 135 ---- .../comm/history/cgms/CGMSHistoryEntryType.kt | 62 ++ .../cgms/MedtronicCGMSHistoryDecoder.java | 469 ------------ .../cgms/MedtronicCGMSHistoryDecoder.kt | 269 +++++++ .../pump/MedtronicPumpHistoryDecoder.java | 724 ------------------ .../pump/MedtronicPumpHistoryDecoder.kt | 502 ++++++++++++ .../comm/history/pump/PumpHistoryEntry.java | 174 ----- .../comm/history/pump/PumpHistoryEntry.kt | 117 +++ .../history/pump/PumpHistoryEntryType.java | 378 --------- .../comm/history/pump/PumpHistoryEntryType.kt | 323 ++++++++ .../comm/history/pump/PumpHistoryResult.java | 177 ----- .../comm/history/pump/PumpHistoryResult.kt | 144 ++++ .../medtronic/data/dto/DailyTotalsDTO.java | 16 +- .../dialog/MedtronicHistoryActivity.java | 4 +- .../common/defs/PumpHistoryEntryGroup.java | 66 -- .../pump/common/defs/PumpHistoryEntryGroup.kt | 50 ++ .../plugins/pump/common/utils/ByteUtil.java | 69 +- 32 files changed, 2590 insertions(+), 2872 deletions(-) create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt delete mode 100644 rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.java create mode 100644 rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig new file mode 100644 index 0000000000..a0bffe268a --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig @@ -0,0 +1,535 @@ +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 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); + } + + +} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java deleted file mode 100644 index 2b33249503..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.java +++ /dev/null @@ -1,182 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; - -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.inject.Inject; - -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.common.utils.StringUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - - -/** - * 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} - */ - -public abstract class MedtronicHistoryDecoder implements MedtronicHistoryDecoderInterface { - - @Inject protected AAPSLogger aapsLogger; - @Inject protected MedtronicUtil medtronicUtil; - - protected ByteUtil bitUtils; - - // STATISTICS (remove at later time or not) - protected boolean statisticsEnabled = true; - protected Map unknownOpCodes; - protected Map> mapStatistics; - - - public MedtronicHistoryDecoder() { - } - - - // public abstract Class getHistoryEntryClass(); - - // public abstract RecordDecodeStatus decodeRecord(T record); - - public abstract void postProcess(); - - - protected abstract void runPostDecodeTasks(); - - - // TODO_ extend this to also use bigger pages (for now we support only 1024 pages) - private List checkPage(RawHistoryPage page, boolean partial) throws RuntimeException { - List byteList = new ArrayList(); - - // if (!partial && page.getData().length != 1024 /* page.commandType.getRecordLength() */) { - // LOG.error("Page size is not correct. Size should be {}, but it was {} instead.", 1024, - // page.getData().length); - // // throw exception perhaps - // return byteList; - // } - - if (medtronicUtil.getMedtronicPumpModel() == null) { - aapsLogger.error(LTag.PUMPCOMM, "Device Type is not defined."); - return byteList; - } - - if (page.getData().length != 1024) { - return ByteUtil.getListFromByteArray(page.getData()); - } else if (page.isChecksumOK()) { - return ByteUtil.getListFromByteArray(page.getOnlyData()); - } else { - return null; - } - } - - - public List processPageAndCreateRecords(RawHistoryPage rawHistoryPage) { - return processPageAndCreateRecords(rawHistoryPage, false); - } - - - protected void prepareStatistics() { - if (!statisticsEnabled) - return; - - unknownOpCodes = new HashMap<>(); - mapStatistics = new HashMap<>(); - - for (RecordDecodeStatus stat : RecordDecodeStatus.values()) { - mapStatistics.put(stat, new HashMap<>()); - } - } - - - protected void addToStatistics(MedtronicHistoryEntryInterface pumpHistoryEntry, RecordDecodeStatus status, Integer opCode) { - if (!statisticsEnabled) - return; - - if (opCode != null) { - if (!unknownOpCodes.containsKey(opCode)) { - unknownOpCodes.put(opCode, opCode); - } - return; - } - - if (!mapStatistics.get(status).containsKey(pumpHistoryEntry.getEntryTypeName())) { - mapStatistics.get(status).put(pumpHistoryEntry.getEntryTypeName(), ""); - } - } - - - protected void showStatistics() { - StringBuilder sb = new StringBuilder(); - - for (Map.Entry unknownEntry : unknownOpCodes.entrySet()) { - StringUtil.appendToStringBuilder(sb, "" + unknownEntry.getKey(), ", "); - } - - aapsLogger.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE"); - - if (unknownOpCodes.size() > 0) { - aapsLogger.warn(LTag.PUMPCOMM, "Unknown Op Codes: " + sb.toString()); - } - - for (Map.Entry> entry : mapStatistics.entrySet()) { - sb = new StringBuilder(); - - if (entry.getKey() != RecordDecodeStatus.OK) { - if (entry.getValue().size() == 0) - continue; - - for (Map.Entry entrysub : entry.getValue().entrySet()) { - StringUtil.appendToStringBuilder(sb, entrysub.getKey(), ", "); - } - - String spaces = StringUtils.repeat(" ", 14 - entry.getKey().name().length()); - - aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s%s - %d. Elements: %s", entry.getKey().name(), spaces, entry.getValue().size(), sb.toString())); - } else { - aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s - %d", entry.getKey().name(), entry.getValue().size())); - } - } - } - - - private int getUnsignedByte(byte value) { - if (value < 0) - return value + 256; - else - return value; - } - - - protected int getUnsignedInt(int value) { - if (value < 0) - return value + 256; - else - return value; - } - - - public String getFormattedFloat(float value, int decimals) { - return StringUtil.getFormatedValueUS(value, decimals); - } - - - private List processPageAndCreateRecords(RawHistoryPage rawHistoryPage, boolean partial) { - List dataClear = checkPage(rawHistoryPage, partial); - List records = createRecords(dataClear); - - for (T record : records) { - decodeRecord(record); - } - - runPostDecodeTasks(); - - return records; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt new file mode 100644 index 0000000000..a6a8744299 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -0,0 +1,132 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history + +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.common.utils.StringUtil +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import org.apache.commons.lang3.StringUtils +import java.util.* +import javax.inject.Inject +import kotlin.jvm.Throws + +/** + * 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} + */ +abstract class MedtronicHistoryDecoder : MedtronicHistoryDecoderInterface { + + @JvmField @Inject + var aapsLogger: AAPSLogger? = null + + @JvmField @Inject + var medtronicUtil: MedtronicUtil? = null + protected var bitUtils: ByteUtil? = null + + // STATISTICS (remove at later time or not) + protected var statisticsEnabled = true + @JvmField protected var unknownOpCodes: MutableMap? = null + protected var mapStatistics: MutableMap>? = null + + // public abstract Class getHistoryEntryClass(); + // public abstract RecordDecodeStatus decodeRecord(T record); + abstract fun postProcess() + protected abstract fun runPostDecodeTasks() + + // TODO_ extend this to also use bigger pages (for now we support only 1024 pages) + @Throws(RuntimeException::class) + private fun checkPage(page: RawHistoryPage, partial: Boolean): List { + val byteList: List = ArrayList() + + if (medtronicUtil!!.medtronicPumpModel == null) { + aapsLogger!!.error(LTag.PUMPCOMM, "Device Type is not defined.") + return byteList + } + return if (page.data.size != 1024) { + ByteUtil.getListFromByteArray(page.data) + } else if (page.isChecksumOK) { + ByteUtil.getListFromByteArray(page.onlyData) + } else { + byteList + } + } + + fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): List? { + return processPageAndCreateRecords(rawHistoryPage, false) + } + + protected fun prepareStatistics() { + if (!statisticsEnabled) return + unknownOpCodes = HashMap() + mapStatistics = HashMap() + for (stat in RecordDecodeStatus.values()) { + (mapStatistics as HashMap>)[stat] = HashMap() + } + } + + protected fun addToStatistics(pumpHistoryEntry: MedtronicHistoryEntryInterface, status: RecordDecodeStatus?, opCode: Int?) { + if (!statisticsEnabled) return + if (opCode != null) { + if (!unknownOpCodes!!.containsKey(opCode)) { + unknownOpCodes!![opCode] = opCode + } + return + } + if (!mapStatistics!![status]!!.containsKey(pumpHistoryEntry.entryTypeName)) { + mapStatistics!![status]!!.put(pumpHistoryEntry.entryTypeName!!, "") + } + } + + protected fun showStatistics() { + var sb = StringBuilder() + for ((key) in unknownOpCodes!!) { + StringUtil.appendToStringBuilder(sb, "" + key, ", ") + } + aapsLogger!!.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE") + if (unknownOpCodes!!.size > 0) { + aapsLogger!!.warn(LTag.PUMPCOMM, "Unknown Op Codes: $sb") + } + for ((key, value) in mapStatistics!!) { + sb = StringBuilder() + if (key !== RecordDecodeStatus.OK) { + if (value.size == 0) continue + for ((key1) in value) { + StringUtil.appendToStringBuilder(sb, key1, ", ") + } + 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())) + } else { + aapsLogger!!.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s - %d", key.name, value.size)) + } + } + } + + private fun getUnsignedByte(value: Byte): Int { + return if (value < 0) value + 256 else value.toInt() + } + + protected fun getUnsignedInt(value: Int): Int { + return if (value < 0) value + 256 else value + } + + protected fun getUnsignedInt(value: Byte): Int { + return if (value < 0) value + 256 else value.toInt() + } + + fun getFormattedFloat(value: Float, decimals: Int): String { + return StringUtil.getFormatedValueUS(value, decimals) + } + + private fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage, partial: Boolean): List { + val dataClear = checkPage(rawHistoryPage, partial) + val records: List = createRecords(dataClear) + for (record in records!!) { + decodeRecord(record) + } + runPostDecodeTasks() + return records + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java deleted file mode 100644 index b98b2d7d33..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.java +++ /dev/null @@ -1,15 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; - -import java.util.List; - -/** - * Created by andy on 3/10/19. - */ - -public interface MedtronicHistoryDecoderInterface { - - RecordDecodeStatus decodeRecord(T record); - - List createRecords(List dataClear); - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt new file mode 100644 index 0000000000..1137371843 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history + +/** + * Created by andy on 3/10/19. + */ +interface MedtronicHistoryDecoderInterface { + + fun decodeRecord(record: T): RecordDecodeStatus? + fun createRecords(dataClear: List): List +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java deleted file mode 100644 index b5d41f6bfa..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.java +++ /dev/null @@ -1,316 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; - -import com.google.gson.annotations.Expose; - -import org.slf4j.Logger; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import info.nightscout.androidaps.logging.StacktraceLoggerWrapper; -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; - -/** - * 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} - */ - -public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInterface { - - protected List rawData; - - public static final Logger LOG = StacktraceLoggerWrapper.getLogger(MedtronicHistoryEntry.class); - - protected int[] sizes = new int[3]; - - protected byte[] head; - protected byte[] datetime; - protected byte[] body; - - // protected LocalDateTime dateTime; - - public long id; - - @Expose - public String DT; - - @Expose - public Long atechDateTime; - - @Expose - protected Map decodedData; - - public long phoneDateTime; // time on phone - - /** - * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) - */ - protected Long pumpId; - - /** - * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's - * are not actually - * linked)) - */ - public boolean linked = false; - - /** - * Linked object, see linked - */ - public Object linkedObject = null; - - - public void setLinkedObject(Object linkedObject) { - this.linked = true; - this.linkedObject = linkedObject; - } - - - public void setData(List listRawData, boolean doNotProcess) { - this.rawData = listRawData; - - // System.out.println("Head: " + sizes[0] + ", dates: " + sizes[1] + - // ", body=" + sizes[2]); - - if (doNotProcess) - return; - - head = new byte[getHeadLength() - 1]; - for (int i = 1; i < (getHeadLength()); i++) { - head[i - 1] = listRawData.get(i); - } - - if (getDateTimeLength() > 0) { - datetime = new byte[getDateTimeLength()]; - - for (int i = getHeadLength(), j = 0; j < getDateTimeLength(); i++, j++) { - datetime[j] = listRawData.get(i); - } - } - - if (getBodyLength() > 0) { - body = new byte[getBodyLength()]; - - for (int i = (getHeadLength() + getDateTimeLength()), j = 0; j < getBodyLength(); i++, j++) { - body[j] = listRawData.get(i); - } - - } - - } - - - public String getDateTimeString() { - return this.DT == null ? "Unknown" : this.DT; - } - - - public String getDecodedDataAsString() { - if (decodedData == null) - if (isNoDataEntry()) - return "No data"; - else - return ""; - else - return decodedData.toString(); - } - - - public boolean hasData() { - return (decodedData != null) || (isNoDataEntry()) || getEntryTypeName().equals("UnabsorbedInsulin"); - } - - - public boolean isNoDataEntry() { - return (sizes[0] == 2 && sizes[1] == 5 && sizes[2] == 0); - } - - - public Map getDecodedData() { - return this.decodedData; - } - - - public Object getDecodedDataEntry(String key) { - return this.decodedData != null ? this.decodedData.get(key) : null; - } - - - public boolean hasDecodedDataEntry(String key) { - return this.decodedData.containsKey(key); - } - - - public boolean showRaw() { - return getEntryTypeName().equals("EndResultTotals"); - } - - - public int getHeadLength() { - return sizes[0]; - } - - - public int getDateTimeLength() { - return sizes[1]; - } - - - public int getBodyLength() { - return sizes[2]; - } - - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - if (this.DT == null) { - LOG.error("DT is null. RawData=" + ByteUtil.getHex(this.rawData)); - } - - sb.append(getToStringStart()); - sb.append(", DT: " + (this.DT == null ? "null" : StringUtil.getStringInLength(this.DT, 19))); - sb.append(", length="); - sb.append(getHeadLength()); - sb.append(","); - sb.append(getDateTimeLength()); - sb.append(","); - sb.append(getBodyLength()); - sb.append("("); - sb.append((getHeadLength() + getDateTimeLength() + getBodyLength())); - sb.append(")"); - - boolean hasData = hasData(); - - if (hasData) { - sb.append(", data=" + getDecodedDataAsString()); - } - - if (hasData && !showRaw()) { - sb.append("]"); - return sb.toString(); - } - - if (head != null) { - sb.append(", head="); - sb.append(ByteUtil.shortHexString(this.head)); - } - - if (datetime != null) { - sb.append(", datetime="); - sb.append(ByteUtil.shortHexString(this.datetime)); - } - - if (body != null) { - sb.append(", body="); - sb.append(ByteUtil.shortHexString(this.body)); - } - - sb.append(", rawData="); - sb.append(ByteUtil.shortHexString(this.rawData)); - sb.append("]"); - - // sb.append(" DT: "); - // sb.append(this.dateTime == null ? " - " : this.dateTime.toString("dd.MM.yyyy HH:mm:ss")); - - // sb.append(" Ext: "); - - return sb.toString(); - } - - - public abstract int getOpCode(); - - - public abstract String getToStringStart(); - - - public List getRawData() { - return rawData; - } - - - public byte getRawDataByIndex(int index) { - return rawData.get(index); - } - - - public int getUnsignedRawDataByIndex(int index) { - return ByteUtil.convertUnsignedByteToInt(rawData.get(index)); - } - - - public void setRawData(List rawData) { - this.rawData = rawData; - } - - - public byte[] getHead() { - return head; - } - - - public void setHead(byte[] head) { - this.head = head; - } - - - public byte[] getDatetime() { - return datetime; - } - - - public void setDatetime(byte[] datetime) { - this.datetime = datetime; - } - - - public byte[] getBody() { - return body; - } - - - public void setBody(byte[] body) { - this.body = body; - } - - - public void setAtechDateTime(long dt) { - this.atechDateTime = dt; - this.DT = DateTimeUtil.toString(this.atechDateTime); - } - - - public void addDecodedData(String key, Object value) { - if (decodedData == null) - decodedData = new HashMap<>(); - - decodedData.put(key, value); - } - - - public String toShortString() { - if (head == null) { - return "Unidentified record. "; - } else { - return "HistoryRecord: head=[" + ByteUtil.shortHexString(this.head) + "]"; - } - } - - public boolean containsDecodedData(String key) { - if (decodedData == null) - return false; - - return decodedData.containsKey(key); - } - - // if we extend to CGMS this need to be changed back - // public abstract PumpHistoryEntryType getEntryType(); - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt new file mode 100644 index 0000000000..72e3174178 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -0,0 +1,222 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history + +import android.util.Log +import com.google.gson.annotations.Expose +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 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} + */ +abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { + + @JvmField var rawData: List? = null + @JvmField protected var sizes = IntArray(3) + var head: ByteArray? = null + var datetime: ByteArray? = null + var body: ByteArray? = null + + // protected LocalDateTime dateTime; + @JvmField var id: Long = 0 + + @JvmField @Expose + var DT: String? = null + + @JvmField @Expose + var atechDateTime: Long? = null + + @Expose + protected var decodedData: MutableMap? = null + var phoneDateTime // time on phone + : Long = 0 + + /** + * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) + */ + protected open var pumpId: Long? = null + + /** + * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's + * are not actually + * linked)) + */ + var linked = false + + /** + * Linked object, see linked + */ + var linkedObject: Any? = null + get() = field //= linkedObject + set(value) { + linked = true + field = value + } + + // fun setLinkedObject(linkedObject: Any?) { + // linked = true + // this.linkedObject = linkedObject + // } + + override fun setData(listRawData: List?, doNotProcess: Boolean) { + rawData = listRawData + + // System.out.println("Head: " + sizes[0] + ", dates: " + sizes[1] + + // ", body=" + sizes[2]); + if (!doNotProcess) { + head = ByteArray(headLength - 1) + for (i in 1 until headLength) { + head!![i - 1] = listRawData!![i]!! + } + if (dateTimeLength > 0) { + datetime = ByteArray(dateTimeLength) + var i = headLength + var j = 0 + while (j < dateTimeLength) { + datetime!![j] = listRawData!![i]!! + i++ + j++ + } + } + if (bodyLength > 0) { + body = ByteArray(bodyLength) + var i = headLength + dateTimeLength + var j = 0 + while (j < bodyLength) { + body!![j] = listRawData!![i]!! + i++ + j++ + } + } + } + return + } + + val dateTimeString: String + get() = if (DT == null) "Unknown" else DT!! + + val decodedDataAsString: String + get() = if (decodedData == null) if (isNoDataEntry) "No data" else "" else decodedData.toString() + + fun hasData(): Boolean { + return decodedData != null || isNoDataEntry || entryTypeName == "UnabsorbedInsulin" + } + + val isNoDataEntry: Boolean + get() = sizes[0] == 2 && sizes[1] == 5 && sizes[2] == 0 + + // fun getDecodedData(): Map? { + // return decodedData + // } + + fun getDecodedDataEntry(key: String?): Any? { + return if (decodedData != null) decodedData!![key] else null + } + + fun hasDecodedDataEntry(key: String?): Boolean { + return decodedData!!.containsKey(key) + } + + fun showRaw(): Boolean { + return entryTypeName == "EndResultTotals" + } + + val headLength: Int + get() = sizes[0] + + val dateTimeLength: Int + get() = sizes[1] + + val bodyLength: Int + get() = sizes[2] + + override fun toString(): String { + val sb = StringBuilder() + if (DT == null) { + Log.e("", "DT is null. RawData=" + ByteUtil.getHex(rawData)) + } + sb.append(toStringStart) + sb.append(", DT: " + if (DT == null) "null" else StringUtil.getStringInLength(DT, 19)) + sb.append(", length=") + sb.append(headLength) + sb.append(",") + sb.append(dateTimeLength) + sb.append(",") + sb.append(bodyLength) + sb.append("(") + sb.append(headLength + dateTimeLength + bodyLength) + sb.append(")") + val hasData = hasData() + if (hasData) { + sb.append(", data=$decodedDataAsString") + } + if (hasData && !showRaw()) { + sb.append("]") + return sb.toString() + } + if (head != null) { + sb.append(", head=") + sb.append(ByteUtil.shortHexString(head)) + } + if (datetime != null) { + sb.append(", datetime=") + sb.append(ByteUtil.shortHexString(datetime)) + } + if (body != null) { + sb.append(", body=") + sb.append(ByteUtil.shortHexString(body)) + } + sb.append(", rawData=") + sb.append(ByteUtil.shortHexString(rawData)) + sb.append("]") + + // sb.append(" DT: "); + // sb.append(this.dateTime == null ? " - " : this.dateTime.toString("dd.MM.yyyy HH:mm:ss")); + + // sb.append(" Ext: "); + return sb.toString() + } + + abstract val opCode: Byte? + abstract val toStringStart: String? + + fun getRawDataByIndex(index: Int): Byte { + return rawData!![index] + } + + fun getRawDataByIndexInt(index: Int): Int { + return rawData!![index].toInt() + } + + fun getUnsignedRawDataByIndex(index: Int): Int { + return ByteUtil.convertUnsignedByteToInt(rawData!![index]) + } + + fun setAtechDateTime(dt: Long) { + atechDateTime = dt + DT = DateTimeUtil.toString(atechDateTime!!) + } + + fun addDecodedData(key: String, value: Any?) { + if (decodedData == null) decodedData = HashMap() + decodedData!![key] = value + } + + fun toShortString(): String { + return if (head == null) { + "Unidentified record. " + } else { + "HistoryRecord: head=[" + ByteUtil.shortHexString(head) + "]" + } + } + + fun containsDecodedData(key: String?): Boolean { + return if (decodedData == null) false else decodedData!!.containsKey(key) + } // if we extend to CGMS this need to be changed back + // public abstract PumpHistoryEntryType getEntryType(); +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java deleted file mode 100644 index 38b7e1dbeb..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; - -import java.util.List; - -/** - * Created by andy on 7/24/18. - */ -public interface MedtronicHistoryEntryInterface { - - String getEntryTypeName(); - - void setData(List listRawData, boolean doNotProcess); - - int getDateLength(); - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt new file mode 100644 index 0000000000..32f6d4458a --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history + +/** + * Created by andy on 7/24/18. + */ +interface MedtronicHistoryEntryInterface { + + val entryTypeName: String? + fun setData(listRawData: List?, doNotProcess: Boolean) + val dateLength: Int +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java deleted file mode 100644 index 182e09b1bd..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.java +++ /dev/null @@ -1,87 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; - -import java.util.Arrays; -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.common.utils.CRC; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - -/** - * Created by geoff on 6/4/16. - */ -public class RawHistoryPage { - - private final AAPSLogger aapsLogger; - - private byte[] data = new byte[0]; - - - public RawHistoryPage(AAPSLogger aapsLogger) { - this.aapsLogger = aapsLogger; - } - - - public void appendData(byte[] newdata) { - data = ByteUtil.concat(data, newdata); - } - - - public byte[] getData() { - return data; - } - - - byte[] getOnlyData() { - return Arrays.copyOfRange(data, 0, 1022); - } - - - public int getLength() { - return data.length; - } - - - public boolean isChecksumOK() { - if (getLength() != 1024) { - return false; - } - byte[] computedCRC = CRC.calculate16CCITT(ByteUtil.substring(data, 0, 1022)); - - int crcCalculated = ByteUtil.toInt(computedCRC[0], computedCRC[1]); - int crcStored = ByteUtil.toInt(data[1022], data[1023]); - - if (crcCalculated != crcStored) { - aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Stored CRC (%d) is different than calculated (%d), but ignored for now.", crcStored, - crcCalculated)); - } else { - if (MedtronicUtil.isLowLevelDebug()) - aapsLogger.debug(LTag.PUMPBTCOMM, "CRC ok."); - } - - return crcCalculated == crcStored; - } - - - public void dumpToDebug() { - int linesize = 80; - int offset = 0; - - StringBuilder sb = new StringBuilder(); - - while (offset < data.length) { - int bytesToLog = linesize; - if (offset + linesize > data.length) { - bytesToLog = data.length - offset; - } - sb.append(ByteUtil.shortHexString(ByteUtil.substring(data, offset, bytesToLog)) + " "); - // sb.append("\n"); - - offset += linesize; - } - - aapsLogger.info(LTag.PUMPBTCOMM, "History Page Data:\n" + sb.toString()); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt new file mode 100644 index 0000000000..792120b688 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt @@ -0,0 +1,61 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history + +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.common.utils.CRC +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import java.util.* + +/** + * Created by geoff on 6/4/16. + */ +class RawHistoryPage(private val aapsLogger: AAPSLogger) { + + var data = ByteArray(0) + private set + + fun appendData(newdata: ByteArray?) { + data = ByteUtil.concat(data, newdata) + } + + val onlyData: ByteArray + get() = Arrays.copyOfRange(data, 0, 1022) + + val length: Int + get() = data.size + + val isChecksumOK: Boolean + get() { + if (length != 1024) { + return false + } + val computedCRC = CRC.calculate16CCITT(ByteUtil.substring(data, 0, 1022)) + val crcCalculated = ByteUtil.toInt(computedCRC[0].toInt(), computedCRC[1].toInt()) + val crcStored = ByteUtil.toInt(data[1022].toInt(), data[1023].toInt()) + if (crcCalculated != crcStored) { + aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Stored CRC (%d) is different than calculated (%d), but ignored for now.", crcStored, + crcCalculated)) + } else { + if (MedtronicUtil.isLowLevelDebug()) aapsLogger.debug(LTag.PUMPBTCOMM, "CRC ok.") + } + return crcCalculated == crcStored + } + + fun dumpToDebug() { + val linesize = 80 + var offset = 0 + val sb = StringBuilder() + while (offset < data.size) { + var bytesToLog = linesize + if (offset + linesize > data.size) { + bytesToLog = data.size - offset + } + sb.append(ByteUtil.shortHexString(ByteUtil.substring(data, offset, bytesToLog)) + " ") + // sb.append("\n"); + offset += linesize + } + aapsLogger.info(LTag.PUMPBTCOMM, "History Page Data:\n$sb") + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java deleted file mode 100644 index 18cb02cfad..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.java +++ /dev/null @@ -1,30 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history; - -/** - * 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} - */ - -public enum RecordDecodeStatus { - OK("OK "), // - Ignored("IGNORE "), // - NotSupported("N/A YET"), // - Error("ERROR "), // - WIP("WIP "), // - Unknown("UNK "); - - String description; - - - RecordDecodeStatus(String description) { - this.description = description; - - } - - - public String getDescription() { - return description; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.kt new file mode 100644 index 0000000000..82194b1f03 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RecordDecodeStatus.kt @@ -0,0 +1,19 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history + +/** + * 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 RecordDecodeStatus(var description: String) { + + OK("OK "), // + Ignored("IGNORE "), // + NotSupported("N/A YET"), // + Error("ERROR "), // + WIP("WIP "), // + Unknown("UNK "); + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java deleted file mode 100644 index 4d35426fb8..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.java +++ /dev/null @@ -1,92 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.LocalDateTime; - -import java.util.List; - -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry; - -/** - * 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} - */ - -public class CGMSHistoryEntry extends MedtronicHistoryEntry { - - private CGMSHistoryEntryType entryType; - private Integer opCode; // this is set only when we have unknown entry... - - - public CGMSHistoryEntryType getEntryType() { - return entryType; - } - - - public void setEntryType(CGMSHistoryEntryType entryType) { - this.entryType = entryType; - - this.sizes[0] = entryType.getHeadLength(); - this.sizes[1] = entryType.getDateLength(); - this.sizes[2] = entryType.getBodyLength(); - } - - - @Override - public String getEntryTypeName() { - return this.entryType.name(); - } - - - public void setData(List listRawData, boolean doNotProcess) { - if (this.entryType.schemaSet) { - super.setData(listRawData, doNotProcess); - } else { - this.rawData = listRawData; - } - } - - - @Override - public int getDateLength() { - return this.entryType.getDateLength(); - } - - - @Override - public int getOpCode() { - if (opCode == null) - return entryType.getOpCode(); - else - return opCode; - } - - - public void setOpCode(Integer opCode) { - this.opCode = opCode; - } - - - public boolean hasTimeStamp() { - return (this.entryType.hasDate()); - } - - - @Override - public String getToStringStart() { - - return "CGMSHistoryEntry [type=" + StringUtils.rightPad(entryType.name(), 18) + " [" - + StringUtils.leftPad("" + getOpCode(), 3) + ", 0x" + ByteUtil.getCorrectHexValue(getOpCode()) + "]"; - } - - - public void setDateTime(LocalDateTime timeStamp, int getIndex) { - - setAtechDateTime(DateTimeUtil.toATechDate(timeStamp.plusMinutes(getIndex * 5))); - - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt new file mode 100644 index 0000000000..2ede3d65c1 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt @@ -0,0 +1,55 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry +import org.apache.commons.lang3.StringUtils +import org.joda.time.LocalDateTime + +/** + * 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} + */ +class CGMSHistoryEntry : MedtronicHistoryEntry() { + + var entryType: CGMSHistoryEntryType? = null + private set + + override var opCode: Byte? = null // this is set only when we have unknown entry... + get() = if (field == null) entryType!!.code.toByte() else field + + fun setEntryType(entryType: CGMSHistoryEntryType) { + this.entryType = entryType + sizes[0] = entryType.headLength + sizes[1] = entryType.dateLength + sizes[2] = entryType.bodyLength + } + + override val entryTypeName: String + get() = entryType!!.name + + override fun setData(listRawData: List?, doNotProcess: Boolean) { + if (entryType!!.schemaSet) { + super.setData(listRawData, doNotProcess) + } else { + rawData = listRawData + } + } + + override val dateLength: Int + get() = entryType!!.dateLength + + fun hasTimeStamp(): Boolean { + return entryType!!.hasDate() + } + + override val toStringStart: String + get() = ("CGMSHistoryEntry [type=" + StringUtils.rightPad(entryType!!.name, 18) + " [" + + StringUtils.leftPad("" + opCode, 3) + ", 0x" + ByteUtil.getCorrectHexValue(opCode!!) + "]") + + fun setDateTime(timeStamp: LocalDateTime, getIndex: Int) { + setAtechDateTime(DateTimeUtil.toATechDate(timeStamp.plusMinutes(getIndex * 5))) + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java deleted file mode 100644 index 64161c720a..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.java +++ /dev/null @@ -1,135 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms; - -import java.util.HashMap; -import java.util.Map; - -/** - * 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} - */ - -public enum CGMSHistoryEntryType { - - None(0, "None", 1, 0, 0, DateType.None), // - - DataEnd(0x01, "DataEnd", 1, 0, 0, DateType.PreviousTimeStamp), // - SensorWeakSignal(0x02, "SensorWeakSignal", 1, 0, 0, DateType.PreviousTimeStamp), // - SensorCal(0x03, "SensorCal", 1, 0, 1, DateType.PreviousTimeStamp), // - SensorPacket(0x04, "SensorPacket", 1, 0, 1, DateType.PreviousTimeStamp), - SensorError(0x05, "SensorError", 1, 0, 1, DateType.PreviousTimeStamp), - SensorDataLow(0x06, "SensorDataLow", 1, 0, 1, DateType.PreviousTimeStamp), - SensorDataHigh(0x07, "SensorDataHigh", 1, 0, 1, DateType.PreviousTimeStamp), - SensorTimestamp(0x08, "SensorTimestamp", 1, 4, 0, DateType.MinuteSpecific), // - BatteryChange(0x0a, "BatteryChange", 1, 4, 0, DateType.MinuteSpecific), // - SensorStatus(0x0b, "SensorStatus", 1, 4, 0, DateType.MinuteSpecific), // - DateTimeChange(0x0c, "DateTimeChange", 1, 4, 0, DateType.SecondSpecific), // - SensorSync(0x0d, "SensorSync',packet_size=4", 1, 4, 0, DateType.MinuteSpecific), // - CalBGForGH(0x0e, "CalBGForGH',packet_size=5", 1, 4, 1, DateType.MinuteSpecific), // - SensorCalFactor(0x0f, "SensorCalFactor", 1, 4, 2, DateType.MinuteSpecific), // - Something10(0x10, "10-Something", 1, 4, 0, DateType.MinuteSpecific), // - Something19(0x13, "19-Something", 1, 0, 0, DateType.PreviousTimeStamp), - GlucoseSensorData(0xFF, "GlucoseSensorData", 1, 0, 0, DateType.PreviousTimeStamp); - - private static final Map opCodeMap = new HashMap<>(); - - static { - for (CGMSHistoryEntryType type : values()) { - opCodeMap.put(type.opCode, type); - } - } - - public boolean schemaSet; - private final int opCode; - private final String description; - private final int headLength; - private final int dateLength; - private final int bodyLength; - private final int totalLength; - private final DateType dateType; - - - CGMSHistoryEntryType(int opCode, String name, int head, int date, int body, DateType dateType) { - this.opCode = opCode; - this.description = name; - this.headLength = head; - this.dateLength = date; - this.bodyLength = body; - this.totalLength = (head + date + body); - this.schemaSet = true; - this.dateType = dateType; - } - - - // private CGMSHistoryEntryType(int opCode, String name, int length) - // { - // this.opCode = opCode; - // this.description = name; - // this.headLength = 0; - // this.dateLength = 0; - // this.bodyLength = 0; - // this.totalLength = length + 1; // opCode - // } - - public static CGMSHistoryEntryType getByCode(int opCode) { - if (opCodeMap.containsKey(opCode)) { - return opCodeMap.get(opCode); - } else - return CGMSHistoryEntryType.None; - } - - - public int getCode() { - return this.opCode; - } - - - public int getTotalLength() { - return totalLength; - } - - - public int getOpCode() { - return opCode; - } - - - public String getDescription() { - return description; - } - - - public int getHeadLength() { - return headLength; - } - - - public int getDateLength() { - return dateLength; - } - - - public int getBodyLength() { - return bodyLength; - } - - - public DateType getDateType() { - return dateType; - } - - - public boolean hasDate() { - return (this.dateType == DateType.MinuteSpecific) || (this.dateType == DateType.SecondSpecific); - } - - public enum DateType { - None, // - MinuteSpecific, // - SecondSpecific, // - PreviousTimeStamp // - - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt new file mode 100644 index 0000000000..a0cc7573c7 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt @@ -0,0 +1,62 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms + +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 CGMSHistoryEntryType(val code: Int, val description: String, val headLength: Int, val dateLength: Int, val bodyLength: Int, dateType: DateType) { + + None(0, "None", 1, 0, 0, DateType.None), // + DataEnd(0x01, "DataEnd", 1, 0, 0, DateType.PreviousTimeStamp), // + SensorWeakSignal(0x02, "SensorWeakSignal", 1, 0, 0, DateType.PreviousTimeStamp), // + SensorCal(0x03, "SensorCal", 1, 0, 1, DateType.PreviousTimeStamp), // + SensorPacket(0x04, "SensorPacket", 1, 0, 1, DateType.PreviousTimeStamp), SensorError(0x05, "SensorError", 1, 0, 1, DateType.PreviousTimeStamp), SensorDataLow(0x06, "SensorDataLow", 1, 0, 1, DateType.PreviousTimeStamp), SensorDataHigh(0x07, "SensorDataHigh", 1, 0, 1, DateType.PreviousTimeStamp), SensorTimestamp(0x08, "SensorTimestamp", 1, 4, 0, DateType.MinuteSpecific), // + BatteryChange(0x0a, "BatteryChange", 1, 4, 0, DateType.MinuteSpecific), // + SensorStatus(0x0b, "SensorStatus", 1, 4, 0, DateType.MinuteSpecific), // + DateTimeChange(0x0c, "DateTimeChange", 1, 4, 0, DateType.SecondSpecific), // + SensorSync(0x0d, "SensorSync',packet_size=4", 1, 4, 0, DateType.MinuteSpecific), // + CalBGForGH(0x0e, "CalBGForGH',packet_size=5", 1, 4, 1, DateType.MinuteSpecific), // + SensorCalFactor(0x0f, "SensorCalFactor", 1, 4, 2, DateType.MinuteSpecific), // + Something10(0x10, "10-Something", 1, 4, 0, DateType.MinuteSpecific), // + Something19(0x13, "19-Something", 1, 0, 0, DateType.PreviousTimeStamp), GlucoseSensorData(0xFF, "GlucoseSensorData", 1, 0, 0, DateType.PreviousTimeStamp); + + companion object { + private val opCodeMap: MutableMap = HashMap() + @JvmStatic fun getByCode(opCode: Int): CGMSHistoryEntryType? { + return if (opCodeMap.containsKey(opCode)) { + opCodeMap[opCode] + } else None + } + + init { + for (type in values()) { + opCodeMap[type.code] = type + } + } + } + + @JvmField var schemaSet: Boolean + val totalLength: Int + val dateType: DateType + + fun hasDate(): Boolean { + return dateType == DateType.MinuteSpecific || dateType == DateType.SecondSpecific + } + + enum class DateType { + None, // + MinuteSpecific, // + SecondSpecific, // + PreviousTimeStamp // + } + + init { + totalLength = headLength + dateLength + bodyLength + schemaSet = true + this.dateType = dateType + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java deleted file mode 100644 index 9d040fc105..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.java +++ /dev/null @@ -1,469 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms; - -import org.joda.time.LocalDateTime; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.logging.StacktraceLoggerWrapper; -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus; - -/** - * 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} - */ - -public class MedtronicCGMSHistoryDecoder extends MedtronicHistoryDecoder { - - private static final Logger LOG = StacktraceLoggerWrapper.getLogger(LTag.PUMPCOMM); - - - // CGMSValuesWriter cgmsValuesWriter = null; - - public MedtronicCGMSHistoryDecoder() { - } - - - public RecordDecodeStatus decodeRecord(CGMSHistoryEntry record) { - try { - return decodeRecord(record, false); - } catch (Exception ex) { - LOG.error(" Error decoding: type={}, ex={}", record.getEntryType().name(), ex.getMessage(), ex); - return RecordDecodeStatus.Error; - } - } - - - public RecordDecodeStatus decodeRecord(CGMSHistoryEntry entry, boolean x) { - - if (entry.getDateTimeLength() > 0) { - parseDate(entry); - } - - switch (entry.getEntryType()) { - - case SensorPacket: - decodeSensorPacket(entry); - break; - - case SensorError: - decodeSensorError(entry); - break; - - case SensorDataLow: - decodeDataHighLow(entry, 40); - break; - - case SensorDataHigh: - decodeDataHighLow(entry, 400); - break; - - case SensorTimestamp: - decodeSensorTimestamp(entry); - break; - - case SensorCal: - decodeSensorCal(entry); - break; - - case SensorCalFactor: - decodeSensorCalFactor(entry); - break; - - case SensorSync: - decodeSensorSync(entry); - break; - - case SensorStatus: - decodeSensorStatus(entry); - break; - - case CalBGForGH: - decodeCalBGForGH(entry); - break; - - case GlucoseSensorData: - decodeGlucoseSensorData(entry); - break; - - // just timestamp - case BatteryChange: - case Something10: - case DateTimeChange: - break; - - // just relative timestamp - case Something19: - case DataEnd: - case SensorWeakSignal: - break; - - case None: - break; - - } - - return RecordDecodeStatus.NotSupported; - } - - - @Override - public void postProcess() { - - } - - - public List createRecords(List dataClearInput) { - - List dataClear = reverseList(dataClearInput, Byte.class); - - prepareStatistics(); - - int counter = 0; - - List outList = new ArrayList(); - - // create CGMS entries (without dates) - do { - int opCode = getUnsignedInt(dataClear.get(counter)); - counter++; - - CGMSHistoryEntryType entryType; - - if (opCode == 0) { - // continue; - } else if ((opCode > 0) && (opCode < 20)) { - entryType = CGMSHistoryEntryType.getByCode(opCode); - - if (entryType == CGMSHistoryEntryType.None) { - this.unknownOpCodes.put(opCode, opCode); - LOG.warn("GlucoseHistoryEntry with unknown code: " + opCode); - - CGMSHistoryEntry pe = new CGMSHistoryEntry(); - pe.setEntryType(CGMSHistoryEntryType.None); - pe.setOpCode(opCode); - - pe.setData(Arrays.asList((byte) opCode), false); - - outList.add(pe); - } else { - // System.out.println("OpCode: " + opCode); - - List listRawData = new ArrayList(); - listRawData.add((byte) opCode); - - for (int j = 0; j < (entryType.getTotalLength() - 1); j++) { - listRawData.add(dataClear.get(counter)); - counter++; - } - - CGMSHistoryEntry pe = new CGMSHistoryEntry(); - pe.setEntryType(entryType); - - pe.setOpCode(opCode); - pe.setData(listRawData, false); - - // System.out.println("Record: " + pe); - - outList.add(pe); - } - } else { - CGMSHistoryEntry pe = new CGMSHistoryEntry(); - pe.setEntryType(CGMSHistoryEntryType.GlucoseSensorData); - - pe.setData(Arrays.asList((byte) opCode), false); - - outList.add(pe); - } - - } while (counter < dataClear.size()); - - List reversedOutList = reverseList(outList, CGMSHistoryEntry.class); - - Long timeStamp = null; - LocalDateTime dateTime = null; - int getIndex = 0; - - for (CGMSHistoryEntry entry : reversedOutList) { - - decodeRecord(entry); - - if (entry.hasTimeStamp()) { - timeStamp = entry.atechDateTime; - dateTime = DateTimeUtil.toLocalDateTime(timeStamp); - getIndex = 0; - } else if (entry.getEntryType() == CGMSHistoryEntryType.GlucoseSensorData) { - getIndex++; - if (dateTime != null) - entry.setDateTime(dateTime, getIndex); - } else { - if (dateTime != null) - entry.setDateTime(dateTime, getIndex); - } - - LOG.debug("Record: {}", entry); - } - - return reversedOutList; - - } - - - private List reverseList(List dataClearInput, Class clazz) { - - List outList = new ArrayList(); - - for (int i = dataClearInput.size() - 1; i > 0; i--) { - outList.add(dataClearInput.get(i)); - } - - return outList; - } - - - private int parseMinutes(int one) { - return (one & Integer.parseInt("0111111", 2)); - } - - - private int parseHours(int one) { - return (one & 0x1F); - } - - - private int parseDay(int one) { - return one & 0x1F; - } - - - private int parseMonths(int first_byte, int second_byte) { - - int first_two_bits = first_byte >> 6; - int second_two_bits = second_byte >> 6; - - return (first_two_bits << 2) + second_two_bits; - } - - - private int parseYear(int year) { - return (year & 0x0F) + 2000; - } - - - private Long parseDate(CGMSHistoryEntry entry) { - - if (!entry.getEntryType().hasDate()) - return null; - - byte[] data = entry.getDatetime(); - - if (entry.getEntryType().getDateType() == CGMSHistoryEntryType.DateType.MinuteSpecific) { - - Long atechDateTime = DateTimeUtil.toATechDate(parseYear(data[3]), parseMonths(data[0], data[1]), - parseDay(data[2]), parseHours(data[0]), parseMinutes(data[1]), 0); - - entry.setAtechDateTime(atechDateTime); - - return atechDateTime; - - } else if (entry.getEntryType().getDateType() == CGMSHistoryEntryType.DateType.SecondSpecific) { - LOG.warn("parseDate for SecondSpecific type is not implemented."); - throw new RuntimeException(); - // return null; - } else - return null; - - } - - - private void decodeGlucoseSensorData(CGMSHistoryEntry entry) { - int sgv = entry.getUnsignedRawDataByIndex(0) * 2; - entry.addDecodedData("sgv", sgv); - } - - - private void decodeCalBGForGH(CGMSHistoryEntry entry) { - - int amount = ((entry.getRawDataByIndex(3) & 0b00100000) << 3) | entry.getRawDataByIndex(5); - // - String originType; - - switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { - case 0x00: - originType = "rf"; - break; - - default: - originType = "unknown"; - - } - - entry.addDecodedData("amount", amount); - entry.addDecodedData("originType", originType); - - } - - - private void decodeSensorSync(CGMSHistoryEntry entry) { - - String syncType; - - switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { - case 0x01: - syncType = "new"; - break; - - case 0x02: - syncType = "old"; - break; - - default: - syncType = "find"; - break; - - } - - entry.addDecodedData("syncType", syncType); - } - - - private void decodeSensorStatus(CGMSHistoryEntry entry) { - - String statusType; - - switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { - case 0x00: - statusType = "off"; - break; - - case 0x01: - statusType = "on"; - break; - - case 0x02: - statusType = "lost"; - break; - - default: - statusType = "unknown"; - } - - entry.addDecodedData("statusType", statusType); - - } - - - private void decodeSensorCalFactor(CGMSHistoryEntry entry) { - - double factor = (entry.getRawDataByIndex(5) << 8 | entry.getRawDataByIndex(6)) / 1000.0d; - - entry.addDecodedData("factor", factor); - } - - - private void decodeSensorCal(CGMSHistoryEntry entry) { - - String calibrationType; - - switch (entry.getRawDataByIndex(1)) { - case 0x00: - calibrationType = "meter_bg_now"; - break; - - case 0x01: - calibrationType = "waiting"; - break; - - case 0x02: - calibrationType = "cal_error"; - break; - - default: - calibrationType = "unknown"; - } - - entry.addDecodedData("calibrationType", calibrationType); - - } - - - private void decodeSensorTimestamp(CGMSHistoryEntry entry) { - - String sensorTimestampType; - - switch (entry.getRawDataByIndex(3) >> 5 & 0b00000011) { - - case 0x00: - sensorTimestampType = "LastRf"; - break; - - case 0x01: - sensorTimestampType = "PageEnd"; - break; - - case 0x02: - sensorTimestampType = "Gap"; - break; - - default: - sensorTimestampType = "Unknown"; - break; - - } - - entry.addDecodedData("sensorTimestampType", sensorTimestampType); - } - - - private void decodeSensorPacket(CGMSHistoryEntry entry) { - - String packetType; - - switch (entry.getRawDataByIndex(1)) { - case 0x02: - packetType = "init"; - break; - - default: - packetType = "unknown"; - } - - entry.addDecodedData("packetType", packetType); - } - - - private void decodeSensorError(CGMSHistoryEntry entry) { - - String errorType; - - switch (entry.getRawDataByIndex(1)) { - case 0x01: - errorType = "end"; - break; - - default: - errorType = "unknown"; - } - - entry.addDecodedData("errorType", errorType); - } - - - private void decodeDataHighLow(CGMSHistoryEntry entry, int sgv) { - entry.addDecodedData("sgv", sgv); - } - - - @Override - protected void runPostDecodeTasks() { - this.showStatistics(); - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt new file mode 100644 index 0000000000..d56798dd3a --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -0,0 +1,269 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms + +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.logging.StacktraceLoggerWrapper.Companion.getLogger +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSHistoryEntryType +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSHistoryEntryType.Companion.getByCode +import okhttp3.internal.and +import org.joda.time.LocalDateTime +import org.slf4j.Logger +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} + */ +class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() { + + override fun decodeRecord(record: CGMSHistoryEntry): RecordDecodeStatus? { + return try { + decodeRecord(record, false) + } catch (ex: Exception) { + LOG.error(" Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) + RecordDecodeStatus.Error + } + } + + fun decodeRecord(entry: CGMSHistoryEntry, ignore: Boolean): RecordDecodeStatus { + if (entry.dateTimeLength > 0) { + parseDate(entry) + } + when (entry.entryType) { + CGMSHistoryEntryType.SensorPacket -> decodeSensorPacket(entry) + CGMSHistoryEntryType.SensorError -> decodeSensorError(entry) + CGMSHistoryEntryType.SensorDataLow -> decodeDataHighLow(entry, 40) + CGMSHistoryEntryType.SensorDataHigh -> decodeDataHighLow(entry, 400) + CGMSHistoryEntryType.SensorTimestamp -> decodeSensorTimestamp(entry) + CGMSHistoryEntryType.SensorCal -> decodeSensorCal(entry) + CGMSHistoryEntryType.SensorCalFactor -> decodeSensorCalFactor(entry) + CGMSHistoryEntryType.SensorSync -> decodeSensorSync(entry) + CGMSHistoryEntryType.SensorStatus -> decodeSensorStatus(entry) + CGMSHistoryEntryType.CalBGForGH -> decodeCalBGForGH(entry) + CGMSHistoryEntryType.GlucoseSensorData -> decodeGlucoseSensorData(entry) + + CGMSHistoryEntryType.BatteryChange, CGMSHistoryEntryType.Something10, CGMSHistoryEntryType.DateTimeChange -> { + } + + CGMSHistoryEntryType.Something19, CGMSHistoryEntryType.DataEnd, CGMSHistoryEntryType.SensorWeakSignal -> { + } + + CGMSHistoryEntryType.None -> { + } + } + return RecordDecodeStatus.NotSupported + } + + override fun postProcess() {} + override fun createRecords(dataClearInput: List): List { + val dataClear = reverseList(dataClearInput, Byte::class.java) + prepareStatistics() + var counter = 0 + val outList: MutableList = ArrayList() + + // create CGMS entries (without dates) + do { + val opCode = getUnsignedInt(dataClear[counter]) + counter++ + var entryType: CGMSHistoryEntryType? + if (opCode == 0) { + // continue; + } else if (opCode > 0 && opCode < 20) { + entryType = getByCode(opCode) + if (entryType === CGMSHistoryEntryType.None) { + unknownOpCodes!![opCode] = opCode + LOG.warn("GlucoseHistoryEntry with unknown code: $opCode") + val pe = CGMSHistoryEntry() + pe.setEntryType(CGMSHistoryEntryType.None) + pe.opCode = opCode.toByte() + pe.setData(Arrays.asList(opCode.toByte()), false) + outList.add(pe) + } else { + // System.out.println("OpCode: " + opCode); + val listRawData: MutableList = ArrayList() + listRawData.add(opCode.toByte()) + for (j in 0 until entryType!!.totalLength - 1) { + listRawData.add(dataClear[counter]) + counter++ + } + val pe = CGMSHistoryEntry() + pe.setEntryType(entryType) + pe.opCode = opCode.toByte() + pe.setData(listRawData, false) + + // System.out.println("Record: " + pe); + outList.add(pe) + } + } else { + val pe = CGMSHistoryEntry() + pe.setEntryType(CGMSHistoryEntryType.GlucoseSensorData) + pe.setData(Arrays.asList(opCode.toByte()), false) + outList.add(pe) + } + } while (counter < dataClear.size) + val reversedOutList = reverseList(outList, CGMSHistoryEntry::class.java) + var timeStamp: Long? = null + var dateTime: LocalDateTime? = null + var getIndex = 0 + for (entry in reversedOutList) { + decodeRecord(entry) + if (entry.hasTimeStamp()) { + timeStamp = entry.atechDateTime + dateTime = DateTimeUtil.toLocalDateTime(timeStamp!!) + getIndex = 0 + } else if (entry.entryType === CGMSHistoryEntryType.GlucoseSensorData) { + getIndex++ + if (dateTime != null) entry.setDateTime(dateTime, getIndex) + } else { + if (dateTime != null) entry.setDateTime(dateTime, getIndex) + } + LOG.debug("Record: {}", entry) + } + return reversedOutList + } + + private fun reverseList(dataClearInput: List, clazz: Class): List { + val outList: MutableList = ArrayList() + for (i in dataClearInput.size - 1 downTo 1) { + outList.add(dataClearInput[i]) + } + return outList + } + + private fun parseMinutes(one: Int): Int { + return one and "0111111".toInt(2) + } + + private fun parseHours(one: Int): Int { + return one and 0x1F + } + + private fun parseDay(one: Int): Int { + return one and 0x1F + } + + private fun parseMonths(first_byte: Int, second_byte: Int): Int { + val first_two_bits = first_byte shr 6 + val second_two_bits = second_byte shr 6 + return (first_two_bits shl 2) + second_two_bits + } + + private fun parseYear(year: Int): Int { + return (year and 0x0F) + 2000 + } + + private fun parseDate(entry: CGMSHistoryEntry): Long? { + if (!entry.entryType!!.hasDate()) return null + val data = entry.datetime + return if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.MinuteSpecific) { + val atechDateTime = DateTimeUtil.toATechDate(parseYear(data!![3].toInt()), parseMonths(data[0].toInt(), data[1].toInt()), + parseDay(data[2].toInt()), parseHours(data[0].toInt()), parseMinutes(data[1].toInt()), 0) + entry.setAtechDateTime(atechDateTime) + atechDateTime + } else if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.SecondSpecific) { + LOG.warn("parseDate for SecondSpecific type is not implemented.") + throw RuntimeException() + // return null; + } else null + } + + private fun decodeGlucoseSensorData(entry: CGMSHistoryEntry) { + val sgv = entry.getUnsignedRawDataByIndex(0) * 2 + entry.addDecodedData("sgv", sgv) + } + + private fun decodeCalBGForGH(entry: CGMSHistoryEntry) { + val amount: Int = entry.getRawDataByIndex(3) and 32 shl 3 or entry.getRawDataByIndexInt(5) + // + val originType: String + originType = when (entry.getRawDataByIndexInt(3) shr 5 and 3) { + 0x00 -> "rf" + else -> "unknown" + } + entry.addDecodedData("amount", amount) + entry.addDecodedData("originType", originType) + } + + private fun decodeSensorSync(entry: CGMSHistoryEntry) { + val syncType: String + syncType = when (entry.getRawDataByIndexInt(3) shr 5 and 3) { + 0x01 -> "new" + 0x02 -> "old" + else -> "find" + } + entry.addDecodedData("syncType", syncType) + } + + private fun decodeSensorStatus(entry: CGMSHistoryEntry) { + val statusType: String + statusType = when (entry.getRawDataByIndexInt(3) shr 5 and 3) { + 0x00 -> "off" + 0x01 -> "on" + 0x02 -> "lost" + else -> "unknown" + } + entry.addDecodedData("statusType", statusType) + } + + private fun decodeSensorCalFactor(entry: CGMSHistoryEntry) { + val factor: Double = (entry.getRawDataByIndexInt(5) shl 8 or entry.getRawDataByIndexInt(6)) / 1000.0 + entry.addDecodedData("factor", factor) + } + + private fun decodeSensorCal(entry: CGMSHistoryEntry) { + val calibrationType: String + calibrationType = when (entry.getRawDataByIndexInt(1)) { + 0x00 -> "meter_bg_now" + 0x01 -> "waiting" + 0x02 -> "cal_error" + else -> "unknown" + } + entry.addDecodedData("calibrationType", calibrationType) + } + + private fun decodeSensorTimestamp(entry: CGMSHistoryEntry) { + val sensorTimestampType: String + sensorTimestampType = when (entry.getRawDataByIndex(3).toInt() shr 5 and 3) { + 0x00 -> "LastRf" + 0x01 -> "PageEnd" + 0x02 -> "Gap" + else -> "Unknown" + } + entry.addDecodedData("sensorTimestampType", sensorTimestampType) + } + + private fun decodeSensorPacket(entry: CGMSHistoryEntry) { + val packetType: String + packetType = when (entry.getRawDataByIndex(1)) { + 0x02.toByte() -> "init" + else -> "unknown" + } + entry.addDecodedData("packetType", packetType) + } + + private fun decodeSensorError(entry: CGMSHistoryEntry) { + val errorType: String + errorType = when (entry.getRawDataByIndexInt(1)) { + 0x01 -> "end" + else -> "unknown" + } + entry.addDecodedData("errorType", errorType) + } + + private fun decodeDataHighLow(entry: CGMSHistoryEntry, sgv: Int) { + entry.addDecodedData("sgv", sgv) + } + + override fun runPostDecodeTasks() { + showStatistics() + } + + companion object { + private val LOG: Logger = getLogger(LTag.PUMPCOMM) + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java deleted file mode 100644 index b8d57edb7c..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.java +++ /dev/null @@ -1,724 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -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.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusWizardDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.DailyTotalsDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - -/** - * 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} - */ - -@Singleton -public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder { - - private PumpHistoryEntry tbrPreviousRecord; - private PumpHistoryEntry changeTimeRecord; - - @Inject - public MedtronicPumpHistoryDecoder( - AAPSLogger aapsLogger, - MedtronicUtil medtronicUtil - ) { - super.aapsLogger = aapsLogger; - this.medtronicUtil = medtronicUtil; - } - - - public List createRecords(List dataClear) { - prepareStatistics(); - - int counter = 0; - int record = 0; - boolean incompletePacket; - - List outList = new ArrayList<>(); - String skipped = null; - - if (dataClear.size() == 0) { - aapsLogger.error(LTag.PUMPBTCOMM, "Empty page."); - return outList; - } - - do { - int opCode = dataClear.get(counter); - boolean special = false; - incompletePacket = false; - boolean skippedRecords = false; - - if (opCode == 0) { - counter++; - if (skipped == null) - skipped = "0x00"; - else - skipped += " 0x00"; - continue; - } else { - if (skipped != null) { - aapsLogger.warn(LTag.PUMPBTCOMM, " ... Skipped " + skipped); - skipped = null; - skippedRecords = true; - } - } - - if (skippedRecords) { - aapsLogger.error(LTag.PUMPBTCOMM, "We had some skipped bytes, which might indicate error in pump history. Please report this problem."); - } - - PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(opCode); - - PumpHistoryEntry pe = new PumpHistoryEntry(); - pe.setEntryType(medtronicUtil.getMedtronicPumpModel(), entryType); - pe.setOffset(counter); - - counter++; - - if (counter >= 1022) { - break; - } - - List listRawData = new ArrayList<>(); - listRawData.add((byte) opCode); - - if (entryType == PumpHistoryEntryType.UnabsorbedInsulin - || entryType == PumpHistoryEntryType.UnabsorbedInsulin512) { - int elements = dataClear.get(counter); - listRawData.add((byte) elements); - counter++; - - int els = getUnsignedInt(elements); - - for (int k = 0; k < (els - 2); k++) { - if (counter < 1022) { - listRawData.add(dataClear.get(counter)); - counter++; - } - } - - special = true; - } else { - - for (int j = 0; j < (entryType.getTotalLength(medtronicUtil.getMedtronicPumpModel()) - 1); j++) { - - try { - listRawData.add(dataClear.get(counter)); - counter++; - } catch (Exception ex) { - aapsLogger.error(LTag.PUMPBTCOMM, "OpCode: " + ByteUtil.shortHexString((byte) opCode) + ", Invalid package: " - + ByteUtil.getHex(listRawData)); - // throw ex; - incompletePacket = true; - break; - } - - } - - if (incompletePacket) - break; - - } - - if (entryType == PumpHistoryEntryType.None) { - aapsLogger.error(LTag.PUMPBTCOMM, "Error in code. We should have not come into this branch."); - } else { - - if (pe.getEntryType() == PumpHistoryEntryType.UnknownBasePacket) { - pe.setOpCode(opCode); - } - - if (entryType.getHeadLength(medtronicUtil.getMedtronicPumpModel()) == 0) - special = true; - - pe.setData(listRawData, special); - - RecordDecodeStatus decoded = decodeRecord(pe); - - if ((decoded == RecordDecodeStatus.OK) || (decoded == RecordDecodeStatus.Ignored)) { - //Log.i(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); - } else { - aapsLogger.warn(LTag.PUMPBTCOMM, "#" + record + " " + decoded.getDescription() + " " + pe); - } - - addToStatistics(pe, decoded, null); - - record++; - - if (decoded == RecordDecodeStatus.OK) // we add only OK records, all others are ignored - { - outList.add(pe); - } - } - - } while (counter < dataClear.size()); - - return outList; - } - - - public RecordDecodeStatus decodeRecord(PumpHistoryEntry record) { - try { - return decodeRecord(record, false); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.getEntryType().name(), ex.getMessage(), ex)); - return RecordDecodeStatus.Error; - } - } - - - private RecordDecodeStatus decodeRecord(PumpHistoryEntry entry, boolean x) { - - if (entry.getDateTimeLength() > 0) { - decodeDateTime(entry); - } - - switch (entry.getEntryType()) { - - // Valid entries, but not processed - case ChangeBasalPattern: - case CalBGForPH: - case ChangeRemoteId: - case ClearAlarm: - case ChangeAlarmNotifyMode: // ChangeUtility: - case EnableDisableRemote: - case BGReceived: // Ian3F: CGMS - case SensorAlert: // Ian08 CGMS - case ChangeTimeFormat: - case ChangeReservoirWarningTime: - case ChangeBolusReminderEnable: - case SetBolusReminderTime: - case ChangeChildBlockEnable: - case BolusWizardEnabled: - case ChangeBGReminderOffset: - case ChangeAlarmClockTime: - case ChangeMeterId: - case ChangeParadigmID: - case JournalEntryMealMarker: - case JournalEntryExerciseMarker: - case DeleteBolusReminderTime: - case SetAutoOff: - case SelfTest: - case JournalEntryInsulinMarker: - case JournalEntryOtherMarker: - case BolusWizardSetup512: - case ChangeSensorSetup2: - case ChangeSensorAlarmSilenceConfig: - case ChangeSensorRateOfChangeAlertSetup: - case ChangeBolusScrollStepSize: - case BolusWizardSetup: - case ChangeVariableBolus: - case ChangeAudioBolus: - case ChangeBGReminderEnable: - case ChangeAlarmClockEnable: - case BolusReminder: - case DeleteAlarmClockTime: - case ChangeCarbUnits: - case ChangeWatchdogEnable: - case ChangeOtherDeviceID: - case ReadOtherDevicesIDs: - case BGReceived512: - case SensorStatus: - case ReadCaptureEventEnabled: - case ChangeCaptureEventEnable: - case ReadOtherDevicesStatus: - return RecordDecodeStatus.OK; - - case Sensor_0x54: - case Sensor_0x55: - case Sensor_0x51: - case Sensor_0x52: -// case EventUnknown_MM522_0x45: -// case EventUnknown_MM522_0x46: -// case EventUnknown_MM522_0x47: -// case EventUnknown_MM522_0x48: -// case EventUnknown_MM522_0x49: -// case EventUnknown_MM522_0x4a: -// case EventUnknown_MM522_0x4b: -// case EventUnknown_MM522_0x4c: -// case EventUnknown_MM512_0x10: - case EventUnknown_MM512_0x2e: -// case EventUnknown_MM512_0x37: -// case EventUnknown_MM512_0x38: -// case EventUnknown_MM512_0x4e: -// case EventUnknown_MM522_0x70: -// case EventUnknown_MM512_0x88: -// case EventUnknown_MM512_0x94: -// case EventUnknown_MM522_0xE8: -// case EventUnknown_0x4d: -// case EventUnknown_MM522_0x25: -// case EventUnknown_MM522_0x05: - aapsLogger.debug(LTag.PUMPBTCOMM, " -- ignored Unknown Pump Entry: " + entry); - return RecordDecodeStatus.Ignored; - - case UnabsorbedInsulin: - case UnabsorbedInsulin512: - return RecordDecodeStatus.Ignored; - - // **** Implemented records **** - - case DailyTotals522: - case DailyTotals523: - case DailyTotals515: - case EndResultTotals: - return decodeDailyTotals(entry); - - case ChangeBasalProfile_OldProfile: - case ChangeBasalProfile_NewProfile: - return decodeBasalProfile(entry); - - case BasalProfileStart: - return decodeBasalProfileStart(entry); - - case ChangeTime: - changeTimeRecord = entry; - return RecordDecodeStatus.OK; - - case NewTimeSet: - decodeChangeTime(entry); - return RecordDecodeStatus.OK; - - case TempBasalDuration: - // decodeTempBasal(entry); - return RecordDecodeStatus.OK; - - case TempBasalRate: - // decodeTempBasal(entry); - return RecordDecodeStatus.OK; - - case Bolus: - decodeBolus(entry); - return RecordDecodeStatus.OK; - - case BatteryChange: - decodeBatteryActivity(entry); - return RecordDecodeStatus.OK; - - case LowReservoir: - decodeLowReservoir(entry); - return RecordDecodeStatus.OK; - - case LowBattery: - case SuspendPump: - case ResumePump: - case Rewind: - case NoDeliveryAlarm: - case ChangeTempBasalType: - case ChangeMaxBolus: - case ChangeMaxBasal: - case ClearSettings: - case SaveSettings: - return RecordDecodeStatus.OK; - - case BolusWizard: - return decodeBolusWizard(entry); - - case BolusWizard512: - return decodeBolusWizard512(entry); - - case Prime: - decodePrime(entry); - return RecordDecodeStatus.OK; - - case TempBasalCombined: - return RecordDecodeStatus.Ignored; - - case None: - case UnknownBasePacket: - return RecordDecodeStatus.Error; - - default: { - aapsLogger.debug(LTag.PUMPBTCOMM, "Not supported: " + entry.getEntryType()); - return RecordDecodeStatus.NotSupported; - } - - } - - // return RecordDecodeStatus.Error; - - } - - - private RecordDecodeStatus decodeDailyTotals(PumpHistoryEntry entry) { - - entry.addDecodedData("Raw Data", ByteUtil.getHex(entry.getRawData())); - - DailyTotalsDTO totals = new DailyTotalsDTO(entry); - - entry.addDecodedData("Object", totals); - - return RecordDecodeStatus.OK; - } - - - private RecordDecodeStatus decodeBasalProfile(PumpHistoryEntry entry) { - - // LOG.debug("decodeBasalProfile: {}", entry); - - BasalProfile basalProfile = new BasalProfile(aapsLogger); - basalProfile.setRawDataFromHistory(entry.getBody()); - - // LOG.debug("decodeBasalProfile BasalProfile: {}", basalProfile); - - entry.addDecodedData("Object", basalProfile); - - return RecordDecodeStatus.OK; - } - - - private void decodeChangeTime(PumpHistoryEntry entry) { - if (changeTimeRecord == null) - return; - - entry.setDisplayableValue(entry.getDateTimeString()); - - this.changeTimeRecord = null; - } - - - private void decodeBatteryActivity(PumpHistoryEntry entry) { - // this.writeData(PumpBaseType.Event, entry.getHead()[0] == 0 ? PumpEventType.BatteryRemoved : - // PumpEventType.BatteryReplaced, entry.getATechDate()); - - entry.setDisplayableValue(entry.getHead()[0] == 0 ? "Battery Removed" : "Battery Replaced"); - } - - - private static String getFormattedValue(float value, int decimals) { - return String.format(Locale.ENGLISH, "%." + decimals + "f", value); - } - - - private RecordDecodeStatus decodeBasalProfileStart(PumpHistoryEntry entry) { - byte[] body = entry.getBody(); - // int bodyOffset = headerSize + timestampSize; - int offset = body[0] * 1000 * 30 * 60; - Float rate = null; - int index = entry.getHead()[0]; - - if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { - rate = body[1] * 0.025f; - } - - //LOG.info("Basal Profile Start: offset={}, rate={}, index={}, body_raw={}", offset, rate, index, body); - - if (rate == null) { - aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Basal Profile Start (ERROR): offset=%d, rate=%.3f, index=%d, body_raw=%s", offset, rate, index, ByteUtil.getHex(body))); - return RecordDecodeStatus.Error; - } else { - entry.addDecodedData("Value", getFormattedFloat(rate, 3)); - entry.setDisplayableValue(getFormattedFloat(rate, 3)); - return RecordDecodeStatus.OK; - } - - } - - - private RecordDecodeStatus decodeBolusWizard(PumpHistoryEntry entry) { - byte[] body = entry.getBody(); - - BolusWizardDTO dto = new BolusWizardDTO(); - - float bolusStrokes = 10.0f; - - if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { - // https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102 - bolusStrokes = 40.0f; - - dto.carbs = ((body[1] & 0x0c) << 6) + body[0]; - - dto.bloodGlucose = ((body[1] & 0x03) << 8) + entry.getHead()[0]; - dto.carbRatio = body[1] / 10.0f; - // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / - // 10.0s - dto.insulinSensitivity = new Float(body[4]); - dto.bgTargetLow = (int) body[5]; - dto.bgTargetHigh = (int) body[14]; - dto.correctionEstimate = (((body[9] & 0x38) << 5) + body[6]) / bolusStrokes; - dto.foodEstimate = ((body[7] << 8) + body[8]) / bolusStrokes; - dto.unabsorbedInsulin = ((body[10] << 8) + body[11]) / bolusStrokes; - dto.bolusTotal = ((body[12] << 8) + body[13]) / bolusStrokes; - } else { - dto.bloodGlucose = (((body[1] & 0x0F) << 8) | entry.getHead()[0]); - dto.carbs = (int) body[0]; - dto.carbRatio = Float.valueOf(body[2]); - dto.insulinSensitivity = new Float(body[3]); - dto.bgTargetLow = (int) body[4]; - dto.bgTargetHigh = (int) body[12]; - dto.bolusTotal = body[11] / bolusStrokes; - dto.foodEstimate = body[6] / bolusStrokes; - dto.unabsorbedInsulin = body[9] / bolusStrokes; - dto.bolusTotal = body[11] / bolusStrokes; - dto.correctionEstimate = (body[7] + (body[5] & 0x0F)) / bolusStrokes; - } - - if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { - dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.byteValue()); - } - - dto.atechDateTime = entry.atechDateTime; - entry.addDecodedData("Object", dto); - entry.setDisplayableValue(dto.getDisplayableValue()); - - return RecordDecodeStatus.OK; - } - - - private RecordDecodeStatus decodeBolusWizard512(PumpHistoryEntry entry) { - byte[] body = entry.getBody(); - - BolusWizardDTO dto = new BolusWizardDTO(); - - float bolusStrokes = 10.0f; - - dto.bloodGlucose = ((body[1] & 0x03 << 8) | entry.getHead()[0]); - dto.carbs = (body[1] & 0xC) << 6 | body[0]; // (int)body[0]; - dto.carbRatio = Float.valueOf(body[2]); - dto.insulinSensitivity = new Float(body[3]); - dto.bgTargetLow = (int) body[4]; - dto.foodEstimate = body[6] / 10.0f; - dto.correctionEstimate = (body[7] + (body[5] & 0x0F)) / bolusStrokes; - dto.unabsorbedInsulin = body[9] / bolusStrokes; - dto.bolusTotal = body[11] / bolusStrokes; - dto.bgTargetHigh = dto.bgTargetLow; - - if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { - dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.byteValue()); - } - - dto.atechDateTime = entry.atechDateTime; - entry.addDecodedData("Object", dto); - entry.setDisplayableValue(dto.getDisplayableValue()); - - return RecordDecodeStatus.OK; - } - - - private void decodeLowReservoir(PumpHistoryEntry entry) { - float amount = (getUnsignedInt(entry.getHead()[0]) * 1.0f / 10.0f) * 2; - - entry.setDisplayableValue(getFormattedValue(amount, 1)); - } - - - private void decodePrime(PumpHistoryEntry entry) { - float amount = ByteUtil.toInt(entry.getHead()[2], entry.getHead()[3]) / 10.0f; - float fixed = ByteUtil.toInt(entry.getHead()[0], entry.getHead()[1]) / 10.0f; - -// amount = (double)(asUINT8(data[4]) << 2) / 40.0; -// programmedAmount = (double)(asUINT8(data[2]) << 2) / 40.0; -// primeType = programmedAmount == 0 ? "manual" : "fixed"; - - entry.addDecodedData("Amount", amount); - entry.addDecodedData("FixedAmount", fixed); - - entry.setDisplayableValue("Amount=" + getFormattedValue(amount, 2) + ", Fixed Amount=" - + getFormattedValue(fixed, 2)); - } - - - private void decodeChangeTempBasalType(PumpHistoryEntry entry) { - entry.addDecodedData("isPercent", ByteUtil.asUINT8(entry.getRawDataByIndex(0)) == 1); // index moved from 1 -> 0 - } - - - private void decodeBgReceived(PumpHistoryEntry entry) { - entry.addDecodedData("amount", (ByteUtil.asUINT8(entry.getRawDataByIndex(0)) << 3) + (ByteUtil.asUINT8(entry.getRawDataByIndex(3)) >> 5)); - entry.addDecodedData("meter", ByteUtil.substring(entry.getRawData(), 6, 3)); // index moved from 1 -> 0 - } - - - private void decodeCalBGForPH(PumpHistoryEntry entry) { - entry.addDecodedData("amount", ((ByteUtil.asUINT8(entry.getRawDataByIndex(5)) & 0x80) << 1) + ByteUtil.asUINT8(entry.getRawDataByIndex(0))); // index moved from 1 -> 0 - } - - - private void decodeNoDeliveryAlarm(PumpHistoryEntry entry) { - //rawtype = asUINT8(data[1]); - // not sure if this is actually NoDelivery Alarm? - } - - - @Override - public void postProcess() { - } - - - @Override - protected void runPostDecodeTasks() { - this.showStatistics(); - } - - - private void decodeBolus(PumpHistoryEntry entry) { - BolusDTO bolus = new BolusDTO(); - - byte[] data = entry.getHead(); - - if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { - bolus.setRequestedAmount(ByteUtil.toInt(data[0], data[1]) / 40.0d); - bolus.setDeliveredAmount(ByteUtil.toInt(data[2], data[3]) / 40.0d); - bolus.setInsulinOnBoard(ByteUtil.toInt(data[4], data[5]) / 40.0d); - bolus.setDuration(data[6] * 30); - } else { - bolus.setRequestedAmount(ByteUtil.asUINT8(data[0]) / 10.0d); - bolus.setDeliveredAmount(ByteUtil.asUINT8(data[1]) / 10.0d); - bolus.setDuration(ByteUtil.asUINT8(data[2]) * 30); - } - - bolus.setBolusType((bolus.getDuration() != null && (bolus.getDuration() > 0)) ? PumpBolusType.Extended - : PumpBolusType.Normal); - bolus.setAtechDateTime(entry.atechDateTime); - - entry.addDecodedData("Object", bolus); - entry.setDisplayableValue(bolus.getDisplayableValue()); - - } - - - private void decodeTempBasal(PumpHistoryEntry entry) { - - if (this.tbrPreviousRecord == null) { - // LOG.debug(this.tbrPreviousRecord.toString()); - this.tbrPreviousRecord = entry; - return; - } - - decodeTempBasal(this.tbrPreviousRecord, entry); - - tbrPreviousRecord = null; - } - - - public void decodeTempBasal(PumpHistoryEntry tbrPreviousRecord, PumpHistoryEntry entry) { - - PumpHistoryEntry tbrRate = null, tbrDuration = null; - - if (entry.getEntryType() == PumpHistoryEntryType.TempBasalRate) { - tbrRate = entry; - } else { - tbrDuration = entry; - } - - if (tbrRate != null) { - tbrDuration = tbrPreviousRecord; - } else { - tbrRate = tbrPreviousRecord; - } - -// TempBasalPair tbr = new TempBasalPair( -// tbrRate.getHead()[0], -// tbrDuration.getHead()[0], -// (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0); - - TempBasalPair tbr = new TempBasalPair( - tbrRate.getHead()[0], - tbrRate.getBody()[0], - tbrDuration.getHead()[0], - (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0); - - // System.out.println("TBR: amount=" + tbr.getInsulinRate() + ", duration=" + tbr.getDurationMinutes() - // // + " min. Packed: " + tbr.getValue() - // ); - - entry.addDecodedData("Object", tbr); - entry.setDisplayableValue(tbr.getDescription()); - - } - - - private void decodeDateTime(PumpHistoryEntry entry) { - byte[] dt = entry.getDatetime(); - - if (dt == null) { - aapsLogger.warn(LTag.PUMPBTCOMM, "DateTime not set."); - } - - if (entry.getDateTimeLength() == 5) { - - int seconds = dt[0] & 0x3F; - int minutes = dt[1] & 0x3F; - int hour = dt[2] & 0x1F; - - int month = ((dt[0] >> 4) & 0x0c) + ((dt[1] >> 6) & 0x03); - // ((dt[0] & 0xC0) >> 6) | ((dt[1] & 0xC0) >> 4); - - int dayOfMonth = dt[3] & 0x1F; - int year = fix2DigitYear(dt[4] & 0x3F); // Assuming this is correct, need to verify. Otherwise this will be - // a problem in 2016. - - entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)); - - } else if (entry.getDateTimeLength() == 2) { - int low = ByteUtil.asUINT8(dt[0]) & 0x1F; - int mhigh = (ByteUtil.asUINT8(dt[0]) & 0xE0) >> 4; - int mlow = (ByteUtil.asUINT8(dt[1]) & 0x80) >> 7; - int month = mhigh + mlow; - // int dayOfMonth = low + 1; - int dayOfMonth = dt[0] & 0x1F; - int year = 2000 + (ByteUtil.asUINT8(dt[1]) & 0x7F); - - int hour = 0; - int minutes = 0; - int seconds = 0; - - //LOG.debug("DT: {} {} {}", year, month, dayOfMonth); - - if (dayOfMonth == 32) { - aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Entry: Day 32 %s = [%s] %s", entry.getEntryType().name(), - ByteUtil.getHex(entry.getRawData()), entry)); - } - - if (isEndResults(entry.getEntryType())) { - hour = 23; - minutes = 59; - seconds = 59; - } - - entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)); - - } else { - aapsLogger.warn(LTag.PUMPBTCOMM, "Unknown datetime format: " + entry.getDateTimeLength()); - } - - } - - - private boolean isEndResults(PumpHistoryEntryType entryType) { - - return (entryType == PumpHistoryEntryType.EndResultTotals || - entryType == PumpHistoryEntryType.DailyTotals515 || - entryType == PumpHistoryEntryType.DailyTotals522 || - entryType == PumpHistoryEntryType.DailyTotals523); - } - - - private int fix2DigitYear(int year) { - if (year > 90) { - year += 1900; - } else { - year += 2000; - } - - return year; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt new file mode 100644 index 0000000000..e0613567d8 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -0,0 +1,502 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump + +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.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType.Companion.getByCode +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusWizardDTO +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.DailyTotalsDTO +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +/** + * 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} + */ +@Singleton +class MedtronicPumpHistoryDecoder @Inject constructor( + aapsLogger: AAPSLogger?, + medtronicUtil: MedtronicUtil? +) : MedtronicHistoryDecoder() { + + private var tbrPreviousRecord: PumpHistoryEntry? = null + private var changeTimeRecord: PumpHistoryEntry? = null + override fun createRecords(dataClear: List): List { + prepareStatistics() + var counter = 0 + var record = 0 + var incompletePacket: Boolean + val outList: MutableList = ArrayList() + var skipped: String? = null + if (dataClear!!.size == 0) { + aapsLogger!!.error(LTag.PUMPBTCOMM, "Empty page.") + return outList + } + do { + val opCode: Int = dataClear[counter]!!.toInt() + var special = false + incompletePacket = false + var skippedRecords = false + if (opCode == 0) { + counter++ + if (skipped == null) skipped = "0x00" else skipped += " 0x00" + continue + } else { + if (skipped != null) { + aapsLogger!!.warn(LTag.PUMPBTCOMM, " ... Skipped $skipped") + skipped = null + skippedRecords = true + } + } + if (skippedRecords) { + aapsLogger!!.error(LTag.PUMPBTCOMM, "We had some skipped bytes, which might indicate error in pump history. Please report this problem.") + } + val entryType = getByCode(opCode.toByte()) + val pe = PumpHistoryEntry() + pe.setEntryType(medtronicUtil!!.medtronicPumpModel, entryType!!) + pe.offset = counter + counter++ + if (counter >= 1022) { + break + } + val listRawData: MutableList = ArrayList() + listRawData.add(opCode.toByte()) + if (entryType === PumpHistoryEntryType.UnabsorbedInsulin + || entryType === PumpHistoryEntryType.UnabsorbedInsulin512) { + val elements: Int = dataClear[counter]!!.toInt() + listRawData.add(elements.toByte()) + counter++ + val els = getUnsignedInt(elements) + for (k in 0 until els - 2) { + if (counter < 1022) { + listRawData.add(dataClear[counter]) + counter++ + } + } + special = true + } else { + for (j in 0 until entryType.getTotalLength(medtronicUtil!!.medtronicPumpModel) - 1) { + try { + listRawData.add(dataClear[counter]) + counter++ + } catch (ex: Exception) { + aapsLogger!!.error(LTag.PUMPBTCOMM, "OpCode: " + ByteUtil.shortHexString(opCode.toByte()) + ", Invalid package: " + + ByteUtil.getHex(listRawData)) + // throw ex; + incompletePacket = true + break + } + } + if (incompletePacket) break + } + if (entryType === PumpHistoryEntryType.None) { + aapsLogger!!.error(LTag.PUMPBTCOMM, "Error in code. We should have not come into this branch.") + } else { + if (pe.entryType === PumpHistoryEntryType.UnknownBasePacket) { + pe.opCode = opCode.toByte() + } + if (entryType.getHeadLength(medtronicUtil!!.medtronicPumpModel) == 0) special = true + pe.setData(listRawData as List, special) + val decoded = decodeRecord(pe) + if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { + //Log.i(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); + } else { + aapsLogger!!.warn(LTag.PUMPBTCOMM, "#" + record + " " + decoded!!.description + " " + pe) + } + addToStatistics(pe, decoded, null) + record++ + if (decoded === RecordDecodeStatus.OK) // we add only OK records, all others are ignored + { + outList.add(pe) + } + } + } while (counter < dataClear.size) + return outList + } + + override fun decodeRecord(record: PumpHistoryEntry): RecordDecodeStatus? { + return try { + decodeRecord(record, false) + } catch (ex: Exception) { + aapsLogger!!.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.entryType!!.name, ex.message, ex)) + RecordDecodeStatus.Error + } + } + + private fun decodeRecord(entry: PumpHistoryEntry, x: Boolean): RecordDecodeStatus { + if (entry.dateTimeLength > 0) { + decodeDateTime(entry) + } + return when (entry.entryType) { + PumpHistoryEntryType.ChangeBasalPattern, PumpHistoryEntryType.CalBGForPH, PumpHistoryEntryType.ChangeRemoteId, PumpHistoryEntryType.ClearAlarm, PumpHistoryEntryType.ChangeAlarmNotifyMode, PumpHistoryEntryType.EnableDisableRemote, PumpHistoryEntryType.BGReceived, PumpHistoryEntryType.SensorAlert, PumpHistoryEntryType.ChangeTimeFormat, PumpHistoryEntryType.ChangeReservoirWarningTime, PumpHistoryEntryType.ChangeBolusReminderEnable, PumpHistoryEntryType.SetBolusReminderTime, PumpHistoryEntryType.ChangeChildBlockEnable, PumpHistoryEntryType.BolusWizardEnabled, PumpHistoryEntryType.ChangeBGReminderOffset, PumpHistoryEntryType.ChangeAlarmClockTime, PumpHistoryEntryType.ChangeMeterId, PumpHistoryEntryType.ChangeParadigmID, PumpHistoryEntryType.JournalEntryMealMarker, PumpHistoryEntryType.JournalEntryExerciseMarker, PumpHistoryEntryType.DeleteBolusReminderTime, PumpHistoryEntryType.SetAutoOff, PumpHistoryEntryType.SelfTest, PumpHistoryEntryType.JournalEntryInsulinMarker, PumpHistoryEntryType.JournalEntryOtherMarker, PumpHistoryEntryType.BolusWizardSetup512, PumpHistoryEntryType.ChangeSensorSetup2, PumpHistoryEntryType.ChangeSensorAlarmSilenceConfig, PumpHistoryEntryType.ChangeSensorRateOfChangeAlertSetup, PumpHistoryEntryType.ChangeBolusScrollStepSize, PumpHistoryEntryType.BolusWizardSetup, PumpHistoryEntryType.ChangeVariableBolus, PumpHistoryEntryType.ChangeAudioBolus, PumpHistoryEntryType.ChangeBGReminderEnable, PumpHistoryEntryType.ChangeAlarmClockEnable, PumpHistoryEntryType.BolusReminder, PumpHistoryEntryType.DeleteAlarmClockTime, PumpHistoryEntryType.ChangeCarbUnits, PumpHistoryEntryType.ChangeWatchdogEnable, PumpHistoryEntryType.ChangeOtherDeviceID, PumpHistoryEntryType.ReadOtherDevicesIDs, PumpHistoryEntryType.BGReceived512, PumpHistoryEntryType.SensorStatus, PumpHistoryEntryType.ReadCaptureEventEnabled, PumpHistoryEntryType.ChangeCaptureEventEnable, PumpHistoryEntryType.ReadOtherDevicesStatus -> RecordDecodeStatus.OK + + PumpHistoryEntryType.Sensor_0x54, PumpHistoryEntryType.Sensor_0x55, PumpHistoryEntryType.Sensor_0x51, PumpHistoryEntryType.Sensor_0x52, PumpHistoryEntryType.EventUnknown_MM512_0x2e -> { + // case EventUnknown_MM512_0x37: +// case EventUnknown_MM512_0x38: +// case EventUnknown_MM512_0x4e: +// case EventUnknown_MM522_0x70: +// case EventUnknown_MM512_0x88: +// case EventUnknown_MM512_0x94: +// case EventUnknown_MM522_0xE8: +// case EventUnknown_0x4d: +// case EventUnknown_MM522_0x25: +// case EventUnknown_MM522_0x05: + aapsLogger!!.debug(LTag.PUMPBTCOMM, " -- ignored Unknown Pump Entry: $entry") + RecordDecodeStatus.Ignored + } + + PumpHistoryEntryType.UnabsorbedInsulin, PumpHistoryEntryType.UnabsorbedInsulin512 -> RecordDecodeStatus.Ignored + PumpHistoryEntryType.DailyTotals522, PumpHistoryEntryType.DailyTotals523, PumpHistoryEntryType.DailyTotals515, PumpHistoryEntryType.EndResultTotals -> decodeDailyTotals(entry) + PumpHistoryEntryType.ChangeBasalProfile_OldProfile, PumpHistoryEntryType.ChangeBasalProfile_NewProfile -> decodeBasalProfile(entry) + PumpHistoryEntryType.BasalProfileStart -> decodeBasalProfileStart(entry) + + PumpHistoryEntryType.ChangeTime -> { + changeTimeRecord = entry + RecordDecodeStatus.OK + } + + PumpHistoryEntryType.NewTimeSet -> { + decodeChangeTime(entry) + RecordDecodeStatus.OK + } + + PumpHistoryEntryType.TempBasalDuration -> // decodeTempBasal(entry); + RecordDecodeStatus.OK + PumpHistoryEntryType.TempBasalRate -> // decodeTempBasal(entry); + RecordDecodeStatus.OK + + PumpHistoryEntryType.Bolus -> { + decodeBolus(entry) + RecordDecodeStatus.OK + } + + PumpHistoryEntryType.BatteryChange -> { + decodeBatteryActivity(entry) + RecordDecodeStatus.OK + } + + PumpHistoryEntryType.LowReservoir -> { + decodeLowReservoir(entry) + RecordDecodeStatus.OK + } + + PumpHistoryEntryType.LowBattery, PumpHistoryEntryType.SuspendPump, PumpHistoryEntryType.ResumePump, PumpHistoryEntryType.Rewind, PumpHistoryEntryType.NoDeliveryAlarm, PumpHistoryEntryType.ChangeTempBasalType, PumpHistoryEntryType.ChangeMaxBolus, PumpHistoryEntryType.ChangeMaxBasal, PumpHistoryEntryType.ClearSettings, PumpHistoryEntryType.SaveSettings -> RecordDecodeStatus.OK + PumpHistoryEntryType.BolusWizard -> decodeBolusWizard(entry) + PumpHistoryEntryType.BolusWizard512 -> decodeBolusWizard512(entry) + + PumpHistoryEntryType.Prime -> { + decodePrime(entry) + RecordDecodeStatus.OK + } + + PumpHistoryEntryType.TempBasalCombined -> RecordDecodeStatus.Ignored + PumpHistoryEntryType.None, PumpHistoryEntryType.UnknownBasePacket -> RecordDecodeStatus.Error + + else -> { + aapsLogger!!.debug(LTag.PUMPBTCOMM, "Not supported: " + entry.entryType) + RecordDecodeStatus.NotSupported + } + } + + // return RecordDecodeStatus.Error; + } + + private fun decodeDailyTotals(entry: PumpHistoryEntry): RecordDecodeStatus { + entry.addDecodedData("Raw Data", ByteUtil.getHex(entry.rawData)) + val totals = DailyTotalsDTO(entry) + entry.addDecodedData("Object", totals) + return RecordDecodeStatus.OK + } + + private fun decodeBasalProfile(entry: PumpHistoryEntry): RecordDecodeStatus { + + // LOG.debug("decodeBasalProfile: {}", entry); + val basalProfile = BasalProfile(aapsLogger) + basalProfile.setRawDataFromHistory(entry.body) + + // LOG.debug("decodeBasalProfile BasalProfile: {}", basalProfile); + entry.addDecodedData("Object", basalProfile) + return RecordDecodeStatus.OK + } + + private fun decodeChangeTime(entry: PumpHistoryEntry) { + if (changeTimeRecord == null) return + entry.displayableValue = entry.dateTimeString + changeTimeRecord = null + } + + private fun decodeBatteryActivity(entry: PumpHistoryEntry) { + // this.writeData(PumpBaseType.Event, entry.getHead()[0] == 0 ? PumpEventType.BatteryRemoved : + // PumpEventType.BatteryReplaced, entry.getATechDate()); + entry.displayableValue = if (entry.head!![0] == 0.toByte()) "Battery Removed" else "Battery Replaced" + } + + private fun decodeBasalProfileStart(entry: PumpHistoryEntry): RecordDecodeStatus { + val body = entry.body + // int bodyOffset = headerSize + timestampSize; + val offset = body!![0] * 1000 * 30 * 60 + var rate: Float? = null + val index = entry.head!![0].toInt() + if (MedtronicDeviceType.isSameDevice(medtronicUtil!!.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { + rate = body[1] * 0.025f + } + + //LOG.info("Basal Profile Start: offset={}, rate={}, index={}, body_raw={}", offset, rate, index, body); + return if (rate == null) { + aapsLogger!!.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Basal Profile Start (ERROR): offset=%d, rate=%.3f, index=%d, body_raw=%s", offset, rate, index, ByteUtil.getHex(body))) + RecordDecodeStatus.Error + } else { + entry.addDecodedData("Value", getFormattedFloat(rate, 3)) + entry.displayableValue = getFormattedFloat(rate, 3) + RecordDecodeStatus.OK + } + } + + private fun decodeBolusWizard(entry: PumpHistoryEntry): RecordDecodeStatus { + val body = entry.body as IntArray + val dto = BolusWizardDTO() + var bolusStrokes = 10.0f + 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 + bolusStrokes = 40.0f + dto.carbs = (body[1] and 0x0c shl 6) + body[0] + dto.bloodGlucose = (body[1] and 0x03 shl 8) + entry.head!![0] + dto.carbRatio = body[1] / 10.0f + // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / + // 10.0s + dto.insulinSensitivity = body[4].toFloat() + dto.bgTargetLow = body[5] as Int + dto.bgTargetHigh = body[14] as Int + dto.correctionEstimate = ((body[9] and 0x38 shl 5) + body[6]) / bolusStrokes + dto.foodEstimate = ((body[7] shl 8) + body[8]) / bolusStrokes + dto.unabsorbedInsulin = ((body[10] shl 8) + body[11]) / bolusStrokes + dto.bolusTotal = ((body[12] shl 8) + body[13]) / bolusStrokes + } else { + dto.bloodGlucose = body.get(1) and 0x0F shl 8 or entry.head!!.get(0).toInt() + dto.carbs = body.get(0) as Int + dto.carbRatio = body.get(2).toFloat() + dto.insulinSensitivity = body.get(3).toFloat() + dto.bgTargetLow = body.get(4) as Int + dto.bgTargetHigh = body.get(12) as Int + dto.bolusTotal = body.get(11) / bolusStrokes + dto.foodEstimate = body.get(6) / bolusStrokes + dto.unabsorbedInsulin = body.get(9) / bolusStrokes + dto.bolusTotal = body.get(11) / bolusStrokes + dto.correctionEstimate = (body.get(7) + (body.get(5) and 0x0F)) / bolusStrokes + } + if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { + dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.toByte()) + } + dto.atechDateTime = entry.atechDateTime!! + entry.addDecodedData("Object", dto) + entry.displayableValue = dto.displayableValue + return RecordDecodeStatus.OK + } + + private fun decodeBolusWizard512(entry: PumpHistoryEntry): RecordDecodeStatus { + val body = entry.body as IntArray + val dto = BolusWizardDTO() + val bolusStrokes = 10.0f + dto.bloodGlucose = body.get(1) and 0x03 shl 8 or entry.head!!.get(0).toInt() + dto.carbs = body!!.get(1).toInt() and 0xC shl 6 or body.get(0).toInt() // (int)body[0]; + dto.carbRatio = body!!.get(2).toFloat() + dto.insulinSensitivity = body!!.get(3).toFloat() + dto.bgTargetLow = body.get(4) + dto.foodEstimate = body.get(6) / 10.0f + dto.correctionEstimate = (body.get(7) + (body.get(5) and 0x0F)) / bolusStrokes + dto.unabsorbedInsulin = body.get(9) / bolusStrokes + dto.bolusTotal = body.get(11) / bolusStrokes + dto.bgTargetHigh = dto.bgTargetLow + if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { + dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.toByte()) + } + dto.atechDateTime = entry.atechDateTime!! + entry.addDecodedData("Object", dto) + entry.displayableValue = dto.displayableValue + return RecordDecodeStatus.OK + } + + private fun decodeLowReservoir(entry: PumpHistoryEntry) { + val amount = getUnsignedInt(entry.head!!.get(0)) * 1.0f / 10.0f * 2 + entry.displayableValue = getFormattedValue(amount, 1) + } + + private fun decodePrime(entry: PumpHistoryEntry) { + val amount = ByteUtil.toInt(entry.head!!.get(2), entry.head!!.get(3)) / 10.0f + val fixed = ByteUtil.toInt(entry.head!!.get(0), entry.head!!.get(1)) / 10.0f + +// amount = (double)(asUINT8(data[4]) << 2) / 40.0; +// programmedAmount = (double)(asUINT8(data[2]) << 2) / 40.0; +// primeType = programmedAmount == 0 ? "manual" : "fixed"; + entry.addDecodedData("Amount", amount) + entry.addDecodedData("FixedAmount", fixed) + entry.displayableValue = ("Amount=" + getFormattedValue(amount, 2) + ", Fixed Amount=" + + getFormattedValue(fixed, 2)) + } + + private fun decodeChangeTempBasalType(entry: PumpHistoryEntry) { + entry.addDecodedData("isPercent", ByteUtil.asUINT8(entry.getRawDataByIndex(0)) == 1) // index moved from 1 -> 0 + } + + private fun decodeBgReceived(entry: PumpHistoryEntry) { + entry.addDecodedData("amount", (ByteUtil.asUINT8(entry.getRawDataByIndex(0)) shl 3) + (ByteUtil.asUINT8(entry.getRawDataByIndex(3)) shr 5)) + entry.addDecodedData("meter", ByteUtil.substring(entry.rawData, 6, 3)) // index moved from 1 -> 0 + } + + private fun decodeCalBGForPH(entry: PumpHistoryEntry) { + entry.addDecodedData("amount", (ByteUtil.asUINT8(entry.getRawDataByIndex(5)) and 0x80 shl 1) + ByteUtil.asUINT8(entry.getRawDataByIndex(0))) // index moved from 1 -> 0 + } + + private fun decodeNoDeliveryAlarm(entry: PumpHistoryEntry) { + //rawtype = asUINT8(data[1]); + // not sure if this is actually NoDelivery Alarm? + } + + override fun postProcess() {} + + override fun runPostDecodeTasks() { + showStatistics() + } + + private fun decodeBolus(entry: PumpHistoryEntry) { + val bolus = BolusDTO() + val data = entry.head as IntArray + if (MedtronicDeviceType.isSameDevice(medtronicUtil!!.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { + 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.insulinOnBoard = ByteUtil.toInt(data.get(4), data.get(5)) / 40.0 + bolus.duration = data.get(6) * 30 + } else { + bolus.requestedAmount = ByteUtil.asUINT8(data.get(0)) / 10.0 + bolus.deliveredAmount = ByteUtil.asUINT8(data.get(1)) / 10.0 + bolus.duration = ByteUtil.asUINT8(data.get(2)) * 30 + } + bolus.bolusType = if (bolus.duration != null && bolus.duration > 0) PumpBolusType.Extended else PumpBolusType.Normal + bolus.setAtechDateTime(entry.atechDateTime!!) + entry.addDecodedData("Object", bolus) + entry.displayableValue = bolus.displayableValue + } + + // private fun decodeTempBasal(entry: PumpHistoryEntry) { + // if (tbrPreviousRecord == null) { + // // LOG.debug(this.tbrPreviousRecord.toString()); + // tbrPreviousRecord = entry + // return + // } + // decodeTempBasal(tbrPreviousRecord, entry) + // tbrPreviousRecord = null + // } + + fun decodeTempBasal(tbrPreviousRecord: PumpHistoryEntry, entry: PumpHistoryEntry) { + var tbrRate: PumpHistoryEntry? = null + var tbrDuration: PumpHistoryEntry? = null + if (entry.entryType === PumpHistoryEntryType.TempBasalRate) { + tbrRate = entry + } else { + tbrDuration = entry + } + if (tbrRate != null) { + tbrDuration = tbrPreviousRecord + } else { + tbrRate = tbrPreviousRecord + } + +// TempBasalPair tbr = new TempBasalPair( +// tbrRate.getHead()[0], +// tbrDuration.getHead()[0], +// (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0); + val tbr = TempBasalPair( + tbrRate!!.head!!.get(0), + tbrRate!!.body!!.get(0), + tbrDuration!!.head!!.get(0).toInt(), + ByteUtil.asUINT8(tbrRate!!.datetime!!.get(4)) shr 3 == 0) + + // System.out.println("TBR: amount=" + tbr.getInsulinRate() + ", duration=" + tbr.getDurationMinutes() + // // + " min. Packed: " + tbr.getValue() + // ); + entry.addDecodedData("Object", tbr) + entry.displayableValue = tbr.description + } + + private fun decodeDateTime(entry: PumpHistoryEntry) { + val dt = entry.datetime as IntArray + if (dt == null) { + aapsLogger!!.warn(LTag.PUMPBTCOMM, "DateTime not set.") + } + if (entry.dateTimeLength == 5) { + val seconds: Int = (dt!!.get(0) and 0x3F).toInt() + val minutes: Int = (dt!!.get(1) and 0x3F).toInt() + val hour: Int = (dt.get(2) and 0x1F).toInt() + val month: Int = (dt.get(0) shr 4 and 0x0c) + (dt.get(1) shr 6 and 0x03) + // ((dt[0] & 0xC0) >> 6) | ((dt[1] & 0xC0) >> 4); + val dayOfMonth: Int = dt.get(3) and 0x1F + val year = fix2DigitYear(dt.get(4) and 0x3F) // Assuming this is correct, need to verify. Otherwise this will be + // a problem in 2016. + entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)) + } else if (entry.dateTimeLength == 2) { + val low = ByteUtil.asUINT8(dt.get(0)) and 0x1F + val mhigh = ByteUtil.asUINT8(dt.get(0)) and 0xE0 shr 4 + val mlow = ByteUtil.asUINT8(dt.get(1)) and 0x80 shr 7 + val month = mhigh + mlow + // int dayOfMonth = low + 1; + val dayOfMonth: Int = dt.get(0) and 0x1F + val year = 2000 + (ByteUtil.asUINT8(dt.get(1)) and 0x7F) + var hour = 0 + var minutes = 0 + var seconds = 0 + + //LOG.debug("DT: {} {} {}", year, month, dayOfMonth); + if (dayOfMonth == 32) { + aapsLogger!!.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Entry: Day 32 %s = [%s] %s", entry.entryType!!.name, + ByteUtil.getHex(entry.rawData), entry)) + } + if (isEndResults(entry.entryType)) { + hour = 23 + minutes = 59 + seconds = 59 + } + entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)) + } else { + aapsLogger!!.warn(LTag.PUMPBTCOMM, "Unknown datetime format: " + entry.dateTimeLength) + } + } + + private fun isEndResults(entryType: PumpHistoryEntryType?): Boolean { + return entryType === PumpHistoryEntryType.EndResultTotals || entryType === PumpHistoryEntryType.DailyTotals515 || entryType === PumpHistoryEntryType.DailyTotals522 || entryType === PumpHistoryEntryType.DailyTotals523 + } + + private fun fix2DigitYear(year: Int): Int { + var year = year + year += if (year > 90) { + 1900 + } else { + 2000 + } + return year + } + + companion object { + private fun getFormattedValue(value: Float, decimals: Int): String { + return String.format(Locale.ENGLISH, "%." + decimals + "f", value) + } + } + + init { + super.aapsLogger = aapsLogger + this.medtronicUtil = medtronicUtil + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java deleted file mode 100644 index 3866e3e6ba..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.java +++ /dev/null @@ -1,174 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; - -import com.google.gson.annotations.Expose; - -import java.util.Objects; - -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; - -/** - * 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} - */ - -public class PumpHistoryEntry extends MedtronicHistoryEntry { - - @Expose - private PumpHistoryEntryType entryType; - private Integer opCode; // this is set only when we have unknown entry... - private int offset; - private String displayableValue = ""; - - - public PumpHistoryEntryType getEntryType() { - return entryType; - } - - - public void setEntryType(MedtronicDeviceType medtronicDeviceType, PumpHistoryEntryType entryType) { - this.entryType = entryType; - - this.sizes[0] = entryType.getHeadLength(medtronicDeviceType); - this.sizes[1] = entryType.getDateLength(); - this.sizes[2] = entryType.getBodyLength(medtronicDeviceType); - - if (this.entryType != null && this.atechDateTime != null) - setPumpId(); - } - - - private void setPumpId() { - this.pumpId = this.entryType.getCode() + (this.atechDateTime * 1000L); - } - - - @Override - public int getOpCode() { - if (opCode == null) - return entryType.getOpCode(); - else - return opCode; - } - - - public void setOpCode(Integer opCode) { - this.opCode = opCode; - } - - - @Override - public String getToStringStart() { - return "PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType.name(), 20) + " [" - + StringUtil.getStringInLength("" + getOpCode(), 3) + ", 0x" - + ByteUtil.shortHexString((byte) getOpCode()) + "]"; - } - - - public String toString() { - return super.toString(); -// Object object = this.getDecodedDataEntry("Object"); -// -// if (object == null) { -// return super.toString(); -// } else { -// return super.toString() + "PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType.name(), 20) + ", DT: " + DT + ", Object=" + object.toString() + "]"; -// } - } - - - public int getOffset() { - return offset; - } - - - public void setOffset(int offset) { - this.offset = offset; - } - - - @Override - public String getEntryTypeName() { - return this.entryType.name(); - } - - - @Override - public int getDateLength() { - return this.entryType.getDateLength(); - } - - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - - if (!(o instanceof PumpHistoryEntry)) - return false; - - PumpHistoryEntry that = (PumpHistoryEntry) o; - - return entryType == that.entryType && // - this.atechDateTime == that.atechDateTime; // && // - // Objects.equals(this.decodedData, that.decodedData); - } - - - @Override - public int hashCode() { - return Objects.hash(entryType, opCode, offset); - } - - - // public boolean isAfter(LocalDateTime dateTimeIn) { - // // LOG.debug("Entry: " + this.dateTime); - // // LOG.debug("Datetime: " + dateTimeIn); - // // LOG.debug("Item after: " + this.dateTime.isAfter(dateTimeIn)); - // return this.dateTime.isAfter(dateTimeIn); - // } - - public boolean isAfter(long atechDateTime) { - if (this.atechDateTime == null) { - LOG.error("Date is null. Show object: " + toString()); - return false; // FIXME shouldn't happen - } - - return atechDateTime < this.atechDateTime; - } - - - public void setDisplayableValue(String displayableValue) { - this.displayableValue = displayableValue; - } - - - public String getDisplayableValue() { - return displayableValue; - } - - public static class Comparator implements java.util.Comparator { - - @Override - public int compare(PumpHistoryEntry o1, PumpHistoryEntry o2) { - int data = (int) (o2.atechDateTime - o1.atechDateTime); - - if (data != 0) - return data; - - return o2.getEntryType().getCode() - o1.getEntryType().getCode(); - } - } - - - public Long getPumpId() { - setPumpId(); - - return pumpId; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt new file mode 100644 index 0000000000..e1c0daf2ea --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -0,0 +1,117 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump + +import android.util.Log +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType +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} + */ +class PumpHistoryEntry : MedtronicHistoryEntry() { + + @Expose var entryType: PumpHistoryEntryType? = null + private set + + override var opCode: Byte? = null + // this is set only when we have unknown entry... + get() = if (field == null) entryType!!.code else field + set(value) { + field = value + } + + // // override fun getOpCode(): Int { + // // return + // // } + // + // fun setOpCode(opCode: Int?) { + // this.opCode = opCode + // } + + var offset = 0 + var displayableValue = "" + + fun setEntryType(medtronicDeviceType: MedtronicDeviceType?, entryType: PumpHistoryEntryType) { + this.entryType = entryType + sizes[0] = entryType.getHeadLength(medtronicDeviceType) + sizes[1] = entryType.dateLength + sizes[2] = entryType.getBodyLength(medtronicDeviceType) + if (this.entryType != null && atechDateTime != null) setPumpId() + } + + private fun setPumpId() { + pumpId = entryType!!.code + atechDateTime!! * 1000L + } + + override val toStringStart: String + get() = ("PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType!!.name, 20) + " [" + + StringUtil.getStringInLength("" + opCode, 3) + ", 0x" + + ByteUtil.shortHexString(opCode!!) + "]") + + override fun toString(): String { + return super.toString() + // Object object = this.getDecodedDataEntry("Object"); +// +// if (object == null) { +// return super.toString(); +// } else { +// return super.toString() + "PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType.name(), 20) + ", DT: " + DT + ", Object=" + object.toString() + "]"; +// } + } + + override val entryTypeName: String + get() = entryType!!.name + + override val dateLength: Int + get() = entryType!!.dateLength + + override fun equals(o: Any?): Boolean { + if (this === o) return true + if (o !is PumpHistoryEntry) return false + val that = o + return entryType == that.entryType && // + atechDateTime === that.atechDateTime // && // + // Objects.equals(this.decodedData, that.decodedData); + } + + override fun hashCode(): Int { + return Objects.hash(entryType, opCode, offset) + } + + // public boolean isAfter(LocalDateTime dateTimeIn) { + // // LOG.debug("Entry: " + this.dateTime); + // // LOG.debug("Datetime: " + dateTimeIn); + // // LOG.debug("Item after: " + this.dateTime.isAfter(dateTimeIn)); + // return this.dateTime.isAfter(dateTimeIn); + // } + fun isAfter(atechDateTime: Long): Boolean { + if (this.atechDateTime == null) { + Log.e("PumpHistoryEntry", "Date is null. Show object: " + toString()) + return false // FIXME shouldn't happen + } + return atechDateTime < this.atechDateTime!! + } + + class Comparator : java.util.Comparator { + override fun compare(o1: PumpHistoryEntry, o2: PumpHistoryEntry): Int { + val data = (o2.atechDateTime!! - o1.atechDateTime!!).toInt() + return if (data != 0) data else o2.entryType!!.code - o1.entryType!!.code + } + } + + override var pumpId: Long? = null + get() { + setPumpId() + return field + } + set(pumpId) { + super.pumpId = pumpId + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java deleted file mode 100644 index becfcfbcd2..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.java +++ /dev/null @@ -1,378 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; - -/** - * 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} - */ - -public enum PumpHistoryEntryType // implements CodeEnum -{ - // all commented out are probably not the real items - None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), - Bolus(0x01, "Bolus", PumpHistoryEntryGroup.Bolus, 4, 5, 0), // 523+[H=8] 9/13 - Prime(0x03, "Prime", PumpHistoryEntryGroup.Prime, 5, 5, 0), // - // /**/EventUnknown_MM522_0x05((byte) 0x05, "Unknown Event 0x05", PumpHistoryEntryGroup.Unknown, 2, 5, 28), // - NoDeliveryAlarm(0x06, "No Delivery", PumpHistoryEntryGroup.Alarm, 4, 5, 0), // - EndResultTotals(0x07, "End Result Totals", PumpHistoryEntryGroup.Statistic, 5, 2, 0), - ChangeBasalProfile_OldProfile(0x08, "Change Basal Profile (Old)", PumpHistoryEntryGroup.Basal, 2, 5, 145), - ChangeBasalProfile_NewProfile(0x09, "Change Basal Profile (New)", PumpHistoryEntryGroup.Basal, 2, 5, 145), // - // /**/EventUnknown_MM512_0x10(0x10, "Unknown Event 0x10", PumpHistoryEntryGroup.Unknown), // 29, 5, 0 - CalBGForPH(0x0a, "BG Capture", PumpHistoryEntryGroup.Glucose), // - SensorAlert(0x0b, "Sensor Alert", PumpHistoryEntryGroup.Alarm, 3, 5, 0), // Ian08 - ClearAlarm(0x0c, "Clear Alarm", PumpHistoryEntryGroup.Alarm, 2, 5, 0), // 2,5,4 - ChangeBasalPattern(0x14, "Change Basal Pattern", PumpHistoryEntryGroup.Basal), // - TempBasalDuration(0x16, "TBR Duration", PumpHistoryEntryGroup.Basal), // - ChangeTime(0x17, "Change Time", PumpHistoryEntryGroup.Configuration), // - NewTimeSet(0x18, "New Time Set", PumpHistoryEntryGroup.Notification), // - LowBattery(0x19, "LowBattery", PumpHistoryEntryGroup.Notification), // - BatteryChange(0x1a, "Battery Change", PumpHistoryEntryGroup.Notification), // - SetAutoOff(0x1b, "Set Auto Off", PumpHistoryEntryGroup.Configuration), // - SuspendPump(0x1e, "Suspend", PumpHistoryEntryGroup.Basal), // - ResumePump(0x1f, "Resume", PumpHistoryEntryGroup.Basal), // - SelfTest(0x20, "Self Test", PumpHistoryEntryGroup.Statistic), // - Rewind(0x21, "Rewind", PumpHistoryEntryGroup.Prime), // - ClearSettings(0x22, "Clear Settings", PumpHistoryEntryGroup.Configuration), // - ChangeChildBlockEnable(0x23, "Change Child Block Enable", PumpHistoryEntryGroup.Configuration), // - ChangeMaxBolus(0x24, "Change Max Bolus", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM522_0x25(0x25, "Unknown Event 0x25", PumpHistoryEntryGroup.Unknown), // 8? - EnableDisableRemote(0x26, "Enable/Disable Remote", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // 2, 5, 14 V6:2,5,14 - ChangeRemoteId(0x27, "Change Remote ID", PumpHistoryEntryGroup.Configuration), // ?? - ChangeMaxBasal(0x2c, "Change Max Basal", PumpHistoryEntryGroup.Configuration), // - BolusWizardEnabled(0x2d, "Bolus Wizard Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? - /* TODO */EventUnknown_MM512_0x2e(0x2e, "Unknown Event 0x2e", PumpHistoryEntryGroup.Unknown, 2, 5, 100), // - BolusWizard512(0x2f, "Bolus Wizard (512)", PumpHistoryEntryGroup.Bolus, 2, 5, 12), // - UnabsorbedInsulin512(0x30, "Unabsorbed Insulin (512)", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // FIXME - ChangeBGReminderOffset(0x31, "Change BG Reminder Offset", PumpHistoryEntryGroup.Configuration), // - ChangeAlarmClockTime(0x32, "Change Alarm Clock Time", PumpHistoryEntryGroup.Configuration), // - TempBasalRate(0x33, "TBR Rate", PumpHistoryEntryGroup.Basal, 2, 5, 1), // - LowReservoir(0x34, "Low Reservoir", PumpHistoryEntryGroup.Notification), // - ChangeAlarmClock(0x35, "Change Alarm Clock", PumpHistoryEntryGroup.Configuration), // - ChangeMeterId(0x36, "Change Meter ID", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM512_0x37(0x37, "Unknown Event 0x37", PumpHistoryEntryGroup.Unknown), // V:MM512 -// /**/EventUnknown_MM512_0x38(0x38, "Unknown Event 0x38", PumpHistoryEntryGroup.Unknown), // - BGReceived512(0x39, "BG Received (512)", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // - /* TODO */ConfirmInsulinChange(0x3a, "Confirm Insulin Change", PumpHistoryEntryGroup.Unknown), // - SensorStatus(0x3b, "Sensor Status", PumpHistoryEntryGroup.Glucose), // - ChangeParadigmID(0x3c, "Change Paradigm ID", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // V3 ? V6: 2,5,14 ?? is it this length or just 7 - // EventUnknown_MM512_0x3D(0x3d, "Unknown Event 0x3D", PumpHistoryEntryGroup.Unknown), // -// EventUnknown_MM512_0x3E(0x3e, "Unknown Event 0x3E", PumpHistoryEntryGroup.Unknown), // - BGReceived(0x3f, "BG Received", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // Ian3F - JournalEntryMealMarker(0x40, "Meal Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 2), // is size just 7??? V6 - JournalEntryExerciseMarker(0x41, "Exercise Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // ?? - JournalEntryInsulinMarker(0x42, "Insulin Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 0), // V6 = body(0)/was=1 - JournalEntryOtherMarker(0x43, "Other Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // V6 = body(1)/was=0 - EnableSensorAutoCal(0x44, "Enable Sensor AutoCal", PumpHistoryEntryGroup.Glucose), // - // /**/EventUnknown_MM522_0x45(0x45, "Unknown Event 0x45", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x46(0x46, "Unknown Event 0x46", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x47(0x47, "Unknown Event 0x47", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x48(0x48, "Unknown Event 0x48", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x49(0x49, "Unknown Event 0x49", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x4a(0x4a, "Unknown Event 0x4a", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x4b(0x4b, "Unknown Event 0x4b", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_MM522_0x4c(0x4c, "Unknown Event 0x4c", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // -// /**/EventUnknown_0x4d(0x4d, "Unknown Event 0x4d", PumpHistoryEntryGroup.Unknown), // V5: 512: 7, 522: 8 ????NS -// /**/EventUnknown_MM512_0x4e(0x4e, "Unknown Event 0x4e", PumpHistoryEntryGroup.Unknown), // /**/ - BolusWizardSetup512(0x4f, "Bolus Wizard Setup (512)", PumpHistoryEntryGroup.Configuration, 2, 5, 32), // - ChangeSensorSetup2(0x50, "Sensor Setup2", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // Ian50 - /* TODO */Sensor_0x51(0x51, "Unknown Event 0x51", PumpHistoryEntryGroup.Unknown), // - /* TODO */Sensor_0x52(0x52, "Unknown Event 0x52", PumpHistoryEntryGroup.Unknown), // - ChangeSensorAlarmSilenceConfig(0x53, "Sensor Alarm Silence Config", PumpHistoryEntryGroup.Configuration, 2, 5, 1), // 8 - /* TODO */Sensor_0x54(0x54, "Unknown Event 0x54", PumpHistoryEntryGroup.Unknown), // Ian54 - /* TODO */Sensor_0x55(0x55, "Unknown Event 0x55", PumpHistoryEntryGroup.Unknown), // - ChangeSensorRateOfChangeAlertSetup(0x56, "Sensor Rate Of Change Alert Setup", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 - ChangeBolusScrollStepSize(0x57, "Change Bolus Scroll Step Size", PumpHistoryEntryGroup.Configuration), // - BolusWizardSetup(0x5a, "Bolus Wizard Setup (522)", PumpHistoryEntryGroup.Configuration, 2, 5, 117), - // V2: 522+[B=143]; V6: 124, v6: 137, v7: 117/137 [523] - BolusWizard(0x5b, "Bolus Wizard Estimate", PumpHistoryEntryGroup.Configuration, 2, 5, 13), // 15 // - UnabsorbedInsulin(0x5c, "Unabsorbed Insulin", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // head[1] -> body - SaveSettings(0x5d, "Save Settings", PumpHistoryEntryGroup.Configuration), // - ChangeVariableBolus(0x5e, "Change Variable Bolus", PumpHistoryEntryGroup.Configuration), // - ChangeAudioBolus(0x5f, "Easy Bolus Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? - ChangeBGReminderEnable(0x60, "BG Reminder Enable", PumpHistoryEntryGroup.Configuration), // questionable60 - ChangeAlarmClockEnable(0x61, "Alarm Clock Enable", PumpHistoryEntryGroup.Configuration), // - ChangeTempBasalType((byte) 0x62, "Change Basal Type", PumpHistoryEntryGroup.Configuration), // ChangeTempBasalTypePumpEvent - ChangeAlarmNotifyMode(0x63, "Change Alarm Notify Mode", PumpHistoryEntryGroup.Configuration), // - ChangeTimeFormat(0x64, "Change Time Format", PumpHistoryEntryGroup.Configuration), // - ChangeReservoirWarningTime((byte) 0x65, "Change Reservoir Warning Time", PumpHistoryEntryGroup.Configuration), // - ChangeBolusReminderEnable(0x66, "Change Bolus Reminder Enable", PumpHistoryEntryGroup.Configuration), // 9 - SetBolusReminderTime((byte) 0x67, "Change Bolus Reminder Time", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 - DeleteBolusReminderTime((byte) 0x68, "Delete Bolus Reminder Time", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 - BolusReminder(0x69, "Bolus Reminder", PumpHistoryEntryGroup.Configuration, 2, 5, 0), // Ian69 - DeleteAlarmClockTime(0x6a, "Delete Alarm Clock Time", PumpHistoryEntryGroup.Configuration, 2, 5, 7), // 14 - DailyTotals515(0x6c, "Daily Totals (515)", PumpHistoryEntryGroup.Statistic, 1, 2, 35), // v4: 0,0,36. v5: 1,2,33 - DailyTotals522(0x6d, "Daily Totals (522)", PumpHistoryEntryGroup.Statistic, 1, 2, 41), // - DailyTotals523(0x6e, "Daily Totals (523)", PumpHistoryEntryGroup.Statistic, 1, 2, 49), // 1102014-03-17T00:00:00 - ChangeCarbUnits((byte) 0x6f, "Change Carb Units", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM522_0x70((byte) 0x70, "Unknown Event 0x70", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // - BasalProfileStart(0x7b, "Basal Profile Start", PumpHistoryEntryGroup.Basal, 2, 5, 3), // // 722 - ChangeWatchdogEnable((byte) 0x7c, "Change Watchdog Enable", PumpHistoryEntryGroup.Configuration), // - ChangeOtherDeviceID((byte) 0x7d, "Change Other Device ID", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // - ChangeWatchdogMarriageProfile(0x81, "Change Watchdog Marriage Profile", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 - DeleteOtherDeviceID(0x82, "Delete Other Device ID", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // - ChangeCaptureEventEnable(0x83, "Change Capture Event Enable", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM512_0x88(0x88, "Unknown Event 0x88", PumpHistoryEntryGroup.Unknown), // -// /**/EventUnknown_MM512_0x94(0x94, "Unknown Event 0x94", PumpHistoryEntryGroup.Unknown), // - /**/ IanA8(0xA8, "Ian A8 (Unknown)", PumpHistoryEntryGroup.Unknown, 10, 5, 0), // - // /**/EventUnknown_MM522_0xE8(0xe8, "Unknown Event 0xE8", PumpHistoryEntryGroup.Unknown, 2, 5, 25), // - // F0 - F3 are not in go code, but they are in GGC one and thet are used - ReadOtherDevicesIDs(0xf0, "Read Other Devices IDs", PumpHistoryEntryGroup.Configuration), // ? - ReadCaptureEventEnabled(0xf1, "Read Capture Event Enabled", PumpHistoryEntryGroup.Configuration), // ? - ChangeCaptureEventEnable2(0xf2, "Change Capture Event Enable2", PumpHistoryEntryGroup.Configuration), // ? - ReadOtherDevicesStatus(0xf3, "Read Other Devices Status", PumpHistoryEntryGroup.Configuration), // ? - - TempBasalCombined(0xfe, "TBR", PumpHistoryEntryGroup.Basal), // - UnknownBasePacket(0xff, "Unknown Base Packet", PumpHistoryEntryGroup.Unknown); - - private static final Map opCodeMap = new HashMap<>(); - - static { - for (PumpHistoryEntryType type : values()) { - opCodeMap.put(type.opCode, type); - } - - setSpecialRulesForEntryTypes(); - } - - private final int opCode; - private final String description; - private final int headLength; - private final int dateLength; - // private MinimedDeviceType deviceType; - private final int bodyLength; - private final int totalLength; - // special rules need to be put in list from highest to lowest (e.g.: - // 523andHigher=12, 515andHigher=10 and default (set in cnstr) would be 8) - private List specialRulesHead; - private List specialRulesBody; - private boolean hasSpecialRules = false; - private final PumpHistoryEntryGroup group; - - - PumpHistoryEntryType(int opCode, String name, PumpHistoryEntryGroup group) { - this(opCode, name, group, 2, 5, 0); - } - - - PumpHistoryEntryType(int opCode, PumpHistoryEntryGroup group) { - this(opCode, null, group, 2, 5, 0); - } - - - PumpHistoryEntryType(int opCode, PumpHistoryEntryGroup group, int head, int date, int body) { - this(opCode, null, group, head, date, body); - } - - - PumpHistoryEntryType(int opCode, String name, PumpHistoryEntryGroup group, int head, int date, int body) { - this.opCode = (byte) opCode; - this.description = name; - this.headLength = head; - this.dateLength = date; - this.bodyLength = body; - this.totalLength = (head + date + body); - this.group = group; - } - - - static void setSpecialRulesForEntryTypes() { - EndResultTotals.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 3)); - Bolus.addSpecialRuleHead(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 8)); - BolusWizardSetup.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 137)); - BolusWizard.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 15)); - BolusReminder.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 2)); - ChangeSensorSetup2.addSpecialRuleBody(new SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 34)); - } - - - public static PumpHistoryEntryType getByCode(int opCode) { - if (opCodeMap.containsKey(opCode)) { - return opCodeMap.get(opCode); - } else { - return PumpHistoryEntryType.UnknownBasePacket; - } - } - - - // - // private PumpHistoryEntryType(int opCode, String name, int head, int date, - // int body) - // { - // this.opCode = (byte) opCode; - // this.description = name; - // this.headLength = head; - // this.dateLength = date; - // this.bodyLength = body; - // this.totalLength = (head + date + body); - // } - // - - public static boolean isAAPSRelevantEntry(PumpHistoryEntryType entryType) { - return (entryType == PumpHistoryEntryType.Bolus || // Treatments - entryType == PumpHistoryEntryType.TempBasalRate || // - entryType == PumpHistoryEntryType.TempBasalDuration || // - - entryType == PumpHistoryEntryType.Prime || // Pump Status Change - entryType == PumpHistoryEntryType.SuspendPump || // - entryType == PumpHistoryEntryType.ResumePump || // - entryType == PumpHistoryEntryType.Rewind || // - entryType == PumpHistoryEntryType.NoDeliveryAlarm || // no delivery - entryType == PumpHistoryEntryType.BasalProfileStart || // - - entryType == PumpHistoryEntryType.ChangeTime || // Time Change - entryType == PumpHistoryEntryType.NewTimeSet || // - - entryType == PumpHistoryEntryType.ChangeBasalPattern || // Configuration - entryType == PumpHistoryEntryType.ClearSettings || // - entryType == PumpHistoryEntryType.SaveSettings || // - entryType == PumpHistoryEntryType.ChangeMaxBolus || // - entryType == PumpHistoryEntryType.ChangeMaxBasal || // - entryType == PumpHistoryEntryType.ChangeTempBasalType || // - - entryType == PumpHistoryEntryType.ChangeBasalProfile_NewProfile || // Basal profile - - entryType == PumpHistoryEntryType.DailyTotals515 || // Daily Totals - entryType == PumpHistoryEntryType.DailyTotals522 || // - entryType == PumpHistoryEntryType.DailyTotals523 || // - entryType == PumpHistoryEntryType.EndResultTotals); - } - - - public static boolean isRelevantEntry() { - return true; - } - - - public int getCode() { - return this.opCode; - } - - - public int getTotalLength(MedtronicDeviceType medtronicDeviceType) { - if (hasSpecialRules()) { - return getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + getDateLength(); - } else { - return totalLength; - } - } - - - private boolean hasSpecialRules() { - return hasSpecialRules; - } - - - void addSpecialRuleHead(SpecialRule rule) { - if (isEmpty(specialRulesHead)) { - specialRulesHead = new ArrayList<>(); - } - - specialRulesHead.add(rule); - hasSpecialRules = true; - } - - - void addSpecialRuleBody(SpecialRule rule) { - if (isEmpty(specialRulesBody)) { - specialRulesBody = new ArrayList<>(); - } - - specialRulesBody.add(rule); - hasSpecialRules = true; - } - - - public int getOpCode() { - return opCode; - } - - - public String getDescription() { - return this.description == null ? name() : this.description; - } - - - public int getHeadLength(MedtronicDeviceType medtronicDeviceType) { - if (hasSpecialRules) { - if (isNotEmpty(specialRulesHead)) { - return determineSizeByRule(medtronicDeviceType, headLength, specialRulesHead); - } else { - return headLength; - } - } else { - return headLength; - } - } - - - public int getDateLength() { - return dateLength; - } - - - public int getBodyLength(MedtronicDeviceType medtronicDeviceType) { - if (hasSpecialRules) { - if (isNotEmpty(specialRulesBody)) { - return determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody); - } else { - return bodyLength; - } - } else { - return bodyLength; - } - } - - - private boolean isNotEmpty(List list) { - return list != null && !list.isEmpty(); - } - - - private boolean isEmpty(List list) { - return list == null || list.isEmpty(); - } - - - // byte[] dh = { 2, 3 }; - - private int determineSizeByRule(MedtronicDeviceType medtronicDeviceType, int defaultValue, List rules) { - int size = defaultValue; - - for (SpecialRule rule : rules) { - if (MedtronicDeviceType.isSameDevice(medtronicDeviceType, rule.deviceType)) { - size = rule.size; - break; - } - } - - return size; - } - - - public PumpHistoryEntryGroup getGroup() { - - return group; - } - - public static class SpecialRule { - - MedtronicDeviceType deviceType; - int size; - - - SpecialRule(MedtronicDeviceType deviceType, int size) { - this.deviceType = deviceType; - this.size = size; - } - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt new file mode 100644 index 0000000000..3f2a4a0c40 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt @@ -0,0 +1,323 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump + +import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType +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 PumpHistoryEntryType // implements CodeEnum +@JvmOverloads constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int = 2, date: Int = 5, body: Int = 0) { + + // all commented out are probably not the real items + None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), Bolus(0x01, "Bolus", PumpHistoryEntryGroup.Bolus, 4, 5, 0), // 523+[H=8] 9/13 + Prime(0x03, "Prime", PumpHistoryEntryGroup.Prime, 5, 5, 0), // + + // /**/EventUnknown_MM522_0x05((byte) 0x05, "Unknown Event 0x05", PumpHistoryEntryGroup.Unknown, 2, 5, 28), // + NoDeliveryAlarm(0x06, "No Delivery", PumpHistoryEntryGroup.Alarm, 4, 5, 0), // + EndResultTotals(0x07, "End Result Totals", PumpHistoryEntryGroup.Statistic, 5, 2, 0), ChangeBasalProfile_OldProfile(0x08, "Change Basal Profile (Old)", PumpHistoryEntryGroup.Basal, 2, 5, 145), ChangeBasalProfile_NewProfile(0x09, "Change Basal Profile (New)", PumpHistoryEntryGroup.Basal, 2, 5, 145), // + + // /**/EventUnknown_MM512_0x10(0x10, "Unknown Event 0x10", PumpHistoryEntryGroup.Unknown), // 29, 5, 0 + CalBGForPH(0x0a, "BG Capture", PumpHistoryEntryGroup.Glucose), // + SensorAlert(0x0b, "Sensor Alert", PumpHistoryEntryGroup.Alarm, 3, 5, 0), // Ian08 + ClearAlarm(0x0c, "Clear Alarm", PumpHistoryEntryGroup.Alarm, 2, 5, 0), // 2,5,4 + ChangeBasalPattern(0x14, "Change Basal Pattern", PumpHistoryEntryGroup.Basal), // + TempBasalDuration(0x16, "TBR Duration", PumpHistoryEntryGroup.Basal), // + ChangeTime(0x17, "Change Time", PumpHistoryEntryGroup.Configuration), // + NewTimeSet(0x18, "New Time Set", PumpHistoryEntryGroup.Notification), // + LowBattery(0x19, "LowBattery", PumpHistoryEntryGroup.Notification), // + BatteryChange(0x1a, "Battery Change", PumpHistoryEntryGroup.Notification), // + SetAutoOff(0x1b, "Set Auto Off", PumpHistoryEntryGroup.Configuration), // + SuspendPump(0x1e, "Suspend", PumpHistoryEntryGroup.Basal), // + ResumePump(0x1f, "Resume", PumpHistoryEntryGroup.Basal), // + SelfTest(0x20, "Self Test", PumpHistoryEntryGroup.Statistic), // + Rewind(0x21, "Rewind", PumpHistoryEntryGroup.Prime), // + ClearSettings(0x22, "Clear Settings", PumpHistoryEntryGroup.Configuration), // + ChangeChildBlockEnable(0x23, "Change Child Block Enable", PumpHistoryEntryGroup.Configuration), // + ChangeMaxBolus(0x24, "Change Max Bolus", PumpHistoryEntryGroup.Configuration), // + + // /**/EventUnknown_MM522_0x25(0x25, "Unknown Event 0x25", PumpHistoryEntryGroup.Unknown), // 8? + EnableDisableRemote(0x26, "Enable/Disable Remote", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // 2, 5, 14 V6:2,5,14 + ChangeRemoteId(0x27, "Change Remote ID", PumpHistoryEntryGroup.Configuration), // ?? + ChangeMaxBasal(0x2c, "Change Max Basal", PumpHistoryEntryGroup.Configuration), // + BolusWizardEnabled(0x2d, "Bolus Wizard Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? + + /* TODO */ + EventUnknown_MM512_0x2e(0x2e, "Unknown Event 0x2e", PumpHistoryEntryGroup.Unknown, 2, 5, 100), // + BolusWizard512(0x2f, "Bolus Wizard (512)", PumpHistoryEntryGroup.Bolus, 2, 5, 12), // + UnabsorbedInsulin512(0x30, "Unabsorbed Insulin (512)", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // FIXME + ChangeBGReminderOffset(0x31, "Change BG Reminder Offset", PumpHistoryEntryGroup.Configuration), // + ChangeAlarmClockTime(0x32, "Change Alarm Clock Time", PumpHistoryEntryGroup.Configuration), // + TempBasalRate(0x33, "TBR Rate", PumpHistoryEntryGroup.Basal, 2, 5, 1), // + LowReservoir(0x34, "Low Reservoir", PumpHistoryEntryGroup.Notification), // + ChangeAlarmClock(0x35, "Change Alarm Clock", PumpHistoryEntryGroup.Configuration), // + ChangeMeterId(0x36, "Change Meter ID", PumpHistoryEntryGroup.Configuration), // + + // /**/EventUnknown_MM512_0x37(0x37, "Unknown Event 0x37", PumpHistoryEntryGroup.Unknown), // V:MM512 + // /**/EventUnknown_MM512_0x38(0x38, "Unknown Event 0x38", PumpHistoryEntryGroup.Unknown), // + BGReceived512(0x39, "BG Received (512)", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // + + /* TODO */ + ConfirmInsulinChange(0x3a, "Confirm Insulin Change", PumpHistoryEntryGroup.Unknown), // + SensorStatus(0x3b, "Sensor Status", PumpHistoryEntryGroup.Glucose), // + ChangeParadigmID(0x3c, "Change Paradigm ID", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // V3 ? V6: 2,5,14 ?? is it this length or just 7 + + // EventUnknown_MM512_0x3D(0x3d, "Unknown Event 0x3D", PumpHistoryEntryGroup.Unknown), // + // EventUnknown_MM512_0x3E(0x3e, "Unknown Event 0x3E", PumpHistoryEntryGroup.Unknown), // + BGReceived(0x3f, "BG Received", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // Ian3F + JournalEntryMealMarker(0x40, "Meal Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 2), // is size just 7??? V6 + JournalEntryExerciseMarker(0x41, "Exercise Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // ?? + JournalEntryInsulinMarker(0x42, "Insulin Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 0), // V6 = body(0)/was=1 + JournalEntryOtherMarker(0x43, "Other Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // V6 = body(1)/was=0 + EnableSensorAutoCal(0x44, "Enable Sensor AutoCal", PumpHistoryEntryGroup.Glucose), // + + // /**/EventUnknown_MM522_0x45(0x45, "Unknown Event 0x45", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x46(0x46, "Unknown Event 0x46", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x47(0x47, "Unknown Event 0x47", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x48(0x48, "Unknown Event 0x48", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x49(0x49, "Unknown Event 0x49", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x4a(0x4a, "Unknown Event 0x4a", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x4b(0x4b, "Unknown Event 0x4b", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_MM522_0x4c(0x4c, "Unknown Event 0x4c", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + // /**/EventUnknown_0x4d(0x4d, "Unknown Event 0x4d", PumpHistoryEntryGroup.Unknown), // V5: 512: 7, 522: 8 ????NS + // /**/EventUnknown_MM512_0x4e(0x4e, "Unknown Event 0x4e", PumpHistoryEntryGroup.Unknown), // /**/ + BolusWizardSetup512(0x4f, "Bolus Wizard Setup (512)", PumpHistoryEntryGroup.Configuration, 2, 5, 32), // + ChangeSensorSetup2(0x50, "Sensor Setup2", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // Ian50 + + /* TODO */ + Sensor_0x51(0x51, "Unknown Event 0x51", PumpHistoryEntryGroup.Unknown), // + + /* TODO */ + Sensor_0x52(0x52, "Unknown Event 0x52", PumpHistoryEntryGroup.Unknown), // + ChangeSensorAlarmSilenceConfig(0x53, "Sensor Alarm Silence Config", PumpHistoryEntryGroup.Configuration, 2, 5, 1), // 8 + + /* TODO */ + Sensor_0x54(0x54, "Unknown Event 0x54", PumpHistoryEntryGroup.Unknown), // Ian54 + + /* TODO */ + Sensor_0x55(0x55, "Unknown Event 0x55", PumpHistoryEntryGroup.Unknown), // + ChangeSensorRateOfChangeAlertSetup(0x56, "Sensor Rate Of Change Alert Setup", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 + ChangeBolusScrollStepSize(0x57, "Change Bolus Scroll Step Size", PumpHistoryEntryGroup.Configuration), // + BolusWizardSetup(0x5a, "Bolus Wizard Setup (522)", PumpHistoryEntryGroup.Configuration, 2, 5, 117), // V2: 522+[B=143]; V6: 124, v6: 137, v7: 117/137 [523] + BolusWizard(0x5b, "Bolus Wizard Estimate", PumpHistoryEntryGroup.Configuration, 2, 5, 13), // 15 // + UnabsorbedInsulin(0x5c, "Unabsorbed Insulin", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // head[1] -> body + SaveSettings(0x5d, "Save Settings", PumpHistoryEntryGroup.Configuration), // + ChangeVariableBolus(0x5e, "Change Variable Bolus", PumpHistoryEntryGroup.Configuration), // + ChangeAudioBolus(0x5f, "Easy Bolus Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? + ChangeBGReminderEnable(0x60, "BG Reminder Enable", PumpHistoryEntryGroup.Configuration), // questionable60 + ChangeAlarmClockEnable(0x61, "Alarm Clock Enable", PumpHistoryEntryGroup.Configuration), // + ChangeTempBasalType(0x62.toByte(), "Change Basal Type", PumpHistoryEntryGroup.Configuration), // ChangeTempBasalTypePumpEvent + ChangeAlarmNotifyMode(0x63, "Change Alarm Notify Mode", PumpHistoryEntryGroup.Configuration), // + ChangeTimeFormat(0x64, "Change Time Format", PumpHistoryEntryGroup.Configuration), // + ChangeReservoirWarningTime(0x65.toByte(), "Change Reservoir Warning Time", PumpHistoryEntryGroup.Configuration), // + ChangeBolusReminderEnable(0x66, "Change Bolus Reminder Enable", PumpHistoryEntryGroup.Configuration), // 9 + SetBolusReminderTime(0x67.toByte(), "Change Bolus Reminder Time", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 + DeleteBolusReminderTime(0x68.toByte(), "Delete Bolus Reminder Time", PumpHistoryEntryGroup.Configuration, 2, 5, 2), // 9 + BolusReminder(0x69, "Bolus Reminder", PumpHistoryEntryGroup.Configuration, 2, 5, 0), // Ian69 + DeleteAlarmClockTime(0x6a, "Delete Alarm Clock Time", PumpHistoryEntryGroup.Configuration, 2, 5, 7), // 14 + DailyTotals515(0x6c, "Daily Totals (515)", PumpHistoryEntryGroup.Statistic, 1, 2, 35), // v4: 0,0,36. v5: 1,2,33 + DailyTotals522(0x6d, "Daily Totals (522)", PumpHistoryEntryGroup.Statistic, 1, 2, 41), // + DailyTotals523(0x6e, "Daily Totals (523)", PumpHistoryEntryGroup.Statistic, 1, 2, 49), // 1102014-03-17T00:00:00 + ChangeCarbUnits(0x6f.toByte(), "Change Carb Units", PumpHistoryEntryGroup.Configuration), // + + // /**/EventUnknown_MM522_0x70((byte) 0x70, "Unknown Event 0x70", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // + BasalProfileStart(0x7b, "Basal Profile Start", PumpHistoryEntryGroup.Basal, 2, 5, 3), // // 722 + ChangeWatchdogEnable(0x7c, "Change Watchdog Enable", PumpHistoryEntryGroup.Configuration), // + ChangeOtherDeviceID(0x7d, "Change Other Device ID", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // + ChangeWatchdogMarriageProfile(0x81.toByte(), "Change Watchdog Marriage Profile", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 + DeleteOtherDeviceID(0x82.toByte(), "Delete Other Device ID", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // + ChangeCaptureEventEnable(0x83.toByte(), "Change Capture Event Enable", PumpHistoryEntryGroup.Configuration), // + + // /**/EventUnknown_MM512_0x88(0x88, "Unknown Event 0x88", PumpHistoryEntryGroup.Unknown), // + // /**/EventUnknown_MM512_0x94(0x94, "Unknown Event 0x94", PumpHistoryEntryGroup.Unknown), // + /**/ + IanA8(0xA8.toByte(), "Ian A8 (Unknown)", PumpHistoryEntryGroup.Unknown, 10, 5, 0), // + + // /**/EventUnknown_MM522_0xE8(0xe8, "Unknown Event 0xE8", PumpHistoryEntryGroup.Unknown, 2, 5, 25), // + // F0 - F3 are not in go code, but they are in GGC one and thet are used + ReadOtherDevicesIDs(0xf0.toByte(), "Read Other Devices IDs", PumpHistoryEntryGroup.Configuration), // ? + ReadCaptureEventEnabled(0xf1.toByte(), "Read Capture Event Enabled", PumpHistoryEntryGroup.Configuration), // ? + ChangeCaptureEventEnable2(0xf2.toByte(), "Change Capture Event Enable2", PumpHistoryEntryGroup.Configuration), // ? + ReadOtherDevicesStatus(0xf3.toByte(), "Read Other Devices Status", PumpHistoryEntryGroup.Configuration), // ? + TempBasalCombined(0xfe.toByte(), "TBR", PumpHistoryEntryGroup.Basal), // + UnknownBasePacket(0xff.toByte(), "Unknown Base Packet", PumpHistoryEntryGroup.Unknown); + + companion object { + private val opCodeMap: MutableMap = HashMap() + fun setSpecialRulesForEntryTypes() { + EndResultTotals.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 3)) + Bolus.addSpecialRuleHead(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 8)) + BolusWizardSetup.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 137)) + BolusWizard.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 15)) + BolusReminder.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 2)) + ChangeSensorSetup2.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 34)) + } + + @JvmStatic fun getByCode(opCode: Byte): PumpHistoryEntryType? { + return if (opCodeMap.containsKey(opCode)) { + opCodeMap[opCode] + } else { + UnknownBasePacket + } + } + + // + // private PumpHistoryEntryType(int opCode, String name, int head, int date, + // int body) + // { + // this.opCode = (byte) opCode; + // this.description = name; + // this.headLength = head; + // this.dateLength = date; + // this.bodyLength = body; + // this.totalLength = (head + date + body); + // } + // + fun isAAPSRelevantEntry(entryType: PumpHistoryEntryType): Boolean { + return entryType == Bolus || // Treatments + entryType == TempBasalRate || // + entryType == TempBasalDuration || // + entryType == Prime || // Pump Status Change + entryType == SuspendPump || // + entryType == ResumePump || // + entryType == Rewind || // + entryType == NoDeliveryAlarm || // no delivery + entryType == BasalProfileStart || // + entryType == ChangeTime || // Time Change + entryType == NewTimeSet || // + entryType == ChangeBasalPattern || // Configuration + entryType == ClearSettings || // + entryType == SaveSettings || // + entryType == ChangeMaxBolus || // + entryType == ChangeMaxBasal || // + entryType == ChangeTempBasalType || // + entryType == ChangeBasalProfile_NewProfile || // Basal profile + entryType == DailyTotals515 || // Daily Totals + entryType == DailyTotals522 || // + entryType == DailyTotals523 || // + entryType == EndResultTotals + } + + val isRelevantEntry: Boolean + get() = true + + init { + for (type in values()) { + opCodeMap[type.code] = type + } + setSpecialRulesForEntryTypes() + } + } + + val code: Byte + private val description: String? + private val headLength: Int + val dateLength: Int + + // private MinimedDeviceType deviceType; + private val bodyLength: Int + private val totalLength: Int + + // special rules need to be put in list from highest to lowest (e.g.: + // 523andHigher=12, 515andHigher=10 and default (set in cnstr) would be 8) + private var specialRulesHead: MutableList? = null + private var specialRulesBody: MutableList? = null + private var hasSpecialRules = false + val group: PumpHistoryEntryGroup + + 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) {} + + fun getTotalLength(medtronicDeviceType: MedtronicDeviceType?): Int { + return if (hasSpecialRules()) { + getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + dateLength + } else { + totalLength + } + } + + private fun hasSpecialRules(): Boolean { + return hasSpecialRules + } + + fun addSpecialRuleHead(rule: SpecialRule) { + if (isEmpty(specialRulesHead)) { + specialRulesHead = ArrayList() + } + specialRulesHead!!.add(rule) + hasSpecialRules = true + } + + fun addSpecialRuleBody(rule: SpecialRule) { + if (isEmpty(specialRulesBody)) { + specialRulesBody = ArrayList() + } + specialRulesBody!!.add(rule) + hasSpecialRules = true + } + + fun getDescription(): String { + return description ?: name + } + + fun getHeadLength(medtronicDeviceType: MedtronicDeviceType?): Int { + return if (hasSpecialRules) { + if (isNotEmpty(specialRulesHead)) { + determineSizeByRule(medtronicDeviceType, headLength, specialRulesHead) + } else { + headLength + } + } else { + headLength + } + } + + fun getBodyLength(medtronicDeviceType: MedtronicDeviceType?): Int { + return if (hasSpecialRules) { + if (isNotEmpty(specialRulesBody)) { + determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody) + } else { + bodyLength + } + } else { + bodyLength + } + } + + private fun isNotEmpty(list: List<*>?): Boolean { + return list != null && !list.isEmpty() + } + + private fun isEmpty(list: List<*>?): Boolean { + return list == null || list.isEmpty() + } + + // byte[] dh = { 2, 3 }; + private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType?, defaultValue: Int, rules: List?): Int { + var size = defaultValue + for (rule in rules!!) { + if (MedtronicDeviceType.isSameDevice(medtronicDeviceType, rule.deviceType)) { + size = rule.size + break + } + } + return size + } + + class SpecialRule internal constructor(var deviceType: MedtronicDeviceType, var size: Int) + + init { + this.code = opCode //as Byte.toInt() + description = name + headLength = head + dateLength = date + bodyLength = body + totalLength = head + date + body + this.group = group + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java deleted file mode 100644 index 4bb67cfb3e..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.java +++ /dev/null @@ -1,177 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; - -/** - * History page contains data, sorted from newest to oldest (0=newest..n=oldest) - *

- * Created by andy on 9/23/18. - */ -public class PumpHistoryResult { - - private final AAPSLogger aapsLogger; - - private boolean searchFinished = false; - private final PumpHistoryEntry searchEntry = null; - private Long searchDate = null; - private SearchType searchType = SearchType.None; - public List unprocessedEntries; - public List validEntries; - - - public PumpHistoryResult(AAPSLogger aapsLogger, PumpHistoryEntry searchEntry, Long targetDate) { - this.aapsLogger = aapsLogger; - if (searchEntry != null) { - /* - * this.searchEntry = searchEntry; - * this.searchType = SearchType.LastEntry; - * aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Search parameters: Last Entry: " + searchEntry.atechDateTime + " type=" - * + searchEntry.getEntryType().name()); - */ - this.searchDate = searchEntry.atechDateTime; - this.searchType = SearchType.Date; - aapsLogger.debug(LTag.PUMPCOMM, "PumpHistoryResult. Search parameters: Date(with searchEntry): " + targetDate); - } else if (targetDate != null) { - this.searchDate = targetDate; - this.searchType = SearchType.Date; - aapsLogger.debug(LTag.PUMPCOMM, "PumpHistoryResult. Search parameters: Date: " + targetDate); - } - - // this.unprocessedEntries = new ArrayList<>(); - this.validEntries = new ArrayList<>(); - } - - - public void addHistoryEntries(List entries, int page) { - this.unprocessedEntries = entries; - //aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries)); - processEntries(); - } - - // TODO Bug #145 need to check if we had timeChange that went -1, that situation needs to be evaluated separately - public void processEntries() { - int olderEntries = 0; - - Collections.reverse(this.unprocessedEntries); - - switch (searchType) { - case None: - //aapsLogger.debug(LTag.PUMPCOMM,"PE. None search"); - this.validEntries.addAll(this.unprocessedEntries); - break; - - case LastEntry: { - aapsLogger.debug(LTag.PUMPCOMM, "PE. Last entry search"); - - //Collections.sort(this.unprocessedEntries, new PumpHistoryEntry.Comparator()); - - aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: " + searchEntry.atechDateTime); - - Long date = searchEntry.atechDateTime; - - for (PumpHistoryEntry unprocessedEntry : unprocessedEntries) { - - if (unprocessedEntry.equals(searchEntry)) { - //aapsLogger.debug(LTag.PUMPCOMM,"PE. Item found {}.", unprocessedEntry); - searchFinished = true; - break; - } - - //aapsLogger.debug(LTag.PUMPCOMM,"PE. Entry {} added.", unprocessedEntry); - this.validEntries.add(unprocessedEntry); - } - } - break; - case Date: { - aapsLogger.debug(LTag.PUMPCOMM, "PE. Date search: Search date: " + this.searchDate); - - - for (PumpHistoryEntry unprocessedEntry : unprocessedEntries) { - - if (unprocessedEntry.atechDateTime == null || unprocessedEntry.atechDateTime == 0) { - aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: Entry with no date: " + unprocessedEntry); - continue; - } - - if (unprocessedEntry.isAfter(this.searchDate)) { - this.validEntries.add(unprocessedEntry); - } else { -// aapsLogger.debug(LTag.PUMPCOMM,"PE. PumpHistoryResult. Not after.. Unprocessed Entry [year={},entry={}]", -// DateTimeUtil.getYear(unprocessedEntry.atechDateTime), unprocessedEntry); - if (DateTimeUtil.getYear(unprocessedEntry.atechDateTime) > 2015) - olderEntries++; - } - } - - if (olderEntries > 0) { - //Collections.sort(this.validEntries, new PumpHistoryEntry.Comparator()); - - searchFinished = true; - } - } - break; - - } // switch - - //aapsLogger.debug(LTag.PUMPCOMM,"PE. Valid Entries: {}", validEntries); - } - - - public String toString() { - return "PumpHistoryResult [unprocessed=" + (unprocessedEntries != null ? "" + unprocessedEntries.size() : "0") + // - ", valid=" + (validEntries != null ? "" + validEntries.size() : "0") + // - ", searchEntry=" + searchEntry + // - ", searchDate=" + searchDate + // - ", searchType=" + searchType + // - ", searchFinished=" + searchFinished + // - "]"; - - } - - - /** - * Return latest entry (entry with highest date time) - * - * @return - */ - public PumpHistoryEntry getLatestEntry() { - if (this.validEntries == null || this.validEntries.size() == 0) - return null; - else { - return this.validEntries.get(0); - // PumpHistoryEntry pumpHistoryEntry = this.validEntries.get(0); - // - // if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.EndResultTotals) - // return pumpHistoryEntry; - // else - // return this.validEntries.get(1); - } - } - - - public boolean isSearchRequired() { - return searchType != SearchType.None; - } - - - public boolean isSearchFinished() { - return searchFinished; - } - - - public List getValidEntries() { - return validEntries; - } - - enum SearchType { - None, // - LastEntry, // - Date - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt new file mode 100644 index 0000000000..0ab0e7e05e --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt @@ -0,0 +1,144 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump + +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import java.util.* + +/** + * History page contains data, sorted from newest to oldest (0=newest..n=oldest) + * + * + * Created by andy on 9/23/18. + */ +class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHistoryEntry?, targetDate: Long?) { + + var isSearchFinished = false + private set + private val searchEntry: PumpHistoryEntry? = null + private var searchDate: Long? = null + private var searchType = SearchType.None + @JvmField var unprocessedEntries: List? = null + @JvmField var validEntries: MutableList? + fun addHistoryEntries(entries: List?, page: Int) { + unprocessedEntries = entries + //aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries)); + processEntries() + } + + // TODO Bug #145 need to check if we had timeChange that went -1, that situation needs to be evaluated separately + fun processEntries() { + var olderEntries = 0 + Collections.reverse(unprocessedEntries) + when (searchType) { + SearchType.None -> //aapsLogger.debug(LTag.PUMPCOMM,"PE. None search"); + validEntries!!.addAll(unprocessedEntries!!) + + SearchType.LastEntry -> { + aapsLogger.debug(LTag.PUMPCOMM, "PE. Last entry search") + + //Collections.sort(this.unprocessedEntries, new PumpHistoryEntry.Comparator()); + aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: " + searchEntry!!.atechDateTime) + val date = searchEntry.atechDateTime + for (unprocessedEntry in unprocessedEntries!!) { + if (unprocessedEntry!!.equals(searchEntry)) { + //aapsLogger.debug(LTag.PUMPCOMM,"PE. Item found {}.", unprocessedEntry); + isSearchFinished = true + break + } + + //aapsLogger.debug(LTag.PUMPCOMM,"PE. Entry {} added.", unprocessedEntry); + validEntries!!.add(unprocessedEntry) + } + } + + SearchType.Date -> { + aapsLogger.debug(LTag.PUMPCOMM, "PE. Date search: Search date: " + searchDate) + for (unprocessedEntry in unprocessedEntries!!) { + if (unprocessedEntry!!.atechDateTime == null || unprocessedEntry.atechDateTime == 0L) { + aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: Entry with no date: $unprocessedEntry") + continue + } + if (unprocessedEntry.isAfter(searchDate!!)) { + validEntries!!.add(unprocessedEntry) + } else { +// aapsLogger.debug(LTag.PUMPCOMM,"PE. PumpHistoryResult. Not after.. Unprocessed Entry [year={},entry={}]", +// DateTimeUtil.getYear(unprocessedEntry.atechDateTime), unprocessedEntry); + if (DateTimeUtil.getYear(unprocessedEntry.atechDateTime) > 2015) olderEntries++ + } + } + if (olderEntries > 0) { + //Collections.sort(this.validEntries, new PumpHistoryEntry.Comparator()); + isSearchFinished = true + } + } + } + + //aapsLogger.debug(LTag.PUMPCOMM,"PE. Valid Entries: {}", validEntries); + } + + override fun toString(): String { + return "PumpHistoryResult [unprocessed=" + (if (unprocessedEntries != null) "" + unprocessedEntries!!.size else "0") + // + ", valid=" + (if (validEntries != null) "" + validEntries!!.size else "0") + // + ", searchEntry=" + searchEntry + // + ", searchDate=" + searchDate + // + ", searchType=" + searchType + // + ", 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 + */ + val latestEntry: PumpHistoryEntry? + get() = if (validEntries == null || validEntries!!.size == 0) null else { + 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? { + return validEntries + } + + internal enum class SearchType { + None, // + LastEntry, // + Date + } + + init { + if (searchEntry != null) { + /* + * this.searchEntry = searchEntry; + * this.searchType = SearchType.LastEntry; + * aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Search parameters: Last Entry: " + searchEntry.atechDateTime + " type=" + * + searchEntry.getEntryType().name()); + */ + searchDate = searchEntry.atechDateTime + searchType = SearchType.Date + aapsLogger.debug(LTag.PUMPCOMM, "PumpHistoryResult. Search parameters: Date(with searchEntry): $targetDate") + } else if (targetDate != null) { + searchDate = targetDate + searchType = SearchType.Date + aapsLogger.debug(LTag.PUMPCOMM, "PumpHistoryResult. Search parameters: Date: $targetDate") + } + + // this.unprocessedEntries = new ArrayList<>(); + validEntries = ArrayList() + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java index 697b74aa74..ae15a51c07 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java @@ -74,15 +74,15 @@ public class DailyTotalsDTO { break; case DailyTotals515: - decodeDailyTotals515(entry.getBody()); + decodeDailyTotals515(entry.body); break; case DailyTotals522: - decodeDailyTotals522(entry.getBody()); + decodeDailyTotals522(entry.body); break; case DailyTotals523: - decodeDailyTotals523(entry.getBody()); + decodeDailyTotals523(entry.body); break; default: @@ -96,18 +96,18 @@ public class DailyTotalsDTO { private void setDisplayable() { if (this.insulinBasal == null) { - this.entry.setDisplayableValue("Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2)); + this.entry.displayableValue = "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)); + this.entry.displayableValue = "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; + double totals = ByteUtil.toInt((int) entry.head[0], (int) entry.head[1], (int) entry.head[2], + (int) entry.head[3], ByteUtil.BitConversion.BIG_ENDIAN) * 0.025d; this.insulinTotal = totals; diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java index fc986f4f83..a2ce6c00e7 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java @@ -59,7 +59,7 @@ public class MedtronicHistoryActivity extends NoSplashAppCompatActivity { this.filteredHistoryList.addAll(list); } else { for (PumpHistoryEntry pumpHistoryEntry : list) { - if (pumpHistoryEntry.getEntryType().getGroup() == group) { + if (pumpHistoryEntry.getEntryType().group == group) { this.filteredHistoryList.add(pumpHistoryEntry); } } @@ -214,7 +214,7 @@ public class MedtronicHistoryActivity extends NoSplashAppCompatActivity { if (record != null) { holder.timeView.setText(record.getDateTimeString()); holder.typeView.setText(record.getEntryType().getDescription()); - holder.valueView.setText(record.getDisplayableValue()); + holder.valueView.setText(record.displayableValue); } } diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.java deleted file mode 100644 index 70a484d5d6..0000000000 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.java +++ /dev/null @@ -1,66 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.common.defs; - -import java.util.ArrayList; -import java.util.List; - - -import info.nightscout.androidaps.core.R; -import info.nightscout.androidaps.utils.resources.ResourceHelper; - - -/** - * 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} - */ - -public enum PumpHistoryEntryGroup { - - All(R.string.history_group_all), - Bolus(R.string.history_group_bolus), - Basal(R.string.history_group_basal), - Prime(R.string.history_group_prime), - Configuration(R.string.history_group_configuration), - Alarm(R.string.history_group_alarm), - Glucose(R.string.history_group_glucose), - Notification(R.string.history_group_notification), - Statistic(R.string.history_group_statistic), - Unknown(R.string.history_group_unknown), - ; - - private final int resourceId; - private String translated; - - private static List translatedList; - - PumpHistoryEntryGroup(int resourceId) { - this.resourceId = resourceId; - } - - private static void doTranslation(ResourceHelper resourceHelper) { - translatedList = new ArrayList<>(); - - for (PumpHistoryEntryGroup pumpHistoryEntryGroup : values()) { - pumpHistoryEntryGroup.translated = resourceHelper.gs(pumpHistoryEntryGroup.resourceId); - translatedList.add(pumpHistoryEntryGroup); - } - } - - public static List getTranslatedList(ResourceHelper resourceHelper) { - if (translatedList == null) doTranslation(resourceHelper); - return translatedList; - } - - public int getResourceId() { - return resourceId; - } - - public String getTranslated() { - return translated; - } - - public String toString() { - return this.translated; - } -} diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt new file mode 100644 index 0000000000..8b856d7036 --- /dev/null +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt @@ -0,0 +1,50 @@ +package info.nightscout.androidaps.plugins.pump.common.defs + +import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.utils.resources.ResourceHelper +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 PumpHistoryEntryGroup(val resourceId: Int) { + + All(R.string.history_group_all), + Bolus(R.string.history_group_bolus), + Basal(R.string.history_group_basal), + Prime(R.string.history_group_prime), + Configuration(R.string.history_group_configuration), + Alarm(R.string.history_group_alarm), + Glucose(R.string.history_group_glucose), + Notification(R.string.history_group_notification), + Statistic(R.string.history_group_statistic), + Unknown(R.string.history_group_unknown); + + var translated: String? = null + private set + + override fun toString(): String { + return translated!! + } + + companion object { + private var translatedList: MutableList? = null + private fun doTranslation(resourceHelper: ResourceHelper) { + translatedList = ArrayList() + for (pumpHistoryEntryGroup in values()) { + pumpHistoryEntryGroup.translated = resourceHelper.gs(pumpHistoryEntryGroup.resourceId) + (translatedList as ArrayList).add(pumpHistoryEntryGroup) + } + } + + @JvmStatic fun getTranslatedList(resourceHelper: ResourceHelper): List? { + if (translatedList == null) doTranslation(resourceHelper) + return translatedList + } + } + +} \ No newline at end of file diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java index 6273ff5203..da5e99596c 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java @@ -29,9 +29,13 @@ public class ByteUtil { return (b < 0) ? b + 256 : b; } + public static int asUINT8(Integer b) { + return (b < 0) ? b + 256 : b; + } + public static byte[] getBytesFromInt16(int value) { byte[] array = getBytesFromInt(value); - return new byte[] {array[2], array[3]}; + return new byte[]{array[2], array[3]}; } public static byte[] getBytesFromInt(int value) { @@ -283,10 +287,54 @@ public class ByteUtil { } + /** + * Converts 4 (or less) ints into int. (Shorts are objects, so you can send null if you have less parameters) + * + * @param b1 short 1 + * @param b2 short 2 + * @param b3 short 3 + * @param b4 short 4 + * @param flag Conversion Flag (Big Endian, Little endian) + * @return int value + */ + public static int toInt(Byte b1, Byte b2, Byte b3, Byte b4, BitConversion flag) { + switch (flag) { + case LITTLE_ENDIAN: { + if (b4 != null) { + return (b4 & 0xff) << 24 | (b3 & 0xff) << 16 | (b2 & 0xff) << 8 | b1 & 0xff; + } else if (b3 != null) { + return (b3 & 0xff) << 16 | (b2 & 0xff) << 8 | b1 & 0xff; + } else if (b2 != null) { + return (b2 & 0xff) << 8 | b1 & 0xff; + } else { + return b1 & 0xff; + } + } + + default: + case BIG_ENDIAN: { + if (b4 != null) { + return (b1 & 0xff) << 24 | (b2 & 0xff) << 16 | (b3 & 0xff) << 8 | b4 & 0xff; + } else if (b3 != null) { + return (b1 & 0xff) << 16 | (b2 & 0xff) << 8 | b3 & 0xff; + } else if (b2 != null) { + return (b1 & 0xff) << 8 | b2 & 0xff; + } else { + return b1 & 0xff; + } + } + } + } + + public static int toInt(int b1, int b2) { return toInt(b1, b2, null, null, BitConversion.BIG_ENDIAN); } + public static int toInt(Byte b1, Byte b2) { + return toInt(b1, b2, null, null, BitConversion.BIG_ENDIAN); + } + public static int toInt(int b1, int b2, int b3) { return toInt(b1, b2, b3, null, BitConversion.BIG_ENDIAN); @@ -329,6 +377,25 @@ public class ByteUtil { } + public static String getCorrectHexValue(byte inp) { + String hx = Integer.toHexString((char) inp); + + if (hx.length() == 0) + return "00"; + else if (hx.length() == 1) + return "0" + hx; + else if (hx.length() == 2) + return hx; + else if (hx.length() == 4) + return hx.substring(2); + else { + System.out.println("Hex Error: " + inp); + } + + return null; + } + + public static String getHex(byte[] abyte0) { return abyte0 != null ? getHex(abyte0, abyte0.length) : null; } From 05a07c190466445b840ef3d0bbb708c01cf834a5 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Fri, 16 Apr 2021 21:40:25 +0100 Subject: [PATCH 03/39] - kotlinlize: info/nightscout/androidaps/plugins/pump/medtronic/comm/message --- .../pump/medtronic/MedtronicPumpPlugin.java | 2 +- .../comm/MedtronicCommunicationManager.java | 17 +- .../comm/history/MedtronicHistoryDecoder.kt | 11 +- .../comm/history/MedtronicHistoryEntry.kt | 47 ++-- .../history/MedtronicHistoryEntryInterface.kt | 2 +- .../comm/history/cgms/CGMSHistoryEntry.kt | 2 +- .../pump/MedtronicPumpHistoryDecoder.kt | 104 ++++----- .../comm/history/pump/PumpHistoryEntry.kt | 15 +- .../comm/history/pump/PumpHistoryEntryType.kt | 69 ++---- .../comm/message/CarelinkLongMessageBody.java | 49 ---- .../comm/message/CarelinkLongMessageBody.kt | 46 ++++ .../message/CarelinkShortMessageBody.java | 53 ----- .../comm/message/CarelinkShortMessageBody.kt | 38 ++++ .../GetHistoryPageCarelinkMessageBody.java | 59 ----- .../GetHistoryPageCarelinkMessageBody.kt | 45 ++++ .../medtronic/comm/message/MessageBody.java | 34 --- .../medtronic/comm/message/MessageBody.kt | 27 +++ .../medtronic/comm/message/PacketType.java | 47 ---- .../pump/medtronic/comm/message/PacketType.kt | 37 +++ .../comm/message/PumpAckMessageBody.java | 16 -- .../comm/message/PumpAckMessageBody.kt | 15 ++ .../medtronic/comm/message/PumpMessage.java | 214 ------------------ .../medtronic/comm/message/PumpMessage.kt | 183 +++++++++++++++ .../comm/message/UnknownMessageBody.java | 46 ---- .../comm/message/UnknownMessageBody.kt | 15 ++ .../medtronic/data/MedtronicHistoryData.java | 62 ++--- .../medtronic/data/dto/DailyTotalsDTO.java | 18 +- .../data/dto/TempBasalProcessDTO.java | 2 +- .../pump/medtronic/di/MedtronicModule.kt | 7 + .../dialog/MedtronicHistoryActivity.java | 4 +- .../history/pump/PumpHistoryEntryUTest.java | 2 +- 31 files changed, 575 insertions(+), 713 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java index 48ee038ad5..d1fede9118 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -1223,7 +1223,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter return; this.lastPumpHistoryEntry = latestEntry; - sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.atechDateTime); + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.getAtechDateTime()); if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History: valid=" + historyResult.validEntries.size() + ", unprocessed=" + historyResult.unprocessedEntries.size()); diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java index 32963e8d9a..4b8f885701 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java @@ -237,10 +237,10 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager aapsLogger.debug(LTag.PUMPCOMM, "Run command with Args: "); PumpMessage rval; - PumpMessage shortMessage = makePumpMessage(msg.commandType, new CarelinkShortMessageBody(new byte[]{0})); + PumpMessage shortMessage = makePumpMessage(msg.getCommandType(), new CarelinkShortMessageBody(new byte[]{0})); // look for ack from short message PumpMessage shortResponse = sendAndListen(shortMessage); - if (shortResponse.commandType == MedtronicCommandType.CommandACK) { + if (shortResponse.getCommandType() == MedtronicCommandType.CommandACK) { if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, "Run command with Args: Got ACK response"); @@ -266,7 +266,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // look for ack from short message PumpMessage shortResponse = sendAndListen(shortMessage); - if (shortResponse.commandType != MedtronicCommandType.CommandACK) { + if (shortResponse.getCommandType() != MedtronicCommandType.CommandACK) { aapsLogger.error(LTag.PUMPCOMM, "runCommandWithFrames: Pump did not ack Attention packet"); return new PumpMessage(aapsLogger, "No ACK after start message."); @@ -288,7 +288,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // aapsLogger.debug(LTag.PUMPCOMM,"PumpResponse: " + rval); - if (rval.commandType != MedtronicCommandType.CommandACK) { + if (rval.getCommandType() != MedtronicCommandType.CommandACK) { aapsLogger.error(LTag.PUMPCOMM, "runCommandWithFrames: Pump did not ACK frame #" + frameNr); aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Run command with Frames FAILED (command=%s, response=%s)", commandType.name(), @@ -356,8 +356,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // aapsLogger.info(LTag.PUMPCOMM,"getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents())); PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody()); - GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse - .getMessageBody().getTxData()); + GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse.getMessageBody().getTxData()); int expectedFrameNum = 1; boolean done = false; // while (expectedFrameNum == currentResponse.getFrameNumber()) { @@ -861,7 +860,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: %s", commandType.getCommandDescription(), pumpMessage.getResponseContent())); - if (pumpMessage.commandType == MedtronicCommandType.CommandACK) { + if (pumpMessage.getCommandType() == MedtronicCommandType.CommandACK) { return true; } else { aapsLogger.warn(LTag.PUMPCOMM, "We received non-ACK response from pump: " + pumpMessage.getResponseContent()); @@ -900,7 +899,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager responseMessage = runCommandWithFrames(MedtronicCommandType.SetBasalProfileSTD, basalProfileFrames); - if (responseMessage.commandType == MedtronicCommandType.CommandACK) + if (responseMessage.getCommandType() == MedtronicCommandType.CommandACK) return true; } catch (RileyLinkCommunicationException e) { @@ -908,7 +907,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager } if (responseMessage != null) - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Set Basal Profile: Invalid response: commandType=%s,rawData=%s", responseMessage.commandType, ByteUtil.shortHexString(responseMessage.getRawContent()))); + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Set Basal Profile: Invalid response: commandType=%s,rawData=%s", responseMessage.getCommandType(), ByteUtil.shortHexString(responseMessage.getRawContent()))); else aapsLogger.warn(LTag.PUMPCOMM, "Set Basal Profile: Null response."); } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index a6a8744299..181177d54f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -19,16 +19,13 @@ import kotlin.jvm.Throws */ abstract class MedtronicHistoryDecoder : MedtronicHistoryDecoderInterface { - @JvmField @Inject - var aapsLogger: AAPSLogger? = null - - @JvmField @Inject - var medtronicUtil: MedtronicUtil? = null - protected var bitUtils: ByteUtil? = null + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var medtronicUtil: MedtronicUtil + @Inject lateinit var bitUtils: ByteUtil // STATISTICS (remove at later time or not) protected var statisticsEnabled = true - @JvmField protected var unknownOpCodes: MutableMap? = null + protected var unknownOpCodes: MutableMap? = null protected var mapStatistics: MutableMap>? = null // public abstract Class getHistoryEntryClass(); diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index 72e3174178..6f2228b29c 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -16,30 +16,41 @@ import java.util.* */ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { - @JvmField var rawData: List? = null - @JvmField protected var sizes = IntArray(3) + var rawData: List? = null + get() = field + + protected var sizes = IntArray(3) + get() = field + var head: ByteArray? = null + get() = field + var datetime: ByteArray? = null var body: ByteArray? = null - - // protected LocalDateTime dateTime; - @JvmField var id: Long = 0 - - @JvmField @Expose - var DT: String? = null - - @JvmField @Expose - var atechDateTime: Long? = null + var id: Long = 0 + set(value) { + field = value + } @Expose - protected var decodedData: MutableMap? = null - var phoneDateTime // time on phone - : Long = 0 + var DT: String? = null + get() = field + + @Expose + var atechDateTime: Long? = null + get() = field + set(value) { + field = value + } + + @Expose + var decodedData: MutableMap? = null + get() = field /** * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) */ - protected open var pumpId: Long? = null + open var pumpId: Long? = null /** * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's @@ -52,7 +63,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { * Linked object, see linked */ var linkedObject: Any? = null - get() = field //= linkedObject + get() = field set(value) { linked = true field = value @@ -63,7 +74,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { // this.linkedObject = linkedObject // } - override fun setData(listRawData: List?, doNotProcess: Boolean) { + override fun setData(listRawData: List, doNotProcess: Boolean) { rawData = listRawData // System.out.println("Head: " + sizes[0] + ", dates: " + sizes[1] + @@ -78,7 +89,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { var i = headLength var j = 0 while (j < dateTimeLength) { - datetime!![j] = listRawData!![i]!! + datetime!![j] = listRawData[i] i++ j++ } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt index 32f6d4458a..4467f68d7e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt @@ -6,6 +6,6 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history interface MedtronicHistoryEntryInterface { val entryTypeName: String? - fun setData(listRawData: List?, doNotProcess: Boolean) + fun setData(listRawData: List, doNotProcess: Boolean) val dateLength: Int } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt index 2ede3d65c1..670a17ee91 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt @@ -30,7 +30,7 @@ class CGMSHistoryEntry : MedtronicHistoryEntry() { override val entryTypeName: String get() = entryType!!.name - override fun setData(listRawData: List?, doNotProcess: Boolean) { + override fun setData(listRawData: List, doNotProcess: Boolean) { if (entryType!!.schemaSet) { super.setData(listRawData, doNotProcess) } else { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index e0613567d8..c8e38e7fcb 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -19,6 +19,7 @@ import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil import java.util.* import javax.inject.Inject import javax.inject.Singleton +import kotlin.experimental.and /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes @@ -29,12 +30,13 @@ import javax.inject.Singleton */ @Singleton class MedtronicPumpHistoryDecoder @Inject constructor( - aapsLogger: AAPSLogger?, - medtronicUtil: MedtronicUtil? + aapsLogger: AAPSLogger, + medtronicUtil: MedtronicUtil ) : MedtronicHistoryDecoder() { private var tbrPreviousRecord: PumpHistoryEntry? = null private var changeTimeRecord: PumpHistoryEntry? = null + override fun createRecords(dataClear: List): List { prepareStatistics() var counter = 0 @@ -42,8 +44,8 @@ class MedtronicPumpHistoryDecoder @Inject constructor( var incompletePacket: Boolean val outList: MutableList = ArrayList() var skipped: String? = null - if (dataClear!!.size == 0) { - aapsLogger!!.error(LTag.PUMPBTCOMM, "Empty page.") + if (dataClear.size == 0) { + aapsLogger.error(LTag.PUMPBTCOMM, "Empty page.") return outList } do { @@ -57,13 +59,13 @@ class MedtronicPumpHistoryDecoder @Inject constructor( continue } else { if (skipped != null) { - aapsLogger!!.warn(LTag.PUMPBTCOMM, " ... Skipped $skipped") + aapsLogger.warn(LTag.PUMPBTCOMM, " ... Skipped $skipped") skipped = null skippedRecords = true } } if (skippedRecords) { - aapsLogger!!.error(LTag.PUMPBTCOMM, "We had some skipped bytes, which might indicate error in pump history. Please report this problem.") + aapsLogger.error(LTag.PUMPBTCOMM, "We had some skipped bytes, which might indicate error in pump history. Please report this problem.") } val entryType = getByCode(opCode.toByte()) val pe = PumpHistoryEntry() @@ -89,12 +91,12 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } special = true } else { - for (j in 0 until entryType.getTotalLength(medtronicUtil!!.medtronicPumpModel) - 1) { + for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel) - 1) { try { listRawData.add(dataClear[counter]) counter++ } catch (ex: Exception) { - aapsLogger!!.error(LTag.PUMPBTCOMM, "OpCode: " + ByteUtil.shortHexString(opCode.toByte()) + ", Invalid package: " + aapsLogger.error(LTag.PUMPBTCOMM, "OpCode: " + ByteUtil.shortHexString(opCode.toByte()) + ", Invalid package: " + ByteUtil.getHex(listRawData)) // throw ex; incompletePacket = true @@ -115,7 +117,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { //Log.i(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); } else { - aapsLogger!!.warn(LTag.PUMPBTCOMM, "#" + record + " " + decoded!!.description + " " + pe) + aapsLogger.warn(LTag.PUMPBTCOMM, "#" + record + " " + decoded!!.description + " " + pe) } addToStatistics(pe, decoded, null) record++ @@ -132,7 +134,8 @@ class MedtronicPumpHistoryDecoder @Inject constructor( return try { decodeRecord(record, false) } catch (ex: Exception) { - aapsLogger!!.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.entryType!!.name, ex.message, ex)) + aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.entryType!!.name, ex.message, ex)) + //ex.printStackTrace() RecordDecodeStatus.Error } } @@ -145,17 +148,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( PumpHistoryEntryType.ChangeBasalPattern, PumpHistoryEntryType.CalBGForPH, PumpHistoryEntryType.ChangeRemoteId, PumpHistoryEntryType.ClearAlarm, PumpHistoryEntryType.ChangeAlarmNotifyMode, PumpHistoryEntryType.EnableDisableRemote, PumpHistoryEntryType.BGReceived, PumpHistoryEntryType.SensorAlert, PumpHistoryEntryType.ChangeTimeFormat, PumpHistoryEntryType.ChangeReservoirWarningTime, PumpHistoryEntryType.ChangeBolusReminderEnable, PumpHistoryEntryType.SetBolusReminderTime, PumpHistoryEntryType.ChangeChildBlockEnable, PumpHistoryEntryType.BolusWizardEnabled, PumpHistoryEntryType.ChangeBGReminderOffset, PumpHistoryEntryType.ChangeAlarmClockTime, PumpHistoryEntryType.ChangeMeterId, PumpHistoryEntryType.ChangeParadigmID, PumpHistoryEntryType.JournalEntryMealMarker, PumpHistoryEntryType.JournalEntryExerciseMarker, PumpHistoryEntryType.DeleteBolusReminderTime, PumpHistoryEntryType.SetAutoOff, PumpHistoryEntryType.SelfTest, PumpHistoryEntryType.JournalEntryInsulinMarker, PumpHistoryEntryType.JournalEntryOtherMarker, PumpHistoryEntryType.BolusWizardSetup512, PumpHistoryEntryType.ChangeSensorSetup2, PumpHistoryEntryType.ChangeSensorAlarmSilenceConfig, PumpHistoryEntryType.ChangeSensorRateOfChangeAlertSetup, PumpHistoryEntryType.ChangeBolusScrollStepSize, PumpHistoryEntryType.BolusWizardSetup, PumpHistoryEntryType.ChangeVariableBolus, PumpHistoryEntryType.ChangeAudioBolus, PumpHistoryEntryType.ChangeBGReminderEnable, PumpHistoryEntryType.ChangeAlarmClockEnable, PumpHistoryEntryType.BolusReminder, PumpHistoryEntryType.DeleteAlarmClockTime, PumpHistoryEntryType.ChangeCarbUnits, PumpHistoryEntryType.ChangeWatchdogEnable, PumpHistoryEntryType.ChangeOtherDeviceID, PumpHistoryEntryType.ReadOtherDevicesIDs, PumpHistoryEntryType.BGReceived512, PumpHistoryEntryType.SensorStatus, PumpHistoryEntryType.ReadCaptureEventEnabled, PumpHistoryEntryType.ChangeCaptureEventEnable, PumpHistoryEntryType.ReadOtherDevicesStatus -> RecordDecodeStatus.OK PumpHistoryEntryType.Sensor_0x54, PumpHistoryEntryType.Sensor_0x55, PumpHistoryEntryType.Sensor_0x51, PumpHistoryEntryType.Sensor_0x52, PumpHistoryEntryType.EventUnknown_MM512_0x2e -> { - // case EventUnknown_MM512_0x37: -// case EventUnknown_MM512_0x38: -// case EventUnknown_MM512_0x4e: -// case EventUnknown_MM522_0x70: -// case EventUnknown_MM512_0x88: -// case EventUnknown_MM512_0x94: -// case EventUnknown_MM522_0xE8: -// case EventUnknown_0x4d: -// case EventUnknown_MM522_0x25: -// case EventUnknown_MM522_0x05: - aapsLogger!!.debug(LTag.PUMPBTCOMM, " -- ignored Unknown Pump Entry: $entry") + aapsLogger.debug(LTag.PUMPBTCOMM, " -- ignored Unknown Pump Entry: $entry") RecordDecodeStatus.Ignored } @@ -207,12 +200,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( PumpHistoryEntryType.None, PumpHistoryEntryType.UnknownBasePacket -> RecordDecodeStatus.Error else -> { - aapsLogger!!.debug(LTag.PUMPBTCOMM, "Not supported: " + entry.entryType) + aapsLogger.debug(LTag.PUMPBTCOMM, "Not supported: " + entry.entryType) RecordDecodeStatus.NotSupported } } - - // return RecordDecodeStatus.Error; } private fun decodeDailyTotals(entry: PumpHistoryEntry): RecordDecodeStatus { @@ -223,12 +214,8 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBasalProfile(entry: PumpHistoryEntry): RecordDecodeStatus { - - // LOG.debug("decodeBasalProfile: {}", entry); val basalProfile = BasalProfile(aapsLogger) basalProfile.setRawDataFromHistory(entry.body) - - // LOG.debug("decodeBasalProfile BasalProfile: {}", basalProfile); entry.addDecodedData("Object", basalProfile) return RecordDecodeStatus.OK } @@ -240,24 +227,21 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBatteryActivity(entry: PumpHistoryEntry) { - // this.writeData(PumpBaseType.Event, entry.getHead()[0] == 0 ? PumpEventType.BatteryRemoved : - // PumpEventType.BatteryReplaced, entry.getATechDate()); entry.displayableValue = if (entry.head!![0] == 0.toByte()) "Battery Removed" else "Battery Replaced" } private fun decodeBasalProfileStart(entry: PumpHistoryEntry): RecordDecodeStatus { val body = entry.body - // int bodyOffset = headerSize + timestampSize; val offset = body!![0] * 1000 * 30 * 60 var rate: Float? = null 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 } //LOG.info("Basal Profile Start: offset={}, rate={}, index={}, body_raw={}", offset, rate, index, body); return if (rate == null) { - aapsLogger!!.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Basal Profile Start (ERROR): offset=%d, rate=%.3f, index=%d, body_raw=%s", offset, rate, index, ByteUtil.getHex(body))) + aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Basal Profile Start (ERROR): offset=%d, rate=%.3f, index=%d, body_raw=%s", offset, rate, index, ByteUtil.getHex(body))) RecordDecodeStatus.Error } else { entry.addDecodedData("Value", getFormattedFloat(rate, 3)) @@ -267,26 +251,26 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBolusWizard(entry: PumpHistoryEntry): RecordDecodeStatus { - val body = entry.body as IntArray + val body = entry.body!! val dto = BolusWizardDTO() var bolusStrokes = 10.0f 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 bolusStrokes = 40.0f - dto.carbs = (body[1] and 0x0c shl 6) + body[0] - dto.bloodGlucose = (body[1] and 0x03 shl 8) + entry.head!![0] + dto.carbs = ((body[1] and 0x0c.toByte()).toInt() shl 6) + body[0] + dto.bloodGlucose = ((body[1] and 0x03).toInt() shl 8) + entry.head!![0] dto.carbRatio = body[1] / 10.0f // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / // 10.0s dto.insulinSensitivity = body[4].toFloat() dto.bgTargetLow = body[5] as Int dto.bgTargetHigh = body[14] as Int - dto.correctionEstimate = ((body[9] and 0x38 shl 5) + body[6]) / bolusStrokes - dto.foodEstimate = ((body[7] shl 8) + body[8]) / bolusStrokes - dto.unabsorbedInsulin = ((body[10] shl 8) + body[11]) / bolusStrokes - dto.bolusTotal = ((body[12] shl 8) + body[13]) / bolusStrokes + dto.correctionEstimate = (((body[9] and 0x38).toInt() shl 5) + body[6]) / bolusStrokes + dto.foodEstimate = ((body[7].toInt() shl 8) + body[8]) / bolusStrokes + dto.unabsorbedInsulin = ((body[10].toInt() shl 8) + body[11]) / bolusStrokes + dto.bolusTotal = ((body[12].toInt() shl 8) + body[13]) / bolusStrokes } else { - dto.bloodGlucose = body.get(1) and 0x0F 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.carbRatio = body.get(2).toFloat() dto.insulinSensitivity = body.get(3).toFloat() @@ -308,14 +292,14 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBolusWizard512(entry: PumpHistoryEntry): RecordDecodeStatus { - val body = entry.body as IntArray + val body = entry.body!! val dto = BolusWizardDTO() val bolusStrokes = 10.0f - dto.bloodGlucose = body.get(1) and 0x03 shl 8 or entry.head!!.get(0).toInt() - dto.carbs = body!!.get(1).toInt() and 0xC shl 6 or body.get(0).toInt() // (int)body[0]; - dto.carbRatio = body!!.get(2).toFloat() - dto.insulinSensitivity = body!!.get(3).toFloat() - dto.bgTargetLow = body.get(4) + dto.bloodGlucose = (body.get(1) and 0x03).toInt() shl 8 or entry.head!!.get(0).toInt() + dto.carbs = body.get(1).toInt() and 0xC shl 6 or body.get(0).toInt() // (int)body[0]; + dto.carbRatio = body.get(2).toFloat() + dto.insulinSensitivity = body.get(3).toFloat() + dto.bgTargetLow = body.get(4).toInt() dto.foodEstimate = body.get(6) / 10.0f dto.correctionEstimate = (body.get(7) + (body.get(5) and 0x0F)) / bolusStrokes dto.unabsorbedInsulin = body.get(9) / bolusStrokes @@ -374,8 +358,8 @@ class MedtronicPumpHistoryDecoder @Inject constructor( private fun decodeBolus(entry: PumpHistoryEntry) { val bolus = BolusDTO() - val data = entry.head as IntArray - if (MedtronicDeviceType.isSameDevice(medtronicUtil!!.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { + val data = entry.head!! + if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { 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.insulinOnBoard = ByteUtil.toInt(data.get(4), data.get(5)) / 40.0 @@ -433,18 +417,18 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeDateTime(entry: PumpHistoryEntry) { - val dt = entry.datetime as IntArray - if (dt == null) { - aapsLogger!!.warn(LTag.PUMPBTCOMM, "DateTime not set.") + if (entry.datetime==null) { + aapsLogger.warn(LTag.PUMPBTCOMM, "DateTime not set.") } + val dt = entry.datetime!! if (entry.dateTimeLength == 5) { - val seconds: Int = (dt!!.get(0) and 0x3F).toInt() - val minutes: Int = (dt!!.get(1) and 0x3F).toInt() + val seconds: Int = (dt.get(0) and 0x3F.toByte()).toInt() + val minutes: Int = (dt.get(1) and 0x3F.toByte()).toInt() val hour: Int = (dt.get(2) and 0x1F).toInt() - val month: Int = (dt.get(0) shr 4 and 0x0c) + (dt.get(1) shr 6 and 0x03) + val month: Int = (dt.get(0).toInt() shr 4 and 0x0c) + (dt.get(1).toInt() shr 6 and 0x03) // ((dt[0] & 0xC0) >> 6) | ((dt[1] & 0xC0) >> 4); - val dayOfMonth: Int = dt.get(3) and 0x1F - val year = fix2DigitYear(dt.get(4) and 0x3F) // Assuming this is correct, need to verify. Otherwise this will be + val dayOfMonth: Int = (dt.get(3) and 0x1F).toInt() + val year = fix2DigitYear((dt.get(4) and 0x3F.toByte()).toInt()) // Assuming this is correct, need to verify. Otherwise this will be // a problem in 2016. entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)) } else if (entry.dateTimeLength == 2) { @@ -453,7 +437,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val mlow = ByteUtil.asUINT8(dt.get(1)) and 0x80 shr 7 val month = mhigh + mlow // int dayOfMonth = low + 1; - val dayOfMonth: Int = dt.get(0) and 0x1F + val dayOfMonth: Int = (dt.get(0) and 0x1F).toInt() val year = 2000 + (ByteUtil.asUINT8(dt.get(1)) and 0x7F) var hour = 0 var minutes = 0 @@ -461,7 +445,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( //LOG.debug("DT: {} {} {}", year, month, dayOfMonth); if (dayOfMonth == 32) { - aapsLogger!!.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Entry: Day 32 %s = [%s] %s", entry.entryType!!.name, + aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Entry: Day 32 %s = [%s] %s", entry.entryType!!.name, ByteUtil.getHex(entry.rawData), entry)) } if (isEndResults(entry.entryType)) { @@ -471,7 +455,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)) } else { - aapsLogger!!.warn(LTag.PUMPBTCOMM, "Unknown datetime format: " + entry.dateTimeLength) + aapsLogger.warn(LTag.PUMPBTCOMM, "Unknown datetime format: " + entry.dateTimeLength) } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index e1c0daf2ea..289cb113ed 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -17,7 +17,8 @@ import java.util.* */ class PumpHistoryEntry : MedtronicHistoryEntry() { - @Expose var entryType: PumpHistoryEntryType? = null + @Expose + var entryType: PumpHistoryEntryType? = null private set override var opCode: Byte? = null @@ -27,16 +28,12 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { field = value } - // // override fun getOpCode(): Int { - // // return - // // } - // - // fun setOpCode(opCode: Int?) { - // this.opCode = opCode - // } - var offset = 0 var displayableValue = "" + get() = field + set(value) { + field = value + } fun setEntryType(medtronicDeviceType: MedtronicDeviceType?, entryType: PumpHistoryEntryType) { this.entryType = entryType diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt index 3f2a4a0c40..9ddb18b996 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt @@ -12,7 +12,7 @@ import java.util.* * Author: Andy {andy.rozman@gmail.com} */ enum class PumpHistoryEntryType // implements CodeEnum -@JvmOverloads constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int = 2, date: Int = 5, body: Int = 0) { + constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int = 2, date: Int = 5, body: Int = 0) { // all commented out are probably not the real items None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), Bolus(0x01, "Bolus", PumpHistoryEntryGroup.Bolus, 4, 5, 0), // 523+[H=8] 9/13 @@ -40,15 +40,12 @@ enum class PumpHistoryEntryType // implements CodeEnum ClearSettings(0x22, "Clear Settings", PumpHistoryEntryGroup.Configuration), // ChangeChildBlockEnable(0x23, "Change Child Block Enable", PumpHistoryEntryGroup.Configuration), // ChangeMaxBolus(0x24, "Change Max Bolus", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM522_0x25(0x25, "Unknown Event 0x25", PumpHistoryEntryGroup.Unknown), // 8? EnableDisableRemote(0x26, "Enable/Disable Remote", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // 2, 5, 14 V6:2,5,14 ChangeRemoteId(0x27, "Change Remote ID", PumpHistoryEntryGroup.Configuration), // ?? ChangeMaxBasal(0x2c, "Change Max Basal", PumpHistoryEntryGroup.Configuration), // BolusWizardEnabled(0x2d, "Bolus Wizard Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? - - /* TODO */ - EventUnknown_MM512_0x2e(0x2e, "Unknown Event 0x2e", PumpHistoryEntryGroup.Unknown, 2, 5, 100), // + /* TODO */ EventUnknown_MM512_0x2e(0x2e, "Unknown Event 0x2e", PumpHistoryEntryGroup.Unknown, 2, 5, 100), // BolusWizard512(0x2f, "Bolus Wizard (512)", PumpHistoryEntryGroup.Bolus, 2, 5, 12), // UnabsorbedInsulin512(0x30, "Unabsorbed Insulin (512)", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // FIXME ChangeBGReminderOffset(0x31, "Change BG Reminder Offset", PumpHistoryEntryGroup.Configuration), // @@ -57,13 +54,10 @@ enum class PumpHistoryEntryType // implements CodeEnum LowReservoir(0x34, "Low Reservoir", PumpHistoryEntryGroup.Notification), // ChangeAlarmClock(0x35, "Change Alarm Clock", PumpHistoryEntryGroup.Configuration), // ChangeMeterId(0x36, "Change Meter ID", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM512_0x37(0x37, "Unknown Event 0x37", PumpHistoryEntryGroup.Unknown), // V:MM512 // /**/EventUnknown_MM512_0x38(0x38, "Unknown Event 0x38", PumpHistoryEntryGroup.Unknown), // BGReceived512(0x39, "BG Received (512)", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // - - /* TODO */ - ConfirmInsulinChange(0x3a, "Confirm Insulin Change", PumpHistoryEntryGroup.Unknown), // + /* TODO */ ConfirmInsulinChange(0x3a, "Confirm Insulin Change", PumpHistoryEntryGroup.Unknown), // SensorStatus(0x3b, "Sensor Status", PumpHistoryEntryGroup.Glucose), // ChangeParadigmID(0x3c, "Change Paradigm ID", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // V3 ? V6: 2,5,14 ?? is it this length or just 7 @@ -73,9 +67,8 @@ enum class PumpHistoryEntryType // implements CodeEnum JournalEntryMealMarker(0x40, "Meal Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 2), // is size just 7??? V6 JournalEntryExerciseMarker(0x41, "Exercise Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // ?? JournalEntryInsulinMarker(0x42, "Insulin Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 0), // V6 = body(0)/was=1 - JournalEntryOtherMarker(0x43, "Other Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // V6 = body(1)/was=0 + JournalEntryOtherMarker(0x43, "Other Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // V6 = body(1) was=0 EnableSensorAutoCal(0x44, "Enable Sensor AutoCal", PumpHistoryEntryGroup.Glucose), // - // /**/EventUnknown_MM522_0x45(0x45, "Unknown Event 0x45", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // // /**/EventUnknown_MM522_0x46(0x46, "Unknown Event 0x46", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // // /**/EventUnknown_MM522_0x47(0x47, "Unknown Event 0x47", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // @@ -89,18 +82,11 @@ enum class PumpHistoryEntryType // implements CodeEnum BolusWizardSetup512(0x4f, "Bolus Wizard Setup (512)", PumpHistoryEntryGroup.Configuration, 2, 5, 32), // ChangeSensorSetup2(0x50, "Sensor Setup2", PumpHistoryEntryGroup.Configuration, 2, 5, 30), // Ian50 - /* TODO */ - Sensor_0x51(0x51, "Unknown Event 0x51", PumpHistoryEntryGroup.Unknown), // - - /* TODO */ - Sensor_0x52(0x52, "Unknown Event 0x52", PumpHistoryEntryGroup.Unknown), // + /* TODO */ Sensor_0x51(0x51, "Unknown Event 0x51", PumpHistoryEntryGroup.Unknown), // + /* TODO */ Sensor_0x52(0x52, "Unknown Event 0x52", PumpHistoryEntryGroup.Unknown), // ChangeSensorAlarmSilenceConfig(0x53, "Sensor Alarm Silence Config", PumpHistoryEntryGroup.Configuration, 2, 5, 1), // 8 - - /* TODO */ - Sensor_0x54(0x54, "Unknown Event 0x54", PumpHistoryEntryGroup.Unknown), // Ian54 - - /* TODO */ - Sensor_0x55(0x55, "Unknown Event 0x55", PumpHistoryEntryGroup.Unknown), // + /* TODO */ Sensor_0x54(0x54, "Unknown Event 0x54", PumpHistoryEntryGroup.Unknown), // Ian54 + /* TODO */ Sensor_0x55(0x55, "Unknown Event 0x55", PumpHistoryEntryGroup.Unknown), // ChangeSensorRateOfChangeAlertSetup(0x56, "Sensor Rate Of Change Alert Setup", PumpHistoryEntryGroup.Configuration, 2, 5, 5), // 12 ChangeBolusScrollStepSize(0x57, "Change Bolus Scroll Step Size", PumpHistoryEntryGroup.Configuration), // BolusWizardSetup(0x5a, "Bolus Wizard Setup (522)", PumpHistoryEntryGroup.Configuration, 2, 5, 117), // V2: 522+[B=143]; V6: 124, v6: 137, v7: 117/137 [523] @@ -124,7 +110,6 @@ enum class PumpHistoryEntryType // implements CodeEnum DailyTotals522(0x6d, "Daily Totals (522)", PumpHistoryEntryGroup.Statistic, 1, 2, 41), // DailyTotals523(0x6e, "Daily Totals (523)", PumpHistoryEntryGroup.Statistic, 1, 2, 49), // 1102014-03-17T00:00:00 ChangeCarbUnits(0x6f.toByte(), "Change Carb Units", PumpHistoryEntryGroup.Configuration), // - // /**/EventUnknown_MM522_0x70((byte) 0x70, "Unknown Event 0x70", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // BasalProfileStart(0x7b, "Basal Profile Start", PumpHistoryEntryGroup.Basal, 2, 5, 3), // // 722 ChangeWatchdogEnable(0x7c, "Change Watchdog Enable", PumpHistoryEntryGroup.Configuration), // @@ -158,7 +143,7 @@ enum class PumpHistoryEntryType // implements CodeEnum ChangeSensorSetup2.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 34)) } - @JvmStatic fun getByCode(opCode: Byte): PumpHistoryEntryType? { + fun getByCode(opCode: Byte): PumpHistoryEntryType? { return if (opCodeMap.containsKey(opCode)) { opCodeMap[opCode] } else { @@ -166,18 +151,6 @@ enum class PumpHistoryEntryType // implements CodeEnum } } - // - // private PumpHistoryEntryType(int opCode, String name, int head, int date, - // int body) - // { - // this.opCode = (byte) opCode; - // this.description = name; - // this.headLength = head; - // this.dateLength = date; - // this.bodyLength = body; - // this.totalLength = (head + date + body); - // } - // fun isAAPSRelevantEntry(entryType: PumpHistoryEntryType): Boolean { return entryType == Bolus || // Treatments entryType == TempBasalRate || // @@ -215,8 +188,11 @@ enum class PumpHistoryEntryType // implements CodeEnum } val code: Byte - private val description: String? - private val headLength: Int + + val description: String? + get() = field + + val headLength: Int val dateLength: Int // private MinimedDeviceType deviceType; @@ -228,22 +204,25 @@ enum class PumpHistoryEntryType // implements CodeEnum private var specialRulesHead: MutableList? = null private var specialRulesBody: MutableList? = null private var hasSpecialRules = false + get() = field + val group: PumpHistoryEntryGroup + get() = field 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) {} fun getTotalLength(medtronicDeviceType: MedtronicDeviceType?): Int { - return if (hasSpecialRules()) { + return if (hasSpecialRules) { getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + dateLength } else { totalLength } } - private fun hasSpecialRules(): Boolean { - return hasSpecialRules - } + // private fun hasSpecialRules(): Boolean { + // return hasSpecialRules + // } fun addSpecialRuleHead(rule: SpecialRule) { if (isEmpty(specialRulesHead)) { @@ -261,9 +240,9 @@ enum class PumpHistoryEntryType // implements CodeEnum hasSpecialRules = true } - fun getDescription(): String { - return description ?: name - } + // fun getDescription(): String { + // return description ?: name + // } fun getHeadLength(medtronicDeviceType: MedtronicDeviceType?): Int { return if (hasSpecialRules) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java deleted file mode 100644 index 7f2c51e032..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.java +++ /dev/null @@ -1,49 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -/** - * Created by geoff on 6/2/16. - */ -public class CarelinkLongMessageBody extends MessageBody { - - private static final int LONG_MESSAGE_BODY_LENGTH = 65; - protected byte[] data; - - - CarelinkLongMessageBody() { - init(new byte[0]); - } - - - public CarelinkLongMessageBody(byte[] payload) { - init(payload); - } - - @Override - public void init(byte[] rxData) { - - if (rxData != null && rxData.length == LONG_MESSAGE_BODY_LENGTH) { - data = rxData; - } else { - data = new byte[LONG_MESSAGE_BODY_LENGTH]; - if (rxData != null) { - int size = rxData.length < LONG_MESSAGE_BODY_LENGTH ? rxData.length : LONG_MESSAGE_BODY_LENGTH; - for (int i = 0; i < size; i++) { - data[i] = rxData[i]; - } - } - } - } - - - @Override - public int getLength() { - return LONG_MESSAGE_BODY_LENGTH; - } - - - @Override - public byte[] getTxData() { - return data; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.kt new file mode 100644 index 0000000000..e46e8feb6a --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkLongMessageBody.kt @@ -0,0 +1,46 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +/** + * Created by geoff on 6/2/16. + */ +open class CarelinkLongMessageBody : MessageBody { + + //protected var data: ByteArray? = null + + internal constructor() { + init(ByteArray(0)) + } + + constructor(payload: ByteArray) { + init(payload) + } + + override fun init(rxData: ByteArray?) { + if (rxData != null && rxData.size == LONG_MESSAGE_BODY_LENGTH) { + data = rxData + } else { + data = ByteArray(LONG_MESSAGE_BODY_LENGTH) + if (rxData != null) { + val size = if (rxData.size < LONG_MESSAGE_BODY_LENGTH) rxData.size else LONG_MESSAGE_BODY_LENGTH + for (i in 0 until size) { + data!![i] = rxData[i] + } + } + } + } + + override val length: Int + get() = LONG_MESSAGE_BODY_LENGTH + + // { + // return LONG_MESSAGE_BODY_LENGTH + // } + + // override fun getTxData(): ByteArray { + // return data + // } + + companion object { + private const val LONG_MESSAGE_BODY_LENGTH = 65 + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java deleted file mode 100644 index e2ebbff085..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.java +++ /dev/null @@ -1,53 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -/** - * Created by geoff on 5/29/16. - */ -// Andy: See comments in message body -public class CarelinkShortMessageBody extends MessageBody { - - byte[] body; - - - public CarelinkShortMessageBody() { - init(new byte[] { 0 }); - } - - - public CarelinkShortMessageBody(byte[] data) { - init(data); - } - - - @Override - public int getLength() { - return body.length; - } - - - @Override - public void init(byte[] rxData) { - body = rxData; - } - - - public byte[] getRxData() { - return body; - } - - - public void setRxData(byte[] rxData) { - init(rxData); - } - - - @Override - public byte[] getTxData() { - return body; - } - - - public void setTxData(byte[] txData) { - init(txData); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.kt new file mode 100644 index 0000000000..7d99b45ae2 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/CarelinkShortMessageBody.kt @@ -0,0 +1,38 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +/** + * Created by geoff on 5/29/16. + */ +// Andy: See comments in message body +open class CarelinkShortMessageBody : MessageBody { + + //var body: ByteArray? + + constructor() { + init(byteArrayOf(0)) + } + + constructor(data: ByteArray?) { + init(data) + } + + override val length: Int + get() = data!!.size + + override fun init(rxData: ByteArray?) { + data = rxData + } + + var rxData: ByteArray? + get() = data + set(rxData) { + init(rxData) + } + + // override var txData: ByteArray? + // get() = body + // set(txData) { + // init(txData) + // } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java deleted file mode 100644 index 25e8aa087c..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.java +++ /dev/null @@ -1,59 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; - -/** - * Created by geoff on 6/2/16. - */ -public class GetHistoryPageCarelinkMessageBody extends CarelinkLongMessageBody { - - // public boolean wasLastFrame = false; - // public int frameNumber = 0; - // public byte[] frame = new byte[] {}; - - public GetHistoryPageCarelinkMessageBody(byte[] frameData) { - init(frameData); - } - - - public GetHistoryPageCarelinkMessageBody(int pageNum) { - init(pageNum); - } - - - @Override - public int getLength() { - return data.length; - } - - - @Override - public void init(byte[] rxData) { - super.init(rxData); - } - - - public void init(int pageNum) { - byte numArgs = 1; - super.init(new byte[] { numArgs, (byte)pageNum }); - } - - - public int getFrameNumber() { - if (data.length > 0) { - return data[0] & 0x7f; - } - return 255; - } - - - public boolean wasLastFrame() { - return (data[0] & 0x80) != 0; - } - - - public byte[] getFrameData() { - return ByteUtil.substring(data, 1, data.length - 1); - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt new file mode 100644 index 0000000000..b2836d4f77 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt @@ -0,0 +1,45 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import kotlin.experimental.and + +/** + * Created by geoff on 6/2/16. + */ +class GetHistoryPageCarelinkMessageBody : CarelinkLongMessageBody { + + // public boolean wasLastFrame = false; + // public int frameNumber = 0; + // public byte[] frame = new byte[] {}; + constructor(frameData: ByteArray?) { + init(frameData) + } + + constructor(pageNum: Int) { + init(pageNum) + } + + override val length: Int + get() = data!!.size + + override fun init(rxData: ByteArray?) { + super.init(rxData) + } + + fun init(pageNum: Int) { + val numArgs: Byte = 1 + super.init(byteArrayOf(numArgs, pageNum.toByte())) + } + + val frameNumber: Int + get() = if (data!!.size > 0) { + (data!![0] and 0x7f.toByte()).toInt() + } else 255 + + fun wasLastFrame(): Boolean { + return (data!![0] and 0x80.toByte()).toInt() != 0 + } + + val frameData: ByteArray + get() = ByteUtil.substring(data!!, 1, data!!.size - 1) +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java deleted file mode 100644 index fa4a3817be..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.java +++ /dev/null @@ -1,34 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; - -/** - * Created by geoff on 5/29/16. - */ -public class MessageBody { - - public int getLength() { - return 0; - } - - - public void init(byte[] rxData) { - } - - - public byte[] getTxData() { - return new byte[]{}; - } - - - public String toString() { - StringBuilder sb = new StringBuilder(getClass().getSimpleName()); - - sb.append(" [txData="); - sb.append(ByteUtil.shortHexString(getTxData())); - sb.append("]"); - - return sb.toString(); - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt new file mode 100644 index 0000000000..0dd03de7dd --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt @@ -0,0 +1,27 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil + +/** + * Created by geoff on 5/29/16. + */ +open class MessageBody { + + protected var data: ByteArray? = null + + open val length: Int + get() = 0 + + open fun init(rxData: ByteArray?) {} + + open val txData: ByteArray? + get() = if (data==null) byteArrayOf() else data + + override fun toString(): String { + val sb = StringBuilder(javaClass.simpleName) + sb.append(" [txData=") + sb.append(ByteUtil.shortHexString(txData)) + sb.append("]") + return sb.toString() + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java deleted file mode 100644 index f153dd8cac..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.java +++ /dev/null @@ -1,47 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by geoff on 5/29/16. - * refactored into enum - */ -public enum PacketType { - Invalid(0x00), // - MySentry(0xa2), // - Meter(0xa5), // - Carelink(0xa7), // - Sensor(0xa8) // - ; - - public static Map mapByValue; - - static { - mapByValue = new HashMap<>(); - - for (PacketType packetType : values()) { - mapByValue.put(packetType.value, packetType); - } - } - - private final byte value; - - - PacketType(int value) { - this.value = (byte)value; - } - - - public static PacketType getByValue(short value) { - if (mapByValue.containsKey(value)) - return mapByValue.get(value); - else - return PacketType.Invalid; - } - - - public byte getValue() { - return value; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.kt new file mode 100644 index 0000000000..68769944b1 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PacketType.kt @@ -0,0 +1,37 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +import java.util.* + +/** + * Created by geoff on 5/29/16. + * refactored into enum + */ +enum class PacketType(value: Int) { + + Invalid(0x00), // + MySentry(0xa2), // + Meter(0xa5), // + Carelink(0xa7), // + Sensor(0xa8 // + ); + + companion object { + var mapByValue: MutableMap = HashMap() + + fun getByValue(value: Short): PacketType? { + return if (mapByValue.containsKey(value.toByte())) mapByValue.get(value.toByte()) else Invalid + } + + init { + for (packetType in values()) { + mapByValue[packetType.value] = packetType + } + } + } + + val value: Byte + + init { + this.value = value.toByte() + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java deleted file mode 100644 index 4cfda08975..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.java +++ /dev/null @@ -1,16 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -/** - * Created by geoff on 5/29/16. - */ -public class PumpAckMessageBody extends CarelinkShortMessageBody { - - public PumpAckMessageBody() { - init(new byte[] { 0 }); - } - - - public PumpAckMessageBody(byte[] bodyData) { - init(bodyData); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.kt new file mode 100644 index 0000000000..39d85deb44 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpAckMessageBody.kt @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +/** + * Created by geoff on 5/29/16. + */ +class PumpAckMessageBody : CarelinkShortMessageBody { + + constructor() { + init(byteArrayOf(0)) + } + + constructor(bodyData: ByteArray?) { + init(bodyData) + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java deleted file mode 100644 index 71d50c4691..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.java +++ /dev/null @@ -1,214 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage; -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType; - -/** - * Created by geoff on 5/29/16. - */ -public class PumpMessage implements RLMessage { - - private final AAPSLogger aapsLogger; - - private PacketType packetType = PacketType.Carelink; - public byte[] address = new byte[]{0, 0, 0}; - public MedtronicCommandType commandType; - public Byte invalidCommandType; - public MessageBody messageBody = new MessageBody(); - public String error = null; - - public static final int FRAME_DATA_LENGTH = 64; - - - public PumpMessage(AAPSLogger aapsLogger, String error) { - this.error = error; - this.aapsLogger = aapsLogger; - } - - - public PumpMessage(AAPSLogger aapsLogger, byte[] rxData) { - this.aapsLogger = aapsLogger; - init(rxData); - } - - - public PumpMessage(AAPSLogger aapsLogger) { - this.aapsLogger = aapsLogger; - } - - - public boolean isErrorResponse() { - return (this.error != null); - } - - - public void init(PacketType packetType, byte[] address, MedtronicCommandType commandType, MessageBody messageBody) { - this.packetType = packetType; - this.address = address; - this.commandType = commandType; - this.messageBody = messageBody; - } - - - public void init(byte[] rxData) { - if (rxData == null) { - return; - } - if (rxData.length > 0) { - this.packetType = PacketType.getByValue(rxData[0]); - } - if (rxData.length > 3) { - this.address = ByteUtil.substring(rxData, 1, 3); - } - if (rxData.length > 4) { - this.commandType = MedtronicCommandType.getByCode(rxData[4]); - if (this.commandType == MedtronicCommandType.InvalidCommand) { - aapsLogger.error(LTag.PUMPCOMM, "PumpMessage - Unknown commandType " + rxData[4]); - } - } - if (rxData.length > 5) { - this.messageBody = MedtronicCommandType.constructMessageBody(commandType, - ByteUtil.substring(rxData, 5, rxData.length - 5)); - } - } - - - @Override - public byte[] getTxData() { - byte[] rval = ByteUtil.concat(new byte[]{packetType.getValue()}, address); - rval = ByteUtil.concat(rval, commandType.getCommandCode()); - rval = ByteUtil.concat(rval, messageBody.getTxData()); - return rval; - } - - - public byte[] getContents() { - return ByteUtil.concat(new byte[]{commandType.getCommandCode()}, messageBody.getTxData()); - } - - - // rawContent = just response without code (contents-2, messageBody.txData-1); - public byte[] getRawContent() { - - if ((messageBody == null) || (messageBody.getTxData() == null) || (messageBody.getTxData().length == 0)) - return null; - - byte[] data = messageBody.getTxData(); - - int length = ByteUtil.asUINT8(data[0]); // length is not always correct so, we check whole array if we have - // data, after length - int originalLength = length; - - // check if displayed length is invalid - if (length > data.length - 1) { - return data; - } - - // check Old Way - boolean oldWay = false; - for (int i = (length + 1); i < data.length; i++) { - if (data[i] != 0x00) { - oldWay = true; - } - } - - if (oldWay) { - length = data.length - 1; - } - - byte[] arrayOut = new byte[length]; - - System.arraycopy(messageBody.getTxData(), 1, arrayOut, 0, length); - -// if (isLogEnabled()) -// LOG.debug("PumpMessage - Length: " + length + ", Original Length: " + originalLength + ", CommandType: " -// + commandType); - - return arrayOut; - } - - - public byte[] getRawContentOfFrame() { - byte[] raw = messageBody.getTxData(); - if (raw==null || raw.length==0) { - return new byte[0]; - } else { - return ByteUtil.substring(raw, 1, Math.min(FRAME_DATA_LENGTH, raw.length - 1)); - } - } - - - public boolean isValid() { - if (packetType == null) - return false; - if (address == null) - return false; - if (commandType == null) - return false; - return messageBody != null; - } - - - public MessageBody getMessageBody() { - return messageBody; - } - - - public String getResponseContent() { - StringBuilder sb = new StringBuilder("PumpMessage [response="); - boolean showData = true; - - if (commandType != null) { - if (commandType == MedtronicCommandType.CommandACK) { - sb.append("Acknowledged"); - showData = false; - } else if (commandType == MedtronicCommandType.CommandNAK) { - sb.append("NOT Acknowledged"); - showData = false; - } else { - sb.append(commandType.name()); - } - } else { - sb.append("Unknown_Type"); - sb.append(" (" + invalidCommandType + ")"); - } - - if (showData) { - sb.append(", rawResponse="); - sb.append(ByteUtil.shortHexString(getRawContent())); - } - - sb.append("]"); - - return sb.toString(); - } - - - public String toString() { - StringBuilder sb = new StringBuilder("PumpMessage ["); - - sb.append("packetType="); - sb.append(packetType == null ? "null" : packetType.name()); - - sb.append(", address=("); - sb.append(ByteUtil.shortHexString(this.address)); - - sb.append("), commandType="); - sb.append(commandType == null ? "null" : commandType.name()); - - if (invalidCommandType != null) { - sb.append(", invalidCommandType="); - sb.append(invalidCommandType); - } - - sb.append(", messageBody=("); - sb.append(this.messageBody == null ? "null" : this.messageBody); - - sb.append(")]"); - - return sb.toString(); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt new file mode 100644 index 0000000000..3683f4e7c5 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt @@ -0,0 +1,183 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType + +/** + * Created by geoff on 5/29/16. + */ +class PumpMessage : RLMessage { + + private val aapsLogger: AAPSLogger + private var packetType: PacketType? = PacketType.Carelink + var address: ByteArray? = byteArrayOf(0, 0, 0) + var commandType: MedtronicCommandType? = null + var invalidCommandType: Byte? = null + var messageBody: MessageBody? = MessageBody() + var error: String? = null + + constructor(aapsLogger: AAPSLogger, error: String?) { + this.error = error + this.aapsLogger = aapsLogger + } + + constructor(aapsLogger: AAPSLogger, rxData: ByteArray?) { + this.aapsLogger = aapsLogger + init(rxData) + } + + constructor(aapsLogger: AAPSLogger) { + this.aapsLogger = aapsLogger + } + + val isErrorResponse: Boolean + get() = error != null + + fun init(packetType: PacketType?, address: ByteArray?, commandType: MedtronicCommandType?, messageBody: MessageBody?) { + this.packetType = packetType + this.address = address + this.commandType = commandType + this.messageBody = messageBody + } + + fun init(rxData: ByteArray?) { + if (rxData == null) { + return + } + if (rxData.size > 0) { + packetType = PacketType.getByValue(rxData[0].toShort()) + } + if (rxData.size > 3) { + address = ByteUtil.substring(rxData, 1, 3) + } + if (rxData.size > 4) { + commandType = MedtronicCommandType.getByCode(rxData[4]) + if (commandType == MedtronicCommandType.InvalidCommand) { + aapsLogger.error(LTag.PUMPCOMM, "PumpMessage - Unknown commandType " + rxData[4]) + } + } + if (rxData.size > 5) { + messageBody = MedtronicCommandType.constructMessageBody(commandType, + ByteUtil.substring(rxData, 5, rxData.size - 5)) + } + } + + override fun getTxData(): ByteArray { + var rval = ByteUtil.concat(byteArrayOf(packetType!!.value), address) + rval = ByteUtil.concat(rval, commandType!!.getCommandCode()) + rval = ByteUtil.concat(rval, messageBody!!.txData) + return rval + } + + val contents: ByteArray + get() = ByteUtil.concat(byteArrayOf(commandType!!.getCommandCode()), messageBody!!.txData)// length is not always correct so, we check whole array if we have + // data, after length + + // check if displayed length is invalid + + // check Old Way + +// if (isLogEnabled()) +// LOG.debug("PumpMessage - Length: " + length + ", Original Length: " + originalLength + ", CommandType: " +// + commandType); + + // rawContent = just response without code (contents-2, messageBody.txData-1); + val rawContent: ByteArray? + get() { + if (messageBody == null || messageBody!!.txData == null || messageBody!!.txData!!.size == 0) return null + val data = messageBody!!.txData + var length = ByteUtil.asUINT8(data!![0]) // length is not always correct so, we check whole array if we have + // data, after length + val originalLength = length + + // check if displayed length is invalid + if (length > data.size - 1) { + return data + } + + // check Old Way + var oldWay = false + for (i in length + 1 until data.size) { + if (data[i] != 0x00.toByte()) { + oldWay = true + } + } + if (oldWay) { + length = data.size - 1 + } + val arrayOut = ByteArray(length) + System.arraycopy(messageBody!!.txData, 1, arrayOut, 0, length) + +// if (isLogEnabled()) +// LOG.debug("PumpMessage - Length: " + length + ", Original Length: " + originalLength + ", CommandType: " +// + commandType); + return arrayOut + } + + val rawContentOfFrame: ByteArray + get() { + val raw = messageBody!!.txData + return if (raw == null || raw.size == 0) { + ByteArray(0) + } else { + ByteUtil.substring(raw, 1, Math.min(FRAME_DATA_LENGTH, raw.size - 1)) + } + } + + override fun isValid(): Boolean { + if (packetType == null) return false + if (address == null) return false + return if (commandType == null) false else messageBody != null + } + + val responseContent: String + get() { + val sb = StringBuilder("PumpMessage [response=") + var showData = true + if (commandType != null) { + if (commandType == MedtronicCommandType.CommandACK) { + sb.append("Acknowledged") + showData = false + } else if (commandType == MedtronicCommandType.CommandNAK) { + sb.append("NOT Acknowledged") + showData = false + } else { + sb.append(commandType!!.name) + } + } else { + sb.append("Unknown_Type") + sb.append(" ($invalidCommandType)") + } + if (showData) { + sb.append(", rawResponse=") + sb.append(ByteUtil.shortHexString(rawContent)) + } + sb.append("]") + return sb.toString() + } + + override fun toString(): String { + val sb = StringBuilder("PumpMessage [") + sb.append("packetType=") + sb.append(if (packetType == null) "null" else packetType!!.name) + sb.append(", address=(") + sb.append(ByteUtil.shortHexString(address)) + sb.append("), commandType=") + sb.append(if (commandType == null) "null" else commandType!!.name) + if (invalidCommandType != null) { + sb.append(", invalidCommandType=") + sb.append(invalidCommandType) + } + sb.append(", messageBody=(") + sb.append(if (messageBody == null) "null" else messageBody) + sb.append(")]") + return sb.toString() + } + + companion object { + const val FRAME_DATA_LENGTH = 64 + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java deleted file mode 100644 index 675a794bd8..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.java +++ /dev/null @@ -1,46 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.message; - -/** - * Created by geoff on 5/29/16. - */ -public class UnknownMessageBody extends MessageBody { - - public byte[] rxData; - - - public UnknownMessageBody(byte[] data) { - this.rxData = data; - } - - - @Override - public int getLength() { - return 0; - } - - - @Override - public void init(byte[] rxData) { - } - - - public byte[] getRxData() { - return rxData; - } - - - public void setRxData(byte[] rxData) { - this.rxData = rxData; - } - - - @Override - public byte[] getTxData() { - return rxData; - } - - - public void setTxData(byte[] txData) { - this.rxData = txData; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.kt new file mode 100644 index 0000000000..ba3c998d9e --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/UnknownMessageBody.kt @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.message + +/** + * Created by geoff on 5/29/16. + */ +class UnknownMessageBody(override var txData: ByteArray) : MessageBody() { + + override val length: Int + get() = 0 + + override fun init(rxData: ByteArray?) { + data = rxData + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java index 0d0f5ce006..580f0f8252 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java @@ -204,7 +204,7 @@ public class MedtronicHistoryData { } else { if (type == PumpHistoryEntryType.EndResultTotals) { - if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.atechDateTime)) { + if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.getAtechDateTime())) { newHistory2.add(pumpHistoryEntry); } } else { @@ -239,7 +239,7 @@ public class MedtronicHistoryData { for (PumpHistoryEntry bolusEstimate : bolusEstimates) { for (PumpHistoryEntry bolus : boluses) { - if (bolusEstimate.atechDateTime.equals(bolus.atechDateTime)) { + if (bolusEstimate.getAtechDateTime().equals(bolus.getAtechDateTime())) { bolus.addDecodedData("Estimate", bolusEstimate.getDecodedData().get("Object")); } } @@ -256,7 +256,7 @@ public class MedtronicHistoryData { // find last entry for (PumpHistoryEntry pumpHistoryEntry : newHistory) { - if (pumpHistoryEntry.atechDateTime != null && pumpHistoryEntry.isAfter(pheLast.atechDateTime)) { + if (pumpHistoryEntry.getAtechDateTime() != null && pumpHistoryEntry.isAfter(pheLast.getAtechDateTime())) { pheLast = pumpHistoryEntry; } } @@ -268,7 +268,7 @@ public class MedtronicHistoryData { if (!this.allHistory.contains(pumpHistoryEntry)) { lastIdUsed++; - pumpHistoryEntry.id = lastIdUsed; + pumpHistoryEntry.setId(lastIdUsed); this.allHistory.add(pumpHistoryEntry); } @@ -278,13 +278,13 @@ public class MedtronicHistoryData { if (pheLast == null) // if we don't have any valid record we don't do the filtering and setting return; - this.setLastHistoryRecordTime(pheLast.atechDateTime); - sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.atechDateTime); + this.setLastHistoryRecordTime(pheLast.getAtechDateTime()); + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.getAtechDateTime()); LocalDateTime dt = null; try { - dt = DateTimeUtil.toLocalDateTime(pheLast.atechDateTime); + dt = DateTimeUtil.toLocalDateTime(pheLast.getAtechDateTime()); } catch (Exception ex) { aapsLogger.error("Problem decoding date from last record: " + pheLast); } @@ -537,9 +537,9 @@ public class MedtronicHistoryData { continue; } - if (primeRecord.atechDateTime > maxAllowedTimeInPast) { - if (lastPrimeRecord < primeRecord.atechDateTime) { - lastPrimeRecord = primeRecord.atechDateTime; + if (primeRecord.getAtechDateTime() > maxAllowedTimeInPast) { + if (lastPrimeRecord < primeRecord.getAtechDateTime()) { + lastPrimeRecord = primeRecord.getAtechDateTime(); } } } @@ -560,9 +560,9 @@ public class MedtronicHistoryData { long lastRewindRecord = 0L; for (PumpHistoryEntry rewindRecord : rewindRecords) { - if (rewindRecord.atechDateTime > maxAllowedTimeInPast) { - if (lastRewindRecord < rewindRecord.atechDateTime) { - lastRewindRecord = rewindRecord.atechDateTime; + if (rewindRecord.getAtechDateTime() > maxAllowedTimeInPast) { + if (lastRewindRecord < rewindRecord.getAtechDateTime()) { + lastRewindRecord = rewindRecord.getAtechDateTime(); } } } @@ -593,7 +593,7 @@ public class MedtronicHistoryData { for (PumpHistoryEntry tdd : tdds) { - TDD tddDbEntry = findTDD(tdd.atechDateTime, tddsDb); + TDD tddDbEntry = findTDD(tdd.getAtechDateTime(), tddsDb); DailyTotalsDTO totalsDTO = (DailyTotalsDTO) tdd.getDecodedData().get("Object"); @@ -839,7 +839,7 @@ public class MedtronicHistoryData { */ private DbObjectBase findDbEntry(PumpHistoryEntry treatment, List entriesFromHistory) { - long proposedTime = DateTimeUtil.toMillisFromATD(treatment.atechDateTime); + long proposedTime = DateTimeUtil.toMillisFromATD(treatment.getAtechDateTime()); //proposedTime += (this.pumpTime.timeDifference * 1000); @@ -856,10 +856,10 @@ public class MedtronicHistoryData { // TODO: Fix db code // if difference is bigger than 2 minutes we discard entry - long maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.atechDateTime, 2); + long maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.getAtechDateTime(), 2); if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry maxMillisAllowed=%d, AtechDateTime=%d (add 2 minutes). ", maxMillisAllowed, treatment.atechDateTime)); + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry maxMillisAllowed=%d, AtechDateTime=%d (add 2 minutes). ", maxMillisAllowed, treatment.getAtechDateTime())); if (entriesFromHistory.get(0).getDate() > maxMillisAllowed) { if (doubleBolusDebug) @@ -970,7 +970,7 @@ public class MedtronicHistoryData { case Normal: { DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.atechDateTime)); + detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.getAtechDateTime())); detailedBolusInfo.setPumpType(PumpType.MEDTRONIC_512_712); // TODO grab real model detailedBolusInfo.setPumpSerial(medtronicPumpStatus.serialNumber); detailedBolusInfo.setBolusPumpId(bolus.getPumpId()); @@ -993,7 +993,7 @@ public class MedtronicHistoryData { case Audio: case Extended: { ExtendedBolus extendedBolus = new ExtendedBolus(injector); - extendedBolus.date = tryToGetByLocalTime(bolus.atechDateTime); + extendedBolus.date = tryToGetByLocalTime(bolus.getAtechDateTime()); extendedBolus.source = Source.PUMP; extendedBolus.insulin = bolusDTO.getDeliveredAmount(); extendedBolus.pumpId = bolus.getPumpId(); @@ -1060,7 +1060,7 @@ public class MedtronicHistoryData { if (temporaryBasalDb == null) { temporaryBasalDb = new TemporaryBasal(injector); - temporaryBasalDb.date = tryToGetByLocalTime(treatment.atechDateTime); + temporaryBasalDb.date = tryToGetByLocalTime(treatment.getAtechDateTime()); operation = "addTBR"; } @@ -1094,7 +1094,7 @@ public class MedtronicHistoryData { if (tempBasal == null) { // add tempBasal = new TemporaryBasal(injector); - tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne.atechDateTime); + tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne.getAtechDateTime()); tempBasal.source = Source.PUMP; tempBasal.pumpId = tempBasalProcess.itemOne.getPumpId(); @@ -1346,8 +1346,8 @@ public class MedtronicHistoryData { for (PumpHistoryEntry treatment : treatments) { - if (treatment.atechDateTime < dt) { - dt = treatment.atechDateTime; + if (treatment.getAtechDateTime() < dt) { + dt = treatment.getAtechDateTime(); currentTreatment = treatment; } } @@ -1386,8 +1386,8 @@ public class MedtronicHistoryData { for (PumpHistoryEntry treatment : treatments) { - if (treatment.atechDateTime < dt) { - dt = treatment.atechDateTime; + if (treatment.getAtechDateTime() < dt) { + dt = treatment.getAtechDateTime(); currentTreatment = treatment; } } @@ -1469,9 +1469,9 @@ public class MedtronicHistoryData { for (PumpHistoryEntry filteredItem : filteredItems) { - if (lastDate == null || lastDate < filteredItem.atechDateTime) { + if (lastDate == null || lastDate < filteredItem.getAtechDateTime()) { newProfile = filteredItem; - lastDate = newProfile.atechDateTime; + lastDate = newProfile.getAtechDateTime(); } } } @@ -1517,13 +1517,13 @@ public class MedtronicHistoryData { Map map = new HashMap<>(); for (PumpHistoryEntry pumpHistoryEntry : TBRs_Input) { - if (map.containsKey(pumpHistoryEntry.DT)) { - medtronicPumpHistoryDecoder.decodeTempBasal(map.get(pumpHistoryEntry.DT), pumpHistoryEntry); + if (map.containsKey(pumpHistoryEntry.getDT())) { + medtronicPumpHistoryDecoder.decodeTempBasal(map.get(pumpHistoryEntry.getDT()), pumpHistoryEntry); pumpHistoryEntry.setEntryType(medtronicUtil.getMedtronicPumpModel(), PumpHistoryEntryType.TempBasalCombined); TBRs.add(pumpHistoryEntry); - map.remove(pumpHistoryEntry.DT); + map.remove(pumpHistoryEntry.getDT()); } else { - map.put(pumpHistoryEntry.DT, pumpHistoryEntry); + map.put(pumpHistoryEntry.getDT(), pumpHistoryEntry); } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java index ae15a51c07..f32464b105 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java @@ -74,15 +74,15 @@ public class DailyTotalsDTO { break; case DailyTotals515: - decodeDailyTotals515(entry.body); + decodeDailyTotals515(entry.getBody()); break; case DailyTotals522: - decodeDailyTotals522(entry.body); + decodeDailyTotals522(entry.getBody()); break; case DailyTotals523: - decodeDailyTotals523(entry.body); + decodeDailyTotals523(entry.getBody()); break; default: @@ -96,18 +96,18 @@ public class DailyTotalsDTO { private void setDisplayable() { if (this.insulinBasal == null) { - this.entry.displayableValue = "Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2); + this.entry.setDisplayableValue("Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2)); } else { - this.entry.displayableValue = "Basal Insulin: " + StringUtil.getFormatedValueUS(this.insulinBasal, 2) - + ", Total Insulin: " + StringUtil.getFormatedValueUS(this.insulinTotal, 2); + 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.head[0], (int) entry.head[1], (int) entry.head[2], - (int) entry.head[3], ByteUtil.BitConversion.BIG_ENDIAN) * 0.025d; + 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; @@ -241,7 +241,7 @@ public class DailyTotalsDTO { } public void setTDD(TDD tdd) { - tdd.date = DateTimeUtil.toMillisFromATD(this.entry.atechDateTime); + tdd.date = DateTimeUtil.toMillisFromATD(this.entry.getAtechDateTime()); tdd.basal = insulinBasal; tdd.bolus = insulinBolus; tdd.total = insulinTotal; diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java index 86cba28184..f35a5b43c0 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java @@ -15,7 +15,7 @@ public class TempBasalProcessDTO { TempBasalPair tbr = (TempBasalPair) itemOne.getDecodedDataEntry("Object"); return tbr.getDurationMinutes(); } else { - int difference = DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne.atechDateTime, itemTwo.atechDateTime); + int difference = DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne.getAtechDateTime(), itemTwo.getAtechDateTime()); return difference; } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt index 0a324648e8..5e9958fee9 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt @@ -1,7 +1,9 @@ package info.nightscout.androidaps.plugins.pump.medtronic.di import dagger.Module +import dagger.Provides import dagger.android.ContributesAndroidInjector +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicFragment import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunicationManager import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUITask @@ -20,4 +22,9 @@ abstract class MedtronicModule { @ContributesAndroidInjector abstract fun medtronicCommunicationManagerProvider(): MedtronicCommunicationManager @ContributesAndroidInjector abstract fun medtronicUITaskProvider(): MedtronicUITask @ContributesAndroidInjector abstract fun contributesRileyLinkStatusDeviceMedtronic(): RileyLinkStatusDeviceMedtronic + + companion object { + @Provides + fun byteUtilProvider(): ByteUtil = ByteUtil(); + } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java index a2ce6c00e7..fc986f4f83 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java @@ -59,7 +59,7 @@ public class MedtronicHistoryActivity extends NoSplashAppCompatActivity { this.filteredHistoryList.addAll(list); } else { for (PumpHistoryEntry pumpHistoryEntry : list) { - if (pumpHistoryEntry.getEntryType().group == group) { + if (pumpHistoryEntry.getEntryType().getGroup() == group) { this.filteredHistoryList.add(pumpHistoryEntry); } } @@ -214,7 +214,7 @@ public class MedtronicHistoryActivity extends NoSplashAppCompatActivity { if (record != null) { holder.timeView.setText(record.getDateTimeString()); holder.typeView.setText(record.getEntryType().getDescription()); - holder.valueView.setText(record.displayableValue); + holder.valueView.setText(record.getDisplayableValue()); } } diff --git a/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryUTest.java b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryUTest.java index af8c7b0d0a..043a2fdd86 100644 --- a/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryUTest.java +++ b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryUTest.java @@ -16,7 +16,7 @@ public class PumpHistoryEntryUTest { long queryObject = 20191009000000L; PumpHistoryEntry phe = new PumpHistoryEntry(); - phe.atechDateTime = dateObject; + phe.setAtechDateTime(dateObject); Assert.assertTrue(phe.isAfter(queryObject)); } From bb657a249833a28be46c1e2e00d35df188e6dac8 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Fri, 16 Apr 2021 23:41:24 +0100 Subject: [PATCH 04/39] - kotlin changes - disabled problem in Fragment for now --- .../pump/medtronic/MedtronicFragment.kt | 20 +- .../pump/medtronic/MedtronicPumpPlugin.java | 6 +- .../medtronic/comm/MedtronicConverter.java | 444 ------------------ .../pump/medtronic/comm/MedtronicConverter.kt | 314 +++++++++++++ .../cgms/MedtronicCGMSHistoryDecoder.kt | 4 +- .../pump/medtronic/data/dto/BasalProfile.java | 384 --------------- .../pump/medtronic/data/dto/BasalProfile.kt | 315 +++++++++++++ .../medtronic/data/dto/BasalProfileEntry.java | 81 ---- .../medtronic/data/dto/BasalProfileEntry.kt | 74 +++ .../medtronic/defs/MedtronicCommandType.java | 60 --- 10 files changed, 723 insertions(+), 979 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index d9124ec15e..43a75631bf 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -311,13 +311,21 @@ class MedtronicFragment : DaggerFragment() { binding.lastBolus.text = "" } - val pumpState = pumpSync.expectedPumpState() - // base basal rate - binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " - + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) + if (true) { + // base basal rate + binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " + + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) - binding.tempBasal.text = pumpState.temporaryBasal?.toStringFull(dateUtil) - ?: "" + binding.tempBasal.text = "??" + } else { + val pumpState = pumpSync.expectedPumpState() + // base basal rate + binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " + + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) + + binding.tempBasal.text = pumpState.temporaryBasal?.toStringFull(dateUtil) + ?: "" + } // battery if (medtronicPumpStatus.batteryType == BatteryType.None || medtronicPumpStatus.batteryVoltage == null) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java index f41fb04348..b514ec7d3a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -1499,10 +1499,10 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril for (BasalProfileEntry profileEntry : basalProfile.getEntries()) { - if (profileEntry.rate > medtronicPumpStatus.maxBasal) { - stringBuilder.append(profileEntry.startTime.toString("HH:mm")); + if (profileEntry.getRate() > medtronicPumpStatus.maxBasal) { + stringBuilder.append(profileEntry.getStartTime().toString("HH:mm")); stringBuilder.append("="); - stringBuilder.append(profileEntry.rate); + stringBuilder.append(profileEntry.getRate()); } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java deleted file mode 100644 index f9ad49b723..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.java +++ /dev/null @@ -1,444 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm; - -import org.joda.time.IllegalFieldValueException; -import org.joda.time.LocalDateTime; - -import java.util.HashMap; -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.pump.common.defs.PumpType; -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; -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.PumpSettingDTO; -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.MedtronicDeviceType; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - -/** - * Created by andy on 5/9/18. - * High level decoder for data returned through MedtroniUIComm - */ - -@Singleton -public class MedtronicConverter { - - private final AAPSLogger aapsLogger; - private final MedtronicUtil medtronicUtil; - - @Inject - public MedtronicConverter( - AAPSLogger aapsLogger, - MedtronicUtil medtronicUtil - ) { - this.aapsLogger = aapsLogger; - this.medtronicUtil = medtronicUtil; - } - - Object convertResponse(PumpType pumpType, MedtronicCommandType commandType, byte[] rawContent) { - - if ((rawContent == null || rawContent.length < 1) && commandType != MedtronicCommandType.PumpModel) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Content is empty or too short, no data to convert (type=%s,isNull=%b,length=%s)", - commandType.name(), rawContent == null, rawContent == null ? "-" : rawContent.length)); - return null; - } - - aapsLogger.debug(LTag.PUMPCOMM, "Raw response before convert: " + ByteUtil.shortHexString(rawContent)); - - switch (commandType) { - - case PumpModel: { - return decodeModel(rawContent); - } - - case GetRealTimeClock: { - return decodeTime(rawContent); - } - - case GetRemainingInsulin: { - return decodeRemainingInsulin(rawContent); - } - - case GetBatteryStatus: { - return decodeBatteryStatus(rawContent); // 1 - } - - case GetBasalProfileSTD: - case GetBasalProfileA: - case GetBasalProfileB: { - return decodeBasalProfile(pumpType, rawContent); - - } - - case ReadTemporaryBasal: { - return new TempBasalPair(aapsLogger, rawContent); // 5 - } - - case Settings_512: { - return decodeSettingsLoop(rawContent); - } - - case Settings: { - return decodeSettingsLoop(rawContent); - } - - case SetBolus: { - return rawContent; // 1 - } - - default: { - throw new RuntimeException("Unsupported command Type: " + commandType); - } - - } - - } - - - private BasalProfile decodeBasalProfile(PumpType pumpType, byte[] rawContent) { - - BasalProfile basalProfile = new BasalProfile(aapsLogger, rawContent); - - return basalProfile.verify(pumpType) ? basalProfile : null; - } - - - private MedtronicDeviceType decodeModel(byte[] rawContent) { - - if ((rawContent == null || rawContent.length < 4)) { - aapsLogger.warn(LTag.PUMPCOMM, "Error reading PumpModel, returning Unknown_Device"); - return MedtronicDeviceType.Unknown_Device; - } - - String rawModel = StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3)); - MedtronicDeviceType pumpModel = MedtronicDeviceType.getByDescription(rawModel); - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "PumpModel: [raw=%s, resolved=%s]", rawModel, pumpModel.name())); - - if (pumpModel != MedtronicDeviceType.Unknown_Device) { - if (!medtronicUtil.isModelSet()) { - medtronicUtil.setMedtronicPumpModel(pumpModel); - } - } - - return pumpModel; - } - - - private BatteryStatusDTO decodeBatteryStatus(byte[] rawData) { - // 00 7C 00 00 - - BatteryStatusDTO batteryStatus = new BatteryStatusDTO(); - - int status = rawData[0]; - - if (status == 0) { - batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Normal; - } else if (status == 1) { - batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Low; - } else if (status == 2) { - batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown; - } - - if (rawData.length > 1) { - - Double d = null; - - // if response in 3 bytes then we add additional information - if (rawData.length == 2) { - d = (rawData[1] * 1.0d) / 100.0d; - } else { - d = (ByteUtil.toInt(rawData[1], rawData[2]) * 1.0d) / 100.0d; - } - - batteryStatus.voltage = d; - batteryStatus.extendedDataReceived = true; - } - - return batteryStatus; - } - - - private Float decodeRemainingInsulin(byte[] rawData) { - int startIdx = 0; - - MedtronicDeviceType pumpModel = medtronicUtil.getMedtronicPumpModel(); - - int strokes = pumpModel == null ? 10 : pumpModel.getBolusStrokes(); - - if (strokes == 40) { - startIdx = 2; - } - - int reqLength = startIdx + 1; - float value = 0; - - if (reqLength >= rawData.length) { - value = rawData[startIdx] / (1.0f * strokes); - } else { - value = ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0f * strokes); - } - - aapsLogger.debug(LTag.PUMPCOMM, "Remaining insulin: " + value); - return value; - } - - - private LocalDateTime decodeTime(byte[] rawContent) { - - int hours = ByteUtil.asUINT8(rawContent[0]); - int minutes = ByteUtil.asUINT8(rawContent[1]); - int seconds = ByteUtil.asUINT8(rawContent[2]); - int year = (ByteUtil.asUINT8(rawContent[4]) & 0x3f) + 1984; - int month = ByteUtil.asUINT8(rawContent[5]); - int day = ByteUtil.asUINT8(rawContent[6]); - try { - LocalDateTime pumpTime = new LocalDateTime(year, month, day, hours, minutes, seconds); - return pumpTime; - } catch (IllegalFieldValueException e) { - aapsLogger.error(LTag.PUMPCOMM, - String.format(Locale.ENGLISH, "decodeTime: Failed to parse pump time value: year=%d, month=%d, hours=%d, minutes=%d, seconds=%d", - year, month, day, hours, minutes, seconds)); - return null; - } - - } - - - private Map decodeSettingsLoop(byte[] rd) { - - Map map = new HashMap<>(); - - addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map); - addSettingToMap( - "PCFG_MAX_BASAL", - "" - + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[getSettingIndexMaxBasal()], - rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal, map); - addSettingToMap("CFG_BASE_CLOCK_MODE", rd[getSettingIndexTimeDisplayFormat()] == 0 ? "12h" : "24h", - PumpConfigurationGroup.General, map); - - addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal, map); - - if (rd[10] == 1) { - String patt; - switch (rd[11]) { - case 0: - patt = "STD"; - break; - - case 1: - patt = "A"; - break; - - case 2: - patt = "B"; - break; - - default: - patt = "???"; - break; - } - - addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map); - - } else { - addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", "STD", PumpConfigurationGroup.Basal, map); - } - - addSettingToMap("PCFG_TEMP_BASAL_TYPE", rd[14] != 0 ? "Percent" : "Units", PumpConfigurationGroup.Basal, map); - - return map; - } - - - private Map decodeSettings512(byte[] rd) { - - Map map = new HashMap<>(); - - addSettingToMap("PCFG_AUTOOFF_TIMEOUT", "" + rd[0], PumpConfigurationGroup.General, map); - - if (rd[1] == 4) { - addSettingToMap("PCFG_ALARM_MODE", "Silent", PumpConfigurationGroup.Sound, map); - } else { - addSettingToMap("PCFG_ALARM_MODE", "Normal", PumpConfigurationGroup.Sound, map); - addSettingToMap("PCFG_ALARM_BEEP_VOLUME", "" + rd[1], PumpConfigurationGroup.Sound, map); - } - - addSettingToMap("PCFG_AUDIO_BOLUS_ENABLED", parseResultEnable(rd[2]), PumpConfigurationGroup.Bolus, map); - - if (rd[2] == 1) { - addSettingToMap("PCFG_AUDIO_BOLUS_STEP_SIZE", "" + decodeBolusInsulin(ByteUtil.asUINT8(rd[3])), - PumpConfigurationGroup.Bolus, map); - } - - addSettingToMap("PCFG_VARIABLE_BOLUS_ENABLED", parseResultEnable(rd[4]), PumpConfigurationGroup.Bolus, map); - addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map); - addSettingToMap( - "PCFG_MAX_BASAL", - "" - + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[getSettingIndexMaxBasal()], - rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal, map); - addSettingToMap("CFG_BASE_CLOCK_MODE", rd[getSettingIndexTimeDisplayFormat()] == 0 ? "12h" : "24h", - PumpConfigurationGroup.General, map); - - if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { - addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] == 0 ? 50 : 100), PumpConfigurationGroup.Insulin, - map); -// LOG.debug("Insulin concentration: " + rd[9]); - } else { - addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] != 0 ? 50 : 100), PumpConfigurationGroup.Insulin, - map); -// LOG.debug("Insulin concentration: " + rd[9]); - } - addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal, map); - - if (rd[10] == 1) { - String patt; - switch (rd[11]) { - case 0: - patt = "STD"; - break; - - case 1: - patt = "A"; - break; - - case 2: - patt = "B"; - break; - - default: - patt = "???"; - break; - } - - addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map); - - } - - addSettingToMap("CFG_MM_RF_ENABLED", parseResultEnable(rd[12]), PumpConfigurationGroup.General, map); - addSettingToMap("CFG_MM_BLOCK_ENABLED", parseResultEnable(rd[13]), PumpConfigurationGroup.General, map); - - addSettingToMap("PCFG_TEMP_BASAL_TYPE", rd[14] != 0 ? "Percent" : "Units", PumpConfigurationGroup.Basal, map); - - if (rd[14] == 1) { - addSettingToMap("PCFG_TEMP_BASAL_PERCENT", "" + rd[15], PumpConfigurationGroup.Basal, map); - } - - addSettingToMap("CFG_PARADIGM_LINK_ENABLE", parseResultEnable(rd[16]), PumpConfigurationGroup.General, map); - - decodeInsulinActionSetting(rd, map); - - return map; - } - - - private void addSettingToMap(String key, String value, PumpConfigurationGroup group, Map map) { - map.put(key, new PumpSettingDTO(key, value, group)); - } - - - public Map decodeSettings(byte[] rd) { - Map map = decodeSettings512(rd); - - addSettingToMap("PCFG_MM_RESERVOIR_WARNING_TYPE_TIME", rd[18] != 0 ? "PCFG_MM_RESERVOIR_WARNING_TYPE_TIME" - : "PCFG_MM_RESERVOIR_WARNING_TYPE_UNITS", PumpConfigurationGroup.Other, map); - - addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), - PumpConfigurationGroup.Other, map); - - addSettingToMap("CFG_MM_KEYPAD_LOCKED", parseResultEnable(rd[20]), PumpConfigurationGroup.Other, map); - - if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) { - - addSettingToMap("PCFG_BOLUS_SCROLL_STEP_SIZE", "" + rd[21], PumpConfigurationGroup.Bolus, map); - addSettingToMap("PCFG_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22]), PumpConfigurationGroup.Other, map); - addSettingToMap("PCFG_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23]), PumpConfigurationGroup.Other, map); - addSettingToMap("PCFG_OTHER_DEVICE_PAIRED_STATE", parseResultEnable(rd[24]), PumpConfigurationGroup.Other, - map); - } - - return map; - } - - - private String parseResultEnable(int i) { - switch (i) { - case 0: - return "No"; - case 1: - return "Yes"; - default: - return "???"; - } - } - - - private float getStrokesPerUnit(boolean isBasal) { - return isBasal ? 40.0f : 10; // pumpModel.getBolusStrokes(); - } - - - // 512 - private void decodeInsulinActionSetting(byte[] ai, Map map) { - if (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_512_712)) { - addSettingToMap("PCFG_INSULIN_ACTION_TYPE", (ai[17] != 0 ? "Regular" : "Fast"), - PumpConfigurationGroup.Insulin, map); - } else { - int i = ai[17]; - String s; - - if ((i == 0) || (i == 1)) { - s = ai[17] != 0 ? "Regular" : "Fast"; - } else { - if (i == 15) - s = "Unset"; - else - s = "Curve: " + i; - } - - addSettingToMap("PCFG_INSULIN_ACTION_TYPE", s, PumpConfigurationGroup.Insulin, map); - } - } - - - private double decodeBasalInsulin(int i) { - return (double) i / (double) getStrokesPerUnit(true); - } - - - private double decodeBolusInsulin(int i) { - - return (double) i / (double) getStrokesPerUnit(false); - } - - - private int getSettingIndexMaxBasal() { - return is523orHigher() ? 7 : 6; - } - - - private int getSettingIndexTimeDisplayFormat() { - return is523orHigher() ? 9 : 8; - } - - - private double decodeMaxBolus(byte[] ai) { - return is523orHigher() ? decodeBolusInsulin(ByteUtil.toInt(ai[5], ai[6])) : decodeBolusInsulin(ByteUtil - .asUINT8(ai[5])); - } - - - private boolean is523orHigher() { - return (MedtronicDeviceType.isSameDevice(medtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt new file mode 100644 index 0000000000..3796661ef5 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt @@ -0,0 +1,314 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm + +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil +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.PumpSettingDTO +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.MedtronicDeviceType +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import org.joda.time.IllegalFieldValueException +import org.joda.time.LocalDateTime +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Created by andy on 5/9/18. + * High level decoder for data returned through MedtroniUIComm + */ +@Singleton +class MedtronicConverter @Inject constructor( + private val aapsLogger: AAPSLogger, + private val medtronicUtil: MedtronicUtil +) { + + fun convertResponse(pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray?): Any? { + if ((rawContent == null || rawContent.size < 1) && commandType != MedtronicCommandType.PumpModel) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Content is empty or too short, no data to convert (type=%s,isNull=%b,length=%s)", + commandType.name, rawContent == null, rawContent?.size ?: "-")) + return null + } + aapsLogger.debug(LTag.PUMPCOMM, "Raw response before convert: " + ByteUtil.shortHexString(rawContent)) + return when (commandType) { + MedtronicCommandType.PumpModel -> { + decodeModel(rawContent) + } + + MedtronicCommandType.GetRealTimeClock -> { + decodeTime(rawContent) + } + + MedtronicCommandType.GetRemainingInsulin -> { + decodeRemainingInsulin(rawContent) + } + + MedtronicCommandType.GetBatteryStatus -> { + decodeBatteryStatus(rawContent) // 1 + } + + MedtronicCommandType.GetBasalProfileSTD, MedtronicCommandType.GetBasalProfileA, MedtronicCommandType.GetBasalProfileB -> { + decodeBasalProfile(pumpType, rawContent) + } + + MedtronicCommandType.ReadTemporaryBasal -> { + TempBasalPair(aapsLogger, rawContent) // 5 + } + + MedtronicCommandType.Settings_512 -> { + decodeSettingsLoop(rawContent) + } + + MedtronicCommandType.Settings -> { + decodeSettingsLoop(rawContent) + } + + MedtronicCommandType.SetBolus -> { + rawContent // 1 + } + + else -> { + throw RuntimeException("Unsupported command Type: $commandType") + } + } + } + + private fun decodeBasalProfile(pumpType: PumpType, rawContent: ByteArray?): BasalProfile? { + val basalProfile = BasalProfile(aapsLogger, rawContent!!) + return if (basalProfile.verify(pumpType)) basalProfile else null + } + + private fun decodeModel(rawContent: ByteArray?): MedtronicDeviceType { + if (rawContent == null || rawContent.size < 4) { + aapsLogger.warn(LTag.PUMPCOMM, "Error reading PumpModel, returning Unknown_Device") + return MedtronicDeviceType.Unknown_Device + } + val rawModel = StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3)) + val pumpModel = MedtronicDeviceType.getByDescription(rawModel) + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "PumpModel: [raw=%s, resolved=%s]", rawModel, pumpModel.name)) + if (pumpModel != MedtronicDeviceType.Unknown_Device) { + if (!medtronicUtil.isModelSet) { + medtronicUtil.medtronicPumpModel = pumpModel + } + } + return pumpModel + } + + private fun decodeBatteryStatus(rawData: ByteArray?): BatteryStatusDTO { + // 00 7C 00 00 + val batteryStatus = BatteryStatusDTO() + val status = rawData!![0].toInt() + if (status == 0) { + batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Normal + } else if (status == 1) { + batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Low + } else if (status == 2) { + batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown + } + if (rawData.size > 1) { + var d: Double? = null + + // if response in 3 bytes then we add additional information + d = if (rawData.size == 2) { + rawData[1] * 1.0 / 100.0 + } else { + ByteUtil.toInt(rawData[1], rawData[2]) * 1.0 / 100.0 + } + batteryStatus.voltage = d + batteryStatus.extendedDataReceived = true + } + return batteryStatus + } + + private fun decodeRemainingInsulin(rawData: ByteArray?): Float { + var startIdx = 0 + val pumpModel = medtronicUtil.medtronicPumpModel + val strokes = pumpModel?.bolusStrokes ?: 10 + if (strokes == 40) { + startIdx = 2 + } + val reqLength = startIdx + 1 + var value = 0f + value = if (reqLength >= rawData!!.size) { + rawData[startIdx] / (1.0f * strokes) + } else { + ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0f * strokes) + } + aapsLogger.debug(LTag.PUMPCOMM, "Remaining insulin: $value") + return value + } + + private fun decodeTime(rawContent: ByteArray?): LocalDateTime? { + val hours = ByteUtil.asUINT8(rawContent!![0]) + val minutes = ByteUtil.asUINT8(rawContent[1]) + val seconds = ByteUtil.asUINT8(rawContent[2]) + val year = (ByteUtil.asUINT8(rawContent[4]) and 0x3f) + 1984 + val month = ByteUtil.asUINT8(rawContent[5]) + val day = ByteUtil.asUINT8(rawContent[6]) + return try { + LocalDateTime(year, month, day, hours, minutes, seconds) + } catch (e: IllegalFieldValueException) { + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "decodeTime: Failed to parse pump time value: year=%d, month=%d, hours=%d, minutes=%d, seconds=%d", + year, month, day, hours, minutes, seconds)) + null + } + } + + private fun decodeSettingsLoop(rd: ByteArray?): Map { + val map: MutableMap = HashMap() + addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map) + addSettingToMap( + "PCFG_MAX_BASAL", "" + + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd!![settingIndexMaxBasal].toInt(), + rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map) + addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h", + PumpConfigurationGroup.General, map) + addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10].toInt()), PumpConfigurationGroup.Basal, map) + if (rd[10].toInt() == 1) { + val patt: String + patt = when (rd[11].toInt()) { + 0 -> "STD" + 1 -> "A" + 2 -> "B" + else -> "???" + } + addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map) + } else { + addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", "STD", PumpConfigurationGroup.Basal, map) + } + addSettingToMap("PCFG_TEMP_BASAL_TYPE", if (rd[14].toInt() != 0) "Percent" else "Units", PumpConfigurationGroup.Basal, map) + return map + } + + private fun decodeSettings512(rd: ByteArray): MutableMap { + val map: MutableMap = HashMap() + addSettingToMap("PCFG_AUTOOFF_TIMEOUT", "" + rd[0], PumpConfigurationGroup.General, map) + if (rd[1].toInt() == 4) { + addSettingToMap("PCFG_ALARM_MODE", "Silent", PumpConfigurationGroup.Sound, map) + } else { + addSettingToMap("PCFG_ALARM_MODE", "Normal", PumpConfigurationGroup.Sound, map) + addSettingToMap("PCFG_ALARM_BEEP_VOLUME", "" + rd[1], PumpConfigurationGroup.Sound, map) + } + addSettingToMap("PCFG_AUDIO_BOLUS_ENABLED", parseResultEnable(rd[2].toInt()), PumpConfigurationGroup.Bolus, map) + if (rd[2].toInt() == 1) { + addSettingToMap("PCFG_AUDIO_BOLUS_STEP_SIZE", "" + decodeBolusInsulin(ByteUtil.asUINT8(rd[3])), + PumpConfigurationGroup.Bolus, map) + } + addSettingToMap("PCFG_VARIABLE_BOLUS_ENABLED", parseResultEnable(rd[4].toInt()), PumpConfigurationGroup.Bolus, map) + addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map) + addSettingToMap( + "PCFG_MAX_BASAL", "" + + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[settingIndexMaxBasal].toInt(), + rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map) + addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h", + PumpConfigurationGroup.General, map) + if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { + addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + if (rd[9].toInt() == 0) 50 else 100, PumpConfigurationGroup.Insulin, + map) + // LOG.debug("Insulin concentration: " + rd[9]); + } else { + addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + if (rd[9].toInt() != 0) 50 else 100, PumpConfigurationGroup.Insulin, + map) + // LOG.debug("Insulin concentration: " + rd[9]); + } + addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10].toInt()), PumpConfigurationGroup.Basal, map) + if (rd[10].toInt() == 1) { + val patt: String + patt = when (rd[11].toInt()) { + 0 -> "STD" + 1 -> "A" + 2 -> "B" + else -> "???" + } + addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map) + } + addSettingToMap("CFG_MM_RF_ENABLED", parseResultEnable(rd[12].toInt()), PumpConfigurationGroup.General, map) + addSettingToMap("CFG_MM_BLOCK_ENABLED", parseResultEnable(rd[13].toInt()), PumpConfigurationGroup.General, map) + addSettingToMap("PCFG_TEMP_BASAL_TYPE", if (rd[14].toInt() != 0) "Percent" else "Units", PumpConfigurationGroup.Basal, map) + if (rd[14].toInt() == 1) { + addSettingToMap("PCFG_TEMP_BASAL_PERCENT", "" + rd[15], PumpConfigurationGroup.Basal, map) + } + addSettingToMap("CFG_PARADIGM_LINK_ENABLE", parseResultEnable(rd[16].toInt()), PumpConfigurationGroup.General, map) + decodeInsulinActionSetting(rd, map) + return map + } + + private fun addSettingToMap(key: String, value: String, group: PumpConfigurationGroup, map: MutableMap) { + map[key] = PumpSettingDTO(key, value, group) + } + + fun decodeSettings(rd: ByteArray): Map { + val map = decodeSettings512(rd) + addSettingToMap("PCFG_MM_RESERVOIR_WARNING_TYPE_TIME", if (rd[18].toInt() != 0) "PCFG_MM_RESERVOIR_WARNING_TYPE_TIME" else "PCFG_MM_RESERVOIR_WARNING_TYPE_UNITS", PumpConfigurationGroup.Other, map) + addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), + PumpConfigurationGroup.Other, map) + addSettingToMap("CFG_MM_KEYPAD_LOCKED", parseResultEnable(rd[20].toInt()), PumpConfigurationGroup.Other, map) + if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { + 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_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23].toInt()), PumpConfigurationGroup.Other, map) + addSettingToMap("PCFG_OTHER_DEVICE_PAIRED_STATE", parseResultEnable(rd[24].toInt()), PumpConfigurationGroup.Other, + map) + } + return map + } + + private fun parseResultEnable(i: Int): String { + return when (i) { + 0 -> "No" + 1 -> "Yes" + else -> "???" + } + } + + private fun getStrokesPerUnit(isBasal: Boolean): Float { + return if (isBasal) 40.0f else 10.0f // pumpModel.getBolusStrokes(); + } + + // 512 + private fun decodeInsulinActionSetting(ai: ByteArray, map: MutableMap) { + if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712)) { + addSettingToMap("PCFG_INSULIN_ACTION_TYPE", if (ai[17].toInt() != 0) "Regular" else "Fast", + PumpConfigurationGroup.Insulin, map) + } else { + val i = ai[17].toInt() + val s: String + s = if (i == 0 || i == 1) { + if (ai[17].toInt() != 0) "Regular" else "Fast" + } else { + if (i == 15) "Unset" else "Curve: $i" + } + addSettingToMap("PCFG_INSULIN_ACTION_TYPE", s, PumpConfigurationGroup.Insulin, map) + } + } + + private fun decodeBasalInsulin(i: Int): Double { + return i.toDouble() / getStrokesPerUnit(true).toDouble() + } + + private fun decodeBolusInsulin(i: Int): Double { + return i.toDouble() / getStrokesPerUnit(false).toDouble() + } + + private val settingIndexMaxBasal: Int + private get() = if (is523orHigher()) 7 else 6 + + private val settingIndexTimeDisplayFormat: Int + private get() = if (is523orHigher()) 9 else 8 + + private fun decodeMaxBolus(ai: ByteArray?): Double { + return if (is523orHigher()) decodeBolusInsulin(ByteUtil.toInt(ai!![5], ai[6])) else decodeBolusInsulin(ByteUtil + .asUINT8(ai!![5])) + } + + private fun is523orHigher(): Boolean { + return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher) + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index d56798dd3a..77f1ee32c1 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -10,7 +10,9 @@ import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSH import okhttp3.internal.and import org.joda.time.LocalDateTime import org.slf4j.Logger +import org.slf4j.LoggerFactory import java.util.* +import org.slf4j.LoggerFactory.getLogger as getLogger1 /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes @@ -264,6 +266,6 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() } companion object { - private val LOG: Logger = getLogger(LTag.PUMPCOMM) + private val LOG: Logger = getLogger1("MedtronicCGMSHistoryDecoder") } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java deleted file mode 100644 index 3cbd03f20d..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.java +++ /dev/null @@ -1,384 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; - -import androidx.annotation.NonNull; - -import com.google.gson.annotations.Expose; - -import org.joda.time.Instant; - -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.defs.PumpType; -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - -/** - * Created by geoff on 6/1/15. - *

- * There are three basal profiles stored on the pump. (722 only?) They are all parsed the same, the user just has 3 to - * choose from: Standard, A, and B - *

- * The byte array is 48 times three byte entries long, plus a zero? If the profile is completely empty, it should have - * one entry: [0,0,0x3F]. The first entry of [0,0,0] marks the end of the used entries. - *

- * Each entry is assumed to span from the specified start time to the start time of the next entry, or to midnight if - * there are no more entries. - *

- * Individual entries are of the form [r,z,m] where r is the rate (in 0.025 U increments) z is zero (?) m is the start - * time-of-day for the basal rate period (in 30 minute increments) - */ -public class BasalProfile { - - private final AAPSLogger aapsLogger; - - public static final int MAX_RAW_DATA_SIZE = (48 * 3) + 1; - private static final boolean DEBUG_BASALPROFILE = false; - @Expose - private byte[] mRawData; // store as byte array to make transport (via parcel) easier - private List listEntries; - - - public BasalProfile(AAPSLogger aapsLogger) { - this.aapsLogger = aapsLogger; - init(); - } - - - public BasalProfile(AAPSLogger aapsLogger, byte[] data) { - this.aapsLogger = aapsLogger; - setRawData(data); - } - - - // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class. - private static int readUnsignedByte(byte b) { - return (b < 0) ? b + 256 : b; - } - - - public void init() { - mRawData = new byte[MAX_RAW_DATA_SIZE]; - mRawData[0] = 0; - mRawData[1] = 0; - mRawData[2] = 0x3f; - } - - - private boolean setRawData(byte[] data) { - if (data == null) { - aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!"); - return false; - } - - // if we have just one entry through all day it looks like just length 1 - if (data.length == 1) { - data = MedtronicUtil.createByteArray(data[0], (byte) 0, (byte) 0); - } - - if (data.length == MAX_RAW_DATA_SIZE) { - mRawData = data; - } else { - int len = Math.min(MAX_RAW_DATA_SIZE, data.length); - mRawData = new byte[MAX_RAW_DATA_SIZE]; - System.arraycopy(data, 0, mRawData, 0, len); - } - - return true; - } - - - public boolean setRawDataFromHistory(byte[] data) { - if (data == null) { - aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!"); - return false; - } - - mRawData = new byte[MAX_RAW_DATA_SIZE]; - int item = 0; - - for (int i = 0; i < data.length - 2; i += 3) { - - if ((data[i] == 0) && (data[i + 1] == 0) && (data[i + 2] == 0)) { - mRawData[i] = 0; - mRawData[i + 1] = 0; - mRawData[i + 2] = 0; - } - - mRawData[i] = data[i + 1]; - mRawData[i + 1] = data[i + 2]; - mRawData[i + 2] = data[i]; - } - - return true; - } - - - public void dumpBasalProfile() { - aapsLogger.debug(LTag.PUMPCOMM, "Basal Profile entries:"); - List entries = getEntries(); - for (int i = 0; i < entries.size(); i++) { - BasalProfileEntry entry = entries.get(i); - String startString = entry.startTime.toString("HH:mm"); - // this doesn't work - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Entry %d, rate=%.3f (%s), start=%s (0x%02X)", i + 1, entry.rate, - ByteUtil.getHex(entry.rate_raw), startString, entry.startTime_raw)); - - } - } - - - public String getBasalProfileAsString() { - StringBuffer sb = new StringBuffer("Basal Profile entries:\n"); - List entries = getEntries(); - for (int i = 0; i < entries.size(); i++) { - BasalProfileEntry entry = entries.get(i); - String startString = entry.startTime.toString("HH:mm"); - - sb.append(String.format(Locale.ENGLISH, "Entry %d, rate=%.3f, start=%s\n", i + 1, entry.rate, startString)); - } - - return sb.toString(); - } - - public String basalProfileToStringError() { - return "Basal Profile [rawData=" + ByteUtil.shortHexString(this.getRawData()) + "]"; - } - - - public String basalProfileToString() { - StringBuffer sb = new StringBuffer("Basal Profile ["); - List entries = getEntries(); - for (int i = 0; i < entries.size(); i++) { - BasalProfileEntry entry = entries.get(i); - String startString = entry.startTime.toString("HH:mm"); - - sb.append(String.format(Locale.ENGLISH, "%s=%.3f, ", startString, entry.rate)); - } - - sb.append("]"); - - return sb.toString(); - } - - - // TODO: this function must be expanded to include changes in which profile is in use. - // and changes to the profiles themselves. - public BasalProfileEntry getEntryForTime(Instant when) { - BasalProfileEntry rval = new BasalProfileEntry(); - List entries = getEntries(); - if (entries.size() == 0) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getEntryForTime(%s): table is empty", - when.toDateTime().toLocalTime().toString("HH:mm"))); - return rval; - } - // Log.w(TAG,"Assuming first entry"); - rval = entries.get(0); - if (entries.size() == 1) { - aapsLogger.debug(LTag.PUMPCOMM, "getEntryForTime: Only one entry in profile"); - return rval; - } - - int localMillis = when.toDateTime().toLocalTime().getMillisOfDay(); - boolean done = false; - int i = 1; - while (!done) { - BasalProfileEntry entry = entries.get(i); - if (DEBUG_BASALPROFILE) { - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Comparing 'now'=%s to entry 'start time'=%s", when.toDateTime().toLocalTime() - .toString("HH:mm"), entry.startTime.toString("HH:mm"))); - } - if (localMillis >= entry.startTime.getMillisOfDay()) { - rval = entry; - if (DEBUG_BASALPROFILE) - aapsLogger.debug(LTag.PUMPCOMM, "Accepted Entry"); - } else { - // entry at i has later start time, keep older entry - if (DEBUG_BASALPROFILE) - aapsLogger.debug(LTag.PUMPCOMM, "Rejected Entry"); - done = true; - } - i++; - if (i >= entries.size()) { - done = true; - } - } - if (DEBUG_BASALPROFILE) { - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getEntryForTime(%s): Returning entry: rate=%.3f (%s), start=%s (%d)", when - .toDateTime().toLocalTime().toString("HH:mm"), rval.rate, ByteUtil.getHex(rval.rate_raw), - rval.startTime.toString("HH:mm"), rval.startTime_raw)); - } - return rval; - } - - - public List getEntries() { - List entries = new ArrayList<>(); - - if (mRawData == null || mRawData[2] == 0x3f) { - aapsLogger.warn(LTag.PUMPCOMM, "Raw Data is empty."); - return entries; // an empty list - } - int r, st; - - for (int i = 0; i < mRawData.length - 2; i += 3) { - - if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0)) - break; - - if ((mRawData[i] == 0) && (mRawData[i + 1] == 0) && (mRawData[i + 2] == 0x3f)) - break; - - r = MedtronicUtil.makeUnsignedShort(mRawData[i + 1], mRawData[i]); // readUnsignedByte(mRawData[i]); - st = readUnsignedByte(mRawData[i + 2]); - - try { - entries.add(new BasalProfileEntry(aapsLogger, r, st)); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMPCOMM, "Error decoding basal profile from bytes: " + ByteUtil.shortHexString(mRawData)); - throw ex; - } - - } - - return entries; - } - - - /** - * This is used to prepare new profile - * - * @param entry - */ - public void addEntry(BasalProfileEntry entry) { - if (listEntries == null) - listEntries = new ArrayList<>(); - - listEntries.add(entry); - } - - - public void generateRawDataFromEntries() { - - List outData = new ArrayList<>(); - - for (BasalProfileEntry profileEntry : listEntries) { - - byte[] strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true); - - outData.add(profileEntry.rate_raw[0]); - outData.add(profileEntry.rate_raw[1]); - outData.add(profileEntry.startTime_raw); - } - - this.setRawData(MedtronicUtil.createByteArray(outData)); - - // return this.mRawData; - } - - - public Double[] getProfilesByHour(PumpType pumpType) { - - List entries = null; - - try { - entries = getEntries(); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMPCOMM, "============================================================================="); - aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: " + ex, ex); - aapsLogger.error(LTag.PUMPCOMM, " rawBasalValues: " + ByteUtil.shortHexString(this.getRawData())); - aapsLogger.error(LTag.PUMPCOMM, "============================================================================="); - - //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); - } - - if (entries == null || entries.size() == 0) { - Double[] basalByHour = new Double[24]; - - for (int i = 0; i < 24; i++) { - basalByHour[i] = 0.0d; - } - - return basalByHour; - } - - Double[] basalByHour = new Double[24]; - - for (int i = 0; i < entries.size(); i++) { - BasalProfileEntry current = entries.get(i); - - int currentTime = (current.startTime_raw % 2 == 0) ? current.startTime_raw : current.startTime_raw - 1; - - currentTime = (currentTime * 30) / 60; - - int lastHour; - if ((i + 1) == entries.size()) { - lastHour = 24; - } else { - BasalProfileEntry basalProfileEntry = entries.get(i + 1); - - int rawTime = (basalProfileEntry.startTime_raw % 2 == 0) ? basalProfileEntry.startTime_raw - : basalProfileEntry.startTime_raw - 1; - - lastHour = (rawTime * 30) / 60; - } - - // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour); - - for (int j = currentTime; j < lastHour; j++) { - if (pumpType == null) - basalByHour[j] = current.rate; - else - basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate); - } - } - - return basalByHour; - } - - - public static String getProfilesByHourToString(Double[] data) { - - StringBuilder stringBuilder = new StringBuilder(); - - for (Double value : data) { - stringBuilder.append(String.format("%.3f", value)); - stringBuilder.append(" "); - } - - return stringBuilder.toString(); - - } - - - public byte[] getRawData() { - return this.mRawData; - } - - - @NonNull public String toString() { - return basalProfileToString(); - } - - - public boolean verify(PumpType pumpType) { - - try { - getEntries(); - } catch (Exception ex) { - return false; - } - - Double[] profilesByHour = getProfilesByHour(pumpType); - - for (Double aDouble : profilesByHour) { - if (aDouble > 35.0d) - return false; - } - - return true; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt new file mode 100644 index 0000000000..3777c30559 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -0,0 +1,315 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data.dto + +import com.google.gson.annotations.Expose +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import org.joda.time.Instant +import java.util.* + +/** + * Created by geoff on 6/1/15. + * + * + * There are three basal profiles stored on the pump. (722 only?) They are all parsed the same, the user just has 3 to + * choose from: Standard, A, and B + * + * + * The byte array is 48 times three byte entries long, plus a zero? If the profile is completely empty, it should have + * one entry: [0,0,0x3F]. The first entry of [0,0,0] marks the end of the used entries. + * + * + * Each entry is assumed to span from the specified start time to the start time of the next entry, or to midnight if + * there are no more entries. + * + * + * Individual entries are of the form [r,z,m] where r is the rate (in 0.025 U increments) z is zero (?) m is the start + * time-of-day for the basal rate period (in 30 minute increments) + */ +class BasalProfile { + + private val aapsLogger: AAPSLogger + + @Expose var rawData : ByteArray? = null // store as byte array to make transport (via parcel) easier + private set + + private var listEntries: MutableList? = null + + constructor(aapsLogger: AAPSLogger) { + this.aapsLogger = aapsLogger + init() + } + + constructor(aapsLogger: AAPSLogger, data: ByteArray) { + this.aapsLogger = aapsLogger + setRawData(data) + } + + fun init() { + rawData = ByteArray(MAX_RAW_DATA_SIZE) + rawData!![0] = 0 + rawData!![1] = 0 + rawData!![2] = 0x3f + } + + private fun setRawData(data: ByteArray): Boolean { + var data: ByteArray? = data + if (data == null) { + aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") + return false + } + + // if we have just one entry through all day it looks like just length 1 + if (data.size == 1) { + data = MedtronicUtil.createByteArray(data[0], 0.toByte(), 0.toByte()) + } + if (data!!.size == MAX_RAW_DATA_SIZE) { + rawData = data + } else { + val len = Math.min(MAX_RAW_DATA_SIZE, data.size) + rawData = ByteArray(MAX_RAW_DATA_SIZE) + System.arraycopy(data, 0, rawData, 0, len) + } + return true + } + + fun setRawDataFromHistory(data: ByteArray?): Boolean { + if (data == null) { + aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") + return false + } + rawData = ByteArray(MAX_RAW_DATA_SIZE) + val item = 0 + var i = 0 + while (i < data.size - 2) { + if (data[i] == 0.toByte() && data[i + 1] == 0.toByte() && data[i + 2] == 0.toByte()) { + rawData!![i] = 0 + rawData!![i + 1] = 0 + rawData!![i + 2] = 0 + } + rawData!![i] = data[i + 1] + rawData!![i + 1] = data[i + 2] + rawData!![i + 2] = data[i] + i += 3 + } + return true + } + + fun dumpBasalProfile() { + aapsLogger.debug(LTag.PUMPCOMM, "Basal Profile entries:") + val entries = entries + for (i in entries.indices) { + val entry = entries[i] + val startString = entry.startTime!!.toString("HH:mm") + // this doesn't work + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Entry %d, rate=%.3f (%s), start=%s (0x%02X)", i + 1, entry.rate, + ByteUtil.getHex(entry.rate_raw), startString, entry.startTime_raw)) + } + } + + val basalProfileAsString: String + get() { + val sb = StringBuffer("Basal Profile entries:\n") + val entries = entries + for (i in entries.indices) { + val entry = entries[i] + val startString = entry.startTime!!.toString("HH:mm") + sb.append(String.format(Locale.ENGLISH, "Entry %d, rate=%.3f, start=%s\n", i + 1, entry.rate, startString)) + } + return sb.toString() + } + + fun basalProfileToStringError(): String { + return "Basal Profile [rawData=" + ByteUtil.shortHexString(rawData) + "]" + } + + fun basalProfileToString(): String { + val sb = StringBuffer("Basal Profile [") + val entries = entries + for (i in entries.indices) { + val entry = entries[i] + val startString = entry.startTime!!.toString("HH:mm") + sb.append(String.format(Locale.ENGLISH, "%s=%.3f, ", startString, entry.rate)) + } + sb.append("]") + return sb.toString() + } + + // TODO: this function must be expanded to include changes in which profile is in use. + // and changes to the profiles themselves. + fun getEntryForTime(`when`: Instant): BasalProfileEntry { + var rval = BasalProfileEntry() + val entries = entries + if (entries.size == 0) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getEntryForTime(%s): table is empty", + `when`.toDateTime().toLocalTime().toString("HH:mm"))) + return rval + } + // Log.w(TAG,"Assuming first entry"); + rval = entries[0] + if (entries.size == 1) { + aapsLogger.debug(LTag.PUMPCOMM, "getEntryForTime: Only one entry in profile") + return rval + } + val localMillis = `when`.toDateTime().toLocalTime().millisOfDay + var done = false + var i = 1 + while (!done) { + val entry = entries[i] + if (DEBUG_BASALPROFILE) { + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Comparing 'now'=%s to entry 'start time'=%s", `when`.toDateTime().toLocalTime() + .toString("HH:mm"), entry.startTime!!.toString("HH:mm"))) + } + if (localMillis >= entry.startTime!!.millisOfDay) { + rval = entry + if (DEBUG_BASALPROFILE) aapsLogger.debug(LTag.PUMPCOMM, "Accepted Entry") + } else { + // entry at i has later start time, keep older entry + if (DEBUG_BASALPROFILE) aapsLogger.debug(LTag.PUMPCOMM, "Rejected Entry") + done = true + } + i++ + if (i >= entries.size) { + done = true + } + } + if (DEBUG_BASALPROFILE) { + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getEntryForTime(%s): Returning entry: rate=%.3f (%s), start=%s (%d)", `when` + .toDateTime().toLocalTime().toString("HH:mm"), rval.rate, ByteUtil.getHex(rval.rate_raw), + rval.startTime!!.toString("HH:mm"), rval.startTime_raw)) + } + return rval + }// readUnsignedByte(mRawData[i]); + + // an empty list + val entries: List + get() { + val entries: MutableList = ArrayList() + if (rawData == null || rawData!![2] == 0x3f.toByte()) { + aapsLogger.warn(LTag.PUMPCOMM, "Raw Data is empty.") + return entries // an empty list + } + var r: Int + var st: Int + var i = 0 + while (i < rawData!!.size - 2) { + if (rawData!![i] == 0.toByte() && rawData!![i + 1] == 0.toByte() && rawData!![i + 2] == 0.toByte()) break + if (rawData!![i] == 0.toByte() && rawData!![i + 1] == 0.toByte() && rawData!![i + 2] == 0x3f.toByte()) break + r = MedtronicUtil.makeUnsignedShort(rawData!![i + 1].toInt(), rawData!![i].toInt()) // readUnsignedByte(mRawData[i]); + st = readUnsignedByte(rawData!![i + 2]) + try { + entries.add(BasalProfileEntry(aapsLogger, r, st)) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMPCOMM, "Error decoding basal profile from bytes: " + ByteUtil.shortHexString(rawData)) + throw ex + } + i += 3 + } + return entries + } + + /** + * This is used to prepare new profile + * + * @param entry + */ + fun addEntry(entry: BasalProfileEntry) { + if (listEntries == null) listEntries = ArrayList() + listEntries!!.add(entry) + } + + fun generateRawDataFromEntries() { + val outData: MutableList = ArrayList() + for (profileEntry in listEntries!!) { + val strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true) + outData.add(profileEntry.rate_raw[0]) + outData.add(profileEntry.rate_raw[1]) + outData.add(profileEntry.startTime_raw) + } + setRawData(MedtronicUtil.createByteArray(outData)) + + // return this.mRawData; + } + + fun getProfilesByHour(pumpType: PumpType?): Array { + var entries: List? = null + try { + entries = entries + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMPCOMM, "=============================================================================") + aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: $ex", ex) + aapsLogger.error(LTag.PUMPCOMM, " rawBasalValues: " + ByteUtil.shortHexString(rawData)) + aapsLogger.error(LTag.PUMPCOMM, "=============================================================================") + + //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); + } + if (entries == null || entries.size == 0) { + val basalByHour = arrayOfNulls(24) + for (i in 0..23) { + basalByHour[i] = 0.0 + } + return basalByHour + } + val basalByHour = arrayOfNulls(24) + for (i in entries.indices) { + val current = entries[i] + var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1 + currentTime = currentTime * 30 / 60 + var lastHour: Int + lastHour = if (i + 1 == entries.size) { + 24 + } else { + val basalProfileEntry = entries[i + 1] + val rawTime = if (basalProfileEntry.startTime_raw % 2 == 0) basalProfileEntry.startTime_raw.toInt() else basalProfileEntry.startTime_raw - 1 + rawTime * 30 / 60 + } + + // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour); + for (j in currentTime until lastHour) { + if (pumpType == null) basalByHour[j] = current.rate else basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate) + } + } + return basalByHour + } + + override fun toString(): String { + return basalProfileToString() + } + + fun verify(pumpType: PumpType?): Boolean { + try { + entries + } catch (ex: Exception) { + return false + } + val profilesByHour = getProfilesByHour(pumpType) + for (aDouble in profilesByHour) { + if (aDouble!! > 35.0) return false + } + return true + } + + + + companion object { + const val MAX_RAW_DATA_SIZE = 48 * 3 + 1 + private const val DEBUG_BASALPROFILE = false + + // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class. + private fun readUnsignedByte(b: Byte): Int { + return if (b < 0) b + 256 else b.toInt() + } + + @JvmStatic + fun getProfilesByHourToString(data: Array): String { + val stringBuilder = StringBuilder() + for (value in data) { + stringBuilder.append(String.format("%.3f", value)) + stringBuilder.append(" ") + } + return stringBuilder.toString() + } + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java deleted file mode 100644 index da2a7181c0..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.java +++ /dev/null @@ -1,81 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.data.dto; - -import org.joda.time.LocalTime; - -import java.util.Locale; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - -/** - * Created by geoff on 6/1/15. - * This is a helper class for BasalProfile, only used for interpreting the contents of BasalProfile - * - fixed rate is not one bit but two - */ -public class BasalProfileEntry { - - byte[] rate_raw; - public double rate; - byte startTime_raw; - public LocalTime startTime; // Just a "time of day" - - public BasalProfileEntry() { - rate = -9.999E6; - rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(0xFF, true); - startTime = new LocalTime(0); - startTime_raw = (byte) 0xFF; - } - - public BasalProfileEntry(double rate, int hour, int minutes) { - byte[] data = MedtronicUtil.getBasalStrokes(rate, true); - - rate_raw = new byte[2]; - rate_raw[0] = data[1]; - rate_raw[1] = data[0]; - - int interval = hour * 2; - - if (minutes == 30) { - interval++; - } - - startTime_raw = (byte) interval; - startTime = new LocalTime(hour, minutes == 30 ? 30 : 0); - } - - BasalProfileEntry(AAPSLogger aapsLogger, int rateStrokes, int startTimeInterval) { - // rateByte is insulin delivery rate, U/hr, in 0.025 U increments - // startTimeByte is time-of-day, in 30 minute increments - rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateStrokes, true); - rate = rateStrokes * 0.025; - startTime_raw = (byte) startTimeInterval; - - try { - startTime = new LocalTime(startTimeInterval / 2, (startTimeInterval % 2) * 30); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMPCOMM, - String.format(Locale.ENGLISH, "Error creating BasalProfileEntry: startTimeInterval=%d, startTime_raw=%d, hours=%d, rateStrokes=%d", - startTimeInterval, startTime_raw, startTimeInterval / 2, rateStrokes)); - throw ex; - } - - } - - BasalProfileEntry(byte rateByte, int startTimeByte) { - // rateByte is insulin delivery rate, U/hr, in 0.025 U increments - // startTimeByte is time-of-day, in 30 minute increments - rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateByte, true); - rate = rateByte * 0.025; - startTime_raw = (byte) startTimeByte; - startTime = new LocalTime(startTimeByte / 2, (startTimeByte % 2) * 30); - } - - public void setStartTime(LocalTime localTime) { - this.startTime = localTime; - } - - public void setRate(double rate) { - this.rate = rate; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.kt new file mode 100644 index 0000000000..6ffbefcf2d --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfileEntry.kt @@ -0,0 +1,74 @@ +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.medtronic.util.MedtronicUtil +import org.joda.time.LocalTime +import java.util.* + +/** + * Created by geoff on 6/1/15. + * This is a helper class for BasalProfile, only used for interpreting the contents of BasalProfile + * - fixed rate is not one bit but two + */ +class BasalProfileEntry { + + var rate_raw: ByteArray + var rate = 0.0 + set(value) { + field = value + } + + var startTime_raw: Byte + var startTime : LocalTime? = null // Just a "time of day" + set(value) { + field = value + } + + + constructor() { + rate = -9.999E6 + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(0xFF, true) + startTime = LocalTime(0) + startTime_raw = 0xFF.toByte() + } + + constructor(rate: Double, hour: Int, minutes: Int) { + val data = MedtronicUtil.getBasalStrokes(rate, true) + rate_raw = ByteArray(2) + rate_raw[0] = data[1] + rate_raw[1] = data[0] + var interval = hour * 2 + if (minutes == 30) { + interval++ + } + startTime_raw = interval.toByte() + startTime = LocalTime(hour, if (minutes == 30) 30 else 0) + } + + internal constructor(aapsLogger: AAPSLogger, rateStrokes: Int, startTimeInterval: Int) { + // rateByte is insulin delivery rate, U/hr, in 0.025 U increments + // startTimeByte is time-of-day, in 30 minute increments + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateStrokes, true) + rate = rateStrokes * 0.025 + startTime_raw = startTimeInterval.toByte() + startTime = try { + LocalTime(startTimeInterval / 2, startTimeInterval % 2 * 30) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error creating BasalProfileEntry: startTimeInterval=%d, startTime_raw=%d, hours=%d, rateStrokes=%d", + startTimeInterval, startTime_raw, startTimeInterval / 2, rateStrokes)) + throw ex + } + } + + internal constructor(rateByte: Byte, startTimeByte: Int) { + // rateByte is insulin delivery rate, U/hr, in 0.025 U increments + // startTimeByte is time-of-day, in 30 minute increments + rate_raw = MedtronicUtil.getByteArrayFromUnsignedShort(rateByte.toInt(), true) + rate = rateByte * 0.025 + startTime_raw = startTimeByte.toByte() + startTime = LocalTime(startTimeByte / 2, startTimeByte % 2 * 30) + } + + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java index 0c14ac42f8..dfa4e83867 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java @@ -215,32 +215,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType } - // MedtronicCommandType(int code, String description, MedtronicDeviceType devices, -// MinimedCommandParameterType parameterType) { -// this(code, description, devices, parameterType, 64, 1, 0, 0, 0, 0); -// } -// -// -// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, -// MinimedCommandParameterType parameterType, int expectedLength) { -// this(code, description, devices, parameterType, 64, 1, 0, 0, 0, expectedLength); -// } -// -// -// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, -// MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) { -// this(code, description, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, 0); -// } -// -// -// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, -// MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType, -// int expectedLength) { -// this(code, description, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, -// expectedLength); -// } -// -// MedtronicCommandType(int code, String description, MedtronicDeviceType devices, MinimedCommandParameterType parameterType, byte[] cmd_params) { this(code, description, devices, parameterType, 0, 1, 0, 0, 11, 0); @@ -256,14 +230,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType this(code, description, devices, parameterType, 64, 1, 0, null); } - - // NEW - MedtronicCommandType(int code, String description, MedtronicDeviceType devices, - MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) { - this(code, description, devices, parameterType, recordLength, maxRecords, 0, null); - } - - // NEW MedtronicCommandType(int code, String description, MedtronicDeviceType devices, // MinimedCommandParameterType parameterType, int expectedLength) { @@ -390,22 +356,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType } - public boolean canReturnData() { - System.out.println("CanReturnData: ]id=" + this.name() + "max=" + this.maxRecords + "recLen=" + recordLength); - return (this.maxRecords * this.recordLength) > 0; - } - - - public int getRecordLength() { - return recordLength; - } - - - public int getMaxRecords() { - return maxRecords; - } - - public byte getCommandCode() { return commandCode; } @@ -420,16 +370,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType } - public byte[] getCommandParameters() { - return commandParameters; - } - - - public boolean hasCommandParameters() { - return (getCommandParametersCount() > 0); - } - - public String toString() { return name(); } From a202178426feadc5fa038bcd6a544453008338de Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sun, 18 Apr 2021 15:30:05 +0100 Subject: [PATCH 05/39] - kotlin changes to most of the classes, most of it is tested --- .../general/actions/defs/CustomActionType.kt | 2 +- .../pump/common/PumpPluginAbstract.java | 29 +- .../pump/common/PumpPluginAbstract.java.orig | 535 ------------------ .../plugins/pump/common/data/PumpStatus.java | 71 --- .../plugins/pump/common/data/PumpStatus.kt | 52 ++ .../pump/medtronic/MedtronicFragment.kt | 33 +- .../pump/medtronic/MedtronicPumpPlugin.java | 103 ++-- .../comm/MedtronicCommunicationManager.java | 22 +- .../pump/medtronic/comm/MedtronicConverter.kt | 24 +- .../comm/history/MedtronicHistoryDecoder.kt | 12 +- .../comm/history/MedtronicHistoryEntry.kt | 4 +- .../medtronic/comm/history/RawHistoryPage.kt | 2 +- .../pump/MedtronicPumpHistoryDecoder.kt | 40 +- .../comm/history/pump/PumpHistoryEntry.kt | 10 +- .../comm/history/pump/PumpHistoryEntryType.kt | 12 +- .../comm/history/pump/PumpHistoryResult.kt | 51 +- .../medtronic/comm/message/PumpMessage.kt | 6 +- .../medtronic/comm/ui/MedtronicUIComm.java | 58 -- .../pump/medtronic/comm/ui/MedtronicUIComm.kt | 44 ++ .../comm/ui/MedtronicUIPostprocessor.java | 252 --------- .../comm/ui/MedtronicUIPostprocessor.kt | 188 ++++++ .../medtronic/comm/ui/MedtronicUITask.java | 234 -------- .../pump/medtronic/comm/ui/MedtronicUITask.kt | 178 ++++++ .../medtronic/data/MedtronicHistoryData.java | 11 +- .../pump/medtronic/data/dto/BasalProfile.kt | 39 +- .../medtronic/data/dto/BatteryStatusDTO.java | 60 -- .../medtronic/data/dto/BatteryStatusDTO.kt | 46 ++ .../pump/medtronic/data/dto/BolusDTO.java | 160 ------ .../pump/medtronic/data/dto/BolusDTO.kt | 90 +++ .../medtronic/data/dto/BolusWizardDTO.java | 50 -- .../pump/medtronic/data/dto/BolusWizardDTO.kt | 44 ++ .../pump/medtronic/data/dto/ClockDTO.java | 16 - .../pump/medtronic/data/dto/ClockDTO.kt | 12 + .../medtronic/data/dto/DailyTotalsDTO.java | 255 --------- .../pump/medtronic/data/dto/DailyTotalsDTO.kt | 202 +++++++ .../medtronic/data/dto/PumpSettingDTO.java | 29 - .../pump/medtronic/data/dto/PumpSettingDTO.kt | 14 + .../data/dto/PumpTimeStampedRecord.java | 28 - .../data/dto/PumpTimeStampedRecord.kt | 16 + .../data/dto/RLHistoryItemMedtronic.java | 28 - .../data/dto/RLHistoryItemMedtronic.kt | 18 + .../medtronic/data/dto/TempBasalPair.java | 145 ----- .../pump/medtronic/data/dto/TempBasalPair.kt | 110 ++++ .../data/dto/TempBasalProcessDTO.java | 31 - .../medtronic/data/dto/TempBasalProcessDTO.kt | 21 + .../medtronic/defs/BasalProfileStatus.java | 14 - .../pump/medtronic/defs/BasalProfileStatus.kt | 12 + .../pump/medtronic/defs/BatteryType.java | 34 -- .../pump/medtronic/defs/BatteryType.kt | 18 + .../defs/CommandValueDefinitionMDTType.java | 33 -- .../medtronic/defs/MedtronicCommandType.java | 393 ------------- .../medtronic/defs/MedtronicCommandType.kt | 285 ++++++++++ .../defs/MedtronicCustomActionType.java | 20 - .../defs/MedtronicCustomActionType.kt | 19 + .../medtronic/defs/MedtronicDeviceType.java | 140 ----- .../medtronic/defs/MedtronicDeviceType.kt | 100 ++++ .../defs/MedtronicNotificationType.java | 65 --- .../defs/MedtronicNotificationType.kt | 23 + .../defs/MedtronicStatusRefreshType.java | 37 -- .../defs/MedtronicStatusRefreshType.kt | 23 + .../defs/MedtronicUIResponseType.java | 13 - .../medtronic/defs/MedtronicUIResponseType.kt | 9 + .../pump/medtronic/defs/PumpBolusType.java | 129 ----- .../pump/medtronic/defs/PumpBolusType.kt | 54 ++ .../defs/PumpConfigurationGroup.java | 58 -- .../medtronic/defs/PumpConfigurationGroup.kt | 20 + .../medtronic/driver/MedtronicPumpStatus.java | 180 ------ .../medtronic/driver/MedtronicPumpStatus.kt | 139 +++++ .../service/RileyLinkMedtronicService.java | 388 ------------- .../service/RileyLinkMedtronicService.kt | 289 ++++++++++ .../pump/medtronic/util/MedtronicConst.java | 40 -- .../pump/medtronic/util/MedtronicConst.kt | 37 ++ .../pump/medtronic/util/MedtronicUtil.java | 456 --------------- .../pump/medtronic/util/MedtronicUtil.kt | 314 ++++++++++ medtronic/src/main/res/values/strings.xml | 6 +- .../plugins/pump/common/utils/ByteUtil.java | 19 +- 76 files changed, 2581 insertions(+), 4173 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java delete mode 100755 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java create mode 100755 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomActionType.kt b/core/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomActionType.kt index fb472d5592..5ffbb25b6b 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomActionType.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/general/actions/defs/CustomActionType.kt @@ -1,5 +1,5 @@ package info.nightscout.androidaps.plugins.general.actions.defs interface CustomActionType { - val key: String? + fun getKey(): String } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java index a36e76cf57..ca9100a086 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java @@ -244,7 +244,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump, public long lastDataTime() { 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 - @NonNull public PumpDescription getPumpDescription() { + + public PumpDescription getPumpDescription() { return pumpDescription; } @@ -331,7 +332,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump, @NonNull @Override 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(); } @@ -341,8 +342,8 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump, JSONObject status = new JSONObject(); JSONObject extended = new JSONObject(); try { - battery.put("percent", getPumpStatusData().batteryRemaining); - status.put("status", getPumpStatusData().pumpStatusType != null ? getPumpStatusData().pumpStatusType.getStatus() : "normal"); + battery.put("percent", getPumpStatusData().getBatteryRemaining()); + status.put("status", getPumpStatusData().getPumpStatusType() != null ? getPumpStatusData().getPumpStatusType().getStatus() : "normal"); extended.put("Version", version); try { extended.put("ActiveProfile", profileName); @@ -368,7 +369,7 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump, pump.put("battery", battery); pump.put("status", status); pump.put("extended", extended); - pump.put("reservoir", getPumpStatusData().reservoirRemainingUnits); + pump.put("reservoir", getPumpStatusData().getReservoirRemainingUnits()); pump.put("clock", dateUtil.toISOString(dateUtil.now())); } catch (JSONException e) { aapsLogger.error("Unhandled exception", e); @@ -381,14 +382,14 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump, @NonNull @Override public String shortStatus(boolean veryShort) { String ret = ""; - if (getPumpStatusData().lastConnection != 0) { - long agoMsec = System.currentTimeMillis() - getPumpStatusData().lastConnection; + if (getPumpStatusData().getLastConnection() != 0) { + long agoMsec = System.currentTimeMillis() - getPumpStatusData().getLastConnection(); 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"; + if (getPumpStatusData().getLastBolusTime() != null && getPumpStatusData().getLastBolusTime().getTime() != 0) { + ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().getLastBolusAmount()) + "U @" + // + android.text.format.DateFormat.format("HH:mm", getPumpStatusData().getLastBolusTime()) + "\n"; } PumpSync.PumpState.TemporaryBasal activeTemp = pumpSync.expectedPumpState().getTemporaryBasal(); if (activeTemp != null) { @@ -402,9 +403,9 @@ public abstract class PumpPluginAbstract extends PumpPluginBase implements Pump, // 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"; + ret += "IOB: " + getPumpStatusData().getIob() + "U\n"; + ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(getPumpStatusData().getReservoirRemainingUnits()) + "U\n"; + ret += "Batt: " + getPumpStatusData().getBatteryRemaining() + "\n"; return ret; } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig deleted file mode 100644 index a0bffe268a..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java.orig +++ /dev/null @@ -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 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); - } - - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.java deleted file mode 100644 index 505cd1388f..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.java +++ /dev/null @@ -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(); - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt new file mode 100644 index 0000000000..061465c354 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt @@ -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? = 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? + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index 43a75631bf..49b2415264 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -220,12 +220,12 @@ class MedtronicFragment : DaggerFragment() { PumpDeviceState.InvalidConfiguration -> binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) PumpDeviceState.Active -> { - val cmd = medtronicUtil.currentCommand + val cmd = medtronicUtil.getCurrentCommand() if (cmd == null) binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) else { aapsLogger.debug(LTag.PUMP, "Command: $cmd") - val cmdResourceId = cmd.resourceId + val cmdResourceId = cmd.resourceId!! if (cmd == MedtronicCommandType.GetHistoryData) { binding.pumpStatusIcon.text = medtronicUtil.frameNumber?.let { 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) } else { binding.pumpStatusIcon.text = " " + (cmdResourceId?.let { resourceHelper.gs(it) } - ?: cmd.getCommandDescription()) + ?: cmd.commandDescription) } } } @@ -298,34 +298,31 @@ class MedtronicFragment : DaggerFragment() { val bolus = medtronicPumpStatus.lastBolusAmount val bolusTime = medtronicPumpStatus.lastBolusTime 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 unit = resourceHelper.gs(R.string.insulin_unit_shortname) val ago = when { agoMsc < 60 * 1000 -> resourceHelper.gs(R.string.medtronic_pump_connected_now) - bolusMinAgo < 60 -> dateUtil.minAgo(resourceHelper, medtronicPumpStatus.lastBolusTime.time) - else -> dateUtil.hourAgo(medtronicPumpStatus.lastBolusTime.time, resourceHelper) + bolusMinAgo < 60 -> dateUtil.minAgo(resourceHelper, medtronicPumpStatus.lastBolusTime!!.time) + else -> dateUtil.hourAgo(medtronicPumpStatus.lastBolusTime!!.time, resourceHelper) } binding.lastBolus.text = resourceHelper.gs(R.string.mdt_last_bolus, bolus, unit, ago) } else { binding.lastBolus.text = "" } - if (true) { - // base basal rate - binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " - + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) + // base basal rate + binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " + + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) - binding.tempBasal.text = "??" - } else { - val pumpState = pumpSync.expectedPumpState() - // base basal rate - binding.baseBasalRate.text = ("(" + medtronicPumpStatus.activeProfileName + ") " - + resourceHelper.gs(R.string.pump_basebasalrate, medtronicPumpPlugin.baseBasalRate)) + // TBR + var tbrStr = "" + var tbrRemainingTime: Int? = medtronicPumpStatus.tbrRemainingTime - 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 if (medtronicPumpStatus.batteryType == BatteryType.None || medtronicPumpStatus.batteryVoltage == null) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java index b514ec7d3a..c86e7c95a3 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java @@ -40,6 +40,7 @@ import info.nightscout.androidaps.interfaces.CommandQueueProvider; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.Pump; +import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; @@ -210,19 +211,24 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril return "MedtronicPumpPlugin::"; } +// public PumpDescription getPumpDescription() { +// return super.pumpDescription; +// } + + @Override public void initPumpStatusData() { - medtronicPumpStatus.lastConnection = sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); - medtronicPumpStatus.lastDataTime = medtronicPumpStatus.lastConnection; - medtronicPumpStatus.previousConnection = medtronicPumpStatus.lastConnection; + medtronicPumpStatus.setLastConnection(sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L)); + medtronicPumpStatus.setLastDataTime(medtronicPumpStatus.getLastConnection()); + medtronicPumpStatus.setPreviousConnection( medtronicPumpStatus.getLastConnection()); //if (rileyLinkMedtronicService != null) rileyLinkMedtronicService.verifyConfiguration(); aapsLogger.debug(LTag.PUMP, "initPumpStatusData: " + this.medtronicPumpStatus); // 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 if (!sp.contains(MedtronicConst.Statistics.FirstPumpStart)) { @@ -321,15 +327,16 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril return rileyLinkMedtronicService; } - @Override public RileyLinkPumpInfo getPumpInfo() { - 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); - String model = medtronicPumpStatus.medtronicDeviceType == null ? "???" : "Medtronic " + medtronicPumpStatus.medtronicDeviceType.getPumpModel(); - String serialNumber = medtronicPumpStatus.serialNumber; + @Override + public RileyLinkPumpInfo getPumpInfo() { + 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 model = medtronicPumpStatus.getMedtronicDeviceType() == null ? "???" : "Medtronic " + medtronicPumpStatus.getMedtronicDeviceType().getPumpModel(); + String serialNumber = medtronicPumpStatus.getSerialNumber(); return new RileyLinkPumpInfo(frequency, model, serialNumber); } @Override public long getLastConnectionTimeMillis() { - return medtronicPumpStatus.lastConnection; + return medtronicPumpStatus.getLastConnection(); } @Override public void setLastCommunicationToNow() { @@ -580,7 +587,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril if (medtronicUtil.getMedtronicPumpModel() == null) { rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.PumpModel); } 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."); medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, getResourceHelper(), rxBus); } @@ -643,27 +650,27 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril @Override public boolean isThisProfileSet(@NonNull Profile profile) { - aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.basalProfileStatus); + aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.getBasalProfileStatus()); if (!isInitialized) return true; - if (medtronicPumpStatus.basalProfileStatus == BasalProfileStatus.NotInitialized) { + if (medtronicPumpStatus.getBasalProfileStatus() == BasalProfileStatus.NotInitialized) { // this shouldn't happen, but if there was problem we try again getBasalProfiles(); return isProfileSame(profile); - } else if (medtronicPumpStatus.basalProfileStatus == BasalProfileStatus.ProfileChanged) { + } else if (medtronicPumpStatus.getBasalProfileStatus() == BasalProfileStatus.ProfileChanged) { return false; } - return (medtronicPumpStatus.basalProfileStatus != BasalProfileStatus.ProfileOK) || isProfileSame(profile); + return (medtronicPumpStatus.getBasalProfileStatus() != BasalProfileStatus.ProfileOK) || isProfileSame(profile); } private boolean isProfileSame(Profile profile) { boolean invalid = false; - Double[] basalsByHour = medtronicPumpStatus.basalsByHour; + Double[] basalsByHour = medtronicPumpStatus.getBasalsByHour(); aapsLogger.debug(LTag.PUMP, "Current Basals (h): " + (basalsByHour == null ? "null" : BasalProfile.getProfilesByHourToString(basalsByHour))); @@ -704,8 +711,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril @Override public long lastDataTime() { - if (medtronicPumpStatus.lastConnection != 0) { - return medtronicPumpStatus.lastConnection; + if (medtronicPumpStatus.getLastConnection() != 0) { + return medtronicPumpStatus.getLastConnection(); } return System.currentTimeMillis(); @@ -720,13 +727,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril @Override public double getReservoirLevel() { - return medtronicPumpStatus.reservoirRemainingUnits; + return medtronicPumpStatus.getReservoirRemainingUnits(); } @Override public int getBatteryLevel() { - return medtronicPumpStatus.batteryRemaining; + return medtronicPumpStatus.getBatteryRemaining(); } protected void triggerUIChange() { @@ -778,22 +785,22 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril if (clock == null) return; - int timeDiff = Math.abs(clock.timeDifference); + int timeDiff = Math.abs(clock.getTimeDifference()); 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)); 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); rxBus.send(new EventNewNotification(notification)); } } 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)); medtronicUtil.sendNotification(MedtronicNotificationType.TimeChangeOver24h, getResourceHelper(), rxBus); } @@ -814,12 +821,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril setRefreshButtonEnabled(false); - if (detailedBolusInfo.insulin > medtronicPumpStatus.reservoirRemainingUnits) { + if (detailedBolusInfo.insulin > medtronicPumpStatus.getReservoirRemainingUnits()) { return new PumpEnactResult(getInjector()) // .success(false) // .enacted(false) // .comment(getResourceHelper().gs(R.string.medtronic_cmd_bolus_could_not_be_delivered_no_insulin, - medtronicPumpStatus.reservoirRemainingUnits, + medtronicPumpStatus.getReservoirRemainingUnits(), detailedBolusInfo.insulin)); } @@ -857,9 +864,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); 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); @@ -894,7 +901,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril } // 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 : MedtronicConst.Statistics.StandardBoluses); @@ -1022,7 +1029,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR); - Boolean response = (Boolean) responseTask2.returnData; + Boolean response = (Boolean) responseTask2.getResult(); if (response) { 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 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); if (response) { // FIXME put this into UIPostProcessor - medtronicPumpStatus.tempBasalStart = new Date(); - medtronicPumpStatus.tempBasalAmount = absoluteRate; - medtronicPumpStatus.tempBasalLength = durationInMinutes; + medtronicPumpStatus.setTempBasalStart(new Date()); + medtronicPumpStatus.setTempBasalAmount(absoluteRate); + medtronicPumpStatus.setTempBasalLength(durationInMinutes); TemporaryBasal tempStart = new TemporaryBasal(getInjector()) // .date(System.currentTimeMillis()) // @@ -1122,7 +1129,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1); } - if (this.medtronicPumpStatus.basalProfileStatus != BasalProfileStatus.NotInitialized + if (this.medtronicPumpStatus.getBasalProfileStatus() != BasalProfileStatus.NotInitialized && medtronicHistoryData.hasBasalProfileChanged()) { medtronicHistoryData.processLastBasalProfileChange(pumpDescription.getPumpType(), medtronicPumpStatus); } @@ -1194,7 +1201,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril } } else { 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.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime); @@ -1204,12 +1211,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetHistoryData, - lastPumpHistoryEntry, targetDate); + Arrays.asList(lastPumpHistoryEntry, targetDate)); if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task"); - PumpHistoryResult historyResult = (PumpHistoryResult) responseTask2.returnData; + PumpHistoryResult historyResult = (PumpHistoryResult) responseTask2.getResult(); if (debugHistory) 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()); 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.filterNewEntries(); @@ -1281,7 +1288,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril switch (refreshType) { case RemainingInsulin: { - double remaining = medtronicPumpStatus.reservoirRemainingUnits; + double remaining = medtronicPumpStatus.getReservoirRemainingUnits(); int min; if (remaining > 50) min = 4 * 60; @@ -1348,7 +1355,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.ReadTemporaryBasal); 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 if (tbr.getDurationMinutes() == 0) { @@ -1397,7 +1404,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR); - Boolean response = (Boolean) responseTask2.returnData; + Boolean response = (Boolean) responseTask2.getResult(); finishAction("TBR"); @@ -1434,7 +1441,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril @NonNull @Override public String serialNumber() { - return medtronicPumpStatus.serialNumber; + return medtronicPumpStatus.getSerialNumber(); } @NonNull @Override @@ -1465,6 +1472,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril BasalProfile basalProfile = convertProfileToMedtronicProfile(profile); + aapsLogger.debug("Basal Profile: " + basalProfile); + String profileInvalid = isProfileValid(basalProfile); if (profileInvalid != null) { @@ -1475,9 +1484,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril } 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); @@ -1494,12 +1503,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, Ril StringBuilder stringBuilder = new StringBuilder(); - if (medtronicPumpStatus.maxBasal == null) + if (medtronicPumpStatus.getMaxBasal() == null) return null; for (BasalProfileEntry profileEntry : basalProfile.getEntries()) { - if (profileEntry.getRate() > medtronicPumpStatus.maxBasal) { + if (profileEntry.getRate() > medtronicPumpStatus.getMaxBasal()) { stringBuilder.append(profileEntry.getStartTime().toString("HH:mm")); stringBuilder.append("="); stringBuilder.append(profileEntry.getRate()); diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java index 4b8f885701..7773f28ba7 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java @@ -80,8 +80,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager @Inject public void onInit() { // we can't do this in the constructor, as sp only gets injected after the constructor has returned - medtronicPumpStatus.previousConnection = sp.getLong( - RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); + medtronicPumpStatus.setPreviousConnection(sp.getLong( + RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L)); } @Override @@ -136,7 +136,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager if (!canPreventTuneUp) { - long diff = System.currentTimeMillis() - medtronicPumpStatus.lastConnection; + long diff = System.currentTimeMillis() - medtronicPumpStatus.getLastConnection(); if (diff > RILEYLINK_TIMEOUT) { serviceTaskExecutor.startTask(new WakeAndTuneTask(injector)); @@ -278,7 +278,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager for (List frame : frames) { - byte[] frameData = MedtronicUtil.createByteArray(frame); + byte[] frameData = medtronicUtil.createByteArray(frame); // aapsLogger.debug(LTag.PUMPCOMM,"Frame {} data:\n{}", frameNr, ByteUtil.getCompactString(frameData)); @@ -570,7 +570,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager try { 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) { @@ -632,11 +632,11 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // PUMP SPECIFIC COMMANDS - public Float getRemainingInsulin() { + public Double 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.getMessageBody().getTxData())); - String check = checkResponseContent(response, commandType.commandDescription, 1); + String check = checkResponseContent(response, commandType.getCommandDescription(), 1); byte[] data = null; @@ -695,7 +695,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs, // HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData())); - String check2 = checkResponseContent(response, commandType.commandDescription, 1); + String check2 = checkResponseContent(response, commandType.getCommandDescription(), 1); if (check2 == null) { @@ -765,12 +765,12 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager public ClockDTO getPumpTime() { ClockDTO clockDTO = new ClockDTO(); - clockDTO.localDeviceTime = new LocalDateTime(); + clockDTO.setLocalDeviceTime(new LocalDateTime()); Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock); if (responseObject != null) { - clockDTO.pumpTime = (LocalDateTime) responseObject; + clockDTO.setPumpTime((LocalDateTime) responseObject); return clockDTO; } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt index 3796661ef5..a15fb131b7 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt @@ -58,7 +58,7 @@ class MedtronicConverter @Inject constructor( } MedtronicCommandType.ReadTemporaryBasal -> { - TempBasalPair(aapsLogger, rawContent) // 5 + TempBasalPair(aapsLogger, rawContent!!) // 5 } MedtronicCommandType.Settings_512 -> { @@ -112,7 +112,7 @@ class MedtronicConverter @Inject constructor( batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown } if (rawData.size > 1) { - var d: Double? = null + var d: Double? //= null // if response in 3 bytes then we add additional information d = if (rawData.size == 2) { @@ -126,7 +126,7 @@ class MedtronicConverter @Inject constructor( return batteryStatus } - private fun decodeRemainingInsulin(rawData: ByteArray?): Float { + private fun decodeRemainingInsulin(rawData: ByteArray?): Double { var startIdx = 0 val pumpModel = medtronicUtil.medtronicPumpModel val strokes = pumpModel?.bolusStrokes ?: 10 @@ -134,11 +134,11 @@ class MedtronicConverter @Inject constructor( startIdx = 2 } val reqLength = startIdx + 1 - var value = 0f + var value = 0.0 value = if (reqLength >= rawData!!.size) { - rawData[startIdx] / (1.0f * strokes) + rawData[startIdx] / (1.0 * strokes) } 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") return value @@ -208,7 +208,7 @@ class MedtronicConverter @Inject constructor( rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map) addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h", 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, map) // LOG.debug("Insulin concentration: " + rd[9]); @@ -249,7 +249,7 @@ class MedtronicConverter @Inject constructor( addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), 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_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22].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 private fun decodeInsulinActionSetting(ai: ByteArray, map: MutableMap) { - 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", PumpConfigurationGroup.Insulin, map) } else { @@ -297,10 +297,10 @@ class MedtronicConverter @Inject constructor( } private val settingIndexMaxBasal: Int - private get() = if (is523orHigher()) 7 else 6 + get() = if (is523orHigher()) 7 else 6 private val settingIndexTimeDisplayFormat: Int - private get() = if (is523orHigher()) 9 else 8 + get() = if (is523orHigher()) 9 else 8 private fun decodeMaxBolus(ai: ByteArray?): Double { 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 { - return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher) + return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher) } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 181177d54f..57bc0eab11 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -38,8 +38,8 @@ abstract class MedtronicHistoryDecoder : MedtronicHi private fun checkPage(page: RawHistoryPage, partial: Boolean): List { val byteList: List = ArrayList() - if (medtronicUtil!!.medtronicPumpModel == null) { - aapsLogger!!.error(LTag.PUMPCOMM, "Device Type is not defined.") + if (medtronicUtil.medtronicPumpModel == null) { + aapsLogger.error(LTag.PUMPCOMM, "Device Type is not defined.") return byteList } return if (page.data.size != 1024) { @@ -82,9 +82,9 @@ abstract class MedtronicHistoryDecoder : MedtronicHi for ((key) in unknownOpCodes!!) { StringUtil.appendToStringBuilder(sb, "" + key, ", ") } - aapsLogger!!.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE") + aapsLogger.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE") 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!!) { sb = StringBuilder() @@ -94,9 +94,9 @@ abstract class MedtronicHistoryDecoder : MedtronicHi StringUtil.appendToStringBuilder(sb, key1, ", ") } 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 { - 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)) } } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index 6f2228b29c..e8b69a46ff 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -82,7 +82,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { if (!doNotProcess) { head = ByteArray(headLength - 1) for (i in 1 until headLength) { - head!![i - 1] = listRawData!![i]!! + head!![i - 1] = listRawData[i] } if (dateTimeLength > 0) { datetime = ByteArray(dateTimeLength) @@ -99,7 +99,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { var i = headLength + dateTimeLength var j = 0 while (j < bodyLength) { - body!![j] = listRawData!![i]!! + body!![j] = listRawData[i] i++ j++ } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt index 792120b688..c4036ea46e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/RawHistoryPage.kt @@ -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, crcCalculated)) } else { - if (MedtronicUtil.isLowLevelDebug()) aapsLogger.debug(LTag.PUMPBTCOMM, "CRC ok.") + if (MedtronicUtil.isLowLevelDebug) aapsLogger.debug(LTag.PUMPBTCOMM, "CRC ok.") } return crcCalculated == crcStored } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index c8e38e7fcb..0a2da5b5be 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -49,7 +49,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( return outList } do { - val opCode: Int = dataClear[counter]!!.toInt() + val opCode: Int = dataClear[counter].toInt() var special = false incompletePacket = false var skippedRecords = false @@ -69,7 +69,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } val entryType = getByCode(opCode.toByte()) val pe = PumpHistoryEntry() - pe.setEntryType(medtronicUtil!!.medtronicPumpModel, entryType!!) + pe.setEntryType(medtronicUtil.medtronicPumpModel!!, entryType!!) pe.offset = counter counter++ if (counter >= 1022) { @@ -91,7 +91,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } special = true } else { - for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel) - 1) { + for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel!!) - 1) { try { listRawData.add(dataClear[counter]) counter++ @@ -111,7 +111,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( if (pe.entryType === PumpHistoryEntryType.UnknownBasePacket) { 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, special) val decoded = decodeRecord(pe) if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { @@ -235,7 +235,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val offset = body!![0] * 1000 * 30 * 60 var rate: Float? = null 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 } @@ -254,7 +254,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val body = entry.body!! val dto = BolusWizardDTO() 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 bolusStrokes = 40.0f 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]) / // 10.0s dto.insulinSensitivity = body[4].toFloat() - dto.bgTargetLow = body[5] as Int - dto.bgTargetHigh = body[14] as Int + dto.bgTargetLow = body[5].toInt() + dto.bgTargetHigh = body[14].toInt() dto.correctionEstimate = (((body[9] and 0x38).toInt() shl 5) + body[6]) / bolusStrokes dto.foodEstimate = ((body[7].toInt() shl 8) + body[8]) / bolusStrokes dto.unabsorbedInsulin = ((body[10].toInt() shl 8) + body[11]) / bolusStrokes dto.bolusTotal = ((body[12].toInt() shl 8) + body[13]) / bolusStrokes } else { 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.insulinSensitivity = body.get(3).toFloat() - dto.bgTargetLow = body.get(4) as Int - dto.bgTargetHigh = body.get(12) as Int + dto.bgTargetLow = body.get(4).toInt() + dto.bgTargetHigh = body.get(12).toInt() dto.bolusTotal = body.get(11) / bolusStrokes dto.foodEstimate = body.get(6) / bolusStrokes dto.unabsorbedInsulin = body.get(9) / bolusStrokes @@ -359,7 +359,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( private fun decodeBolus(entry: PumpHistoryEntry) { val bolus = BolusDTO() 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.deliveredAmount = ByteUtil.toInt(data.get(2), data.get(3)) / 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.duration = ByteUtil.asUINT8(data.get(2)) * 30 } - bolus.bolusType = if (bolus.duration != null && bolus.duration > 0) PumpBolusType.Extended else PumpBolusType.Normal - bolus.setAtechDateTime(entry.atechDateTime!!) + bolus.bolusType = if (bolus.duration != null && bolus.duration!! > 0) PumpBolusType.Extended else PumpBolusType.Normal + bolus.atechDateTime = entry.atechDateTime!! entry.addDecodedData("Object", bolus) entry.displayableValue = bolus.displayableValue } @@ -404,10 +404,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( // tbrDuration.getHead()[0], // (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0); val tbr = TempBasalPair( - tbrRate!!.head!!.get(0), - tbrRate!!.body!!.get(0), + tbrRate.head!!.get(0), + tbrRate.body!!.get(0), 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() // // + " min. Packed: " + tbr.getValue() @@ -464,13 +464,13 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun fix2DigitYear(year: Int): Int { - var year = year - year += if (year > 90) { + var yearInternal = year + yearInternal += if (yearInternal > 90) { 1900 } else { 2000 } - return year + return yearInternal } companion object { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index 289cb113ed..7cb40c46e6 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -35,16 +35,16 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { field = value } - fun setEntryType(medtronicDeviceType: MedtronicDeviceType?, entryType: PumpHistoryEntryType) { + fun setEntryType(medtronicDeviceType: MedtronicDeviceType, entryType: PumpHistoryEntryType) { this.entryType = entryType sizes[0] = entryType.getHeadLength(medtronicDeviceType) sizes[1] = entryType.dateLength sizes[2] = entryType.getBodyLength(medtronicDeviceType) - if (this.entryType != null && atechDateTime != null) setPumpId() + if (this.entryType != null && atechDateTime != null) generatePumpId() } - private fun setPumpId() { - pumpId = entryType!!.code + atechDateTime!! * 1000L + private fun generatePumpId() : Long { + return entryType!!.code + atechDateTime!! * 1000L } override val toStringStart: String @@ -105,7 +105,7 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { override var pumpId: Long? = null get() { - setPumpId() + field = generatePumpId() return field } set(pumpId) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt index 9ddb18b996..796ec828db 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt @@ -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, 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) { getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + dateLength } else { @@ -220,10 +220,6 @@ enum class PumpHistoryEntryType // implements CodeEnum } } - // private fun hasSpecialRules(): Boolean { - // return hasSpecialRules - // } - fun addSpecialRuleHead(rule: SpecialRule) { if (isEmpty(specialRulesHead)) { specialRulesHead = ArrayList() @@ -244,7 +240,7 @@ enum class PumpHistoryEntryType // implements CodeEnum // return description ?: name // } - fun getHeadLength(medtronicDeviceType: MedtronicDeviceType?): Int { + fun getHeadLength(medtronicDeviceType: MedtronicDeviceType): Int { return if (hasSpecialRules) { if (isNotEmpty(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) { if (isNotEmpty(specialRulesBody)) { determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody) @@ -277,7 +273,7 @@ enum class PumpHistoryEntryType // implements CodeEnum } // byte[] dh = { 2, 3 }; - private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType?, defaultValue: Int, rules: List?): Int { + private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType, defaultValue: Int, rules: List?): Int { var size = defaultValue for (rule in rules!!) { if (MedtronicDeviceType.isSameDevice(medtronicDeviceType, rule.deviceType)) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt index 0ab0e7e05e..b772119de8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt @@ -4,6 +4,7 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import java.util.* +import kotlin.collections.ArrayList /** * 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 var searchDate: Long? = null private var searchType = SearchType.None - @JvmField var unprocessedEntries: List? = null - @JvmField var validEntries: MutableList? - fun addHistoryEntries(entries: List?, page: Int) { + var unprocessedEntries: List = ArrayList() + var validEntries: MutableList = ArrayList() + + + fun addHistoryEntries(entries: List, page: Int) { unprocessedEntries = entries //aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries)); processEntries() @@ -32,7 +35,7 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis Collections.reverse(unprocessedEntries) when (searchType) { SearchType.None -> //aapsLogger.debug(LTag.PUMPCOMM,"PE. None search"); - validEntries!!.addAll(unprocessedEntries!!) + validEntries.addAll(unprocessedEntries) SearchType.LastEntry -> { 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()); aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: " + searchEntry!!.atechDateTime) val date = searchEntry.atechDateTime - for (unprocessedEntry in unprocessedEntries!!) { - if (unprocessedEntry!!.equals(searchEntry)) { + for (unprocessedEntry in unprocessedEntries) { + if (unprocessedEntry.equals(searchEntry)) { //aapsLogger.debug(LTag.PUMPCOMM,"PE. Item found {}.", unprocessedEntry); isSearchFinished = true break } //aapsLogger.debug(LTag.PUMPCOMM,"PE. Entry {} added.", unprocessedEntry); - validEntries!!.add(unprocessedEntry) + validEntries.add(unprocessedEntry) } } SearchType.Date -> { aapsLogger.debug(LTag.PUMPCOMM, "PE. Date search: Search date: " + searchDate) - for (unprocessedEntry in unprocessedEntries!!) { - if (unprocessedEntry!!.atechDateTime == null || unprocessedEntry.atechDateTime == 0L) { + for (unprocessedEntry in unprocessedEntries) { + if (unprocessedEntry.atechDateTime == null || unprocessedEntry.atechDateTime == 0L) { aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: Entry with no date: $unprocessedEntry") continue } if (unprocessedEntry.isAfter(searchDate!!)) { - validEntries!!.add(unprocessedEntry) + validEntries.add(unprocessedEntry) } else { // aapsLogger.debug(LTag.PUMPCOMM,"PE. PumpHistoryResult. Not after.. Unprocessed Entry [year={},entry={}]", // DateTimeUtil.getYear(unprocessedEntry.atechDateTime), unprocessedEntry); @@ -85,35 +88,19 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis ", searchType=" + searchType + // ", 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 */ val latestEntry: PumpHistoryEntry? - get() = if (validEntries == null || validEntries!!.size == 0) null else { - validEntries!![0] - // PumpHistoryEntry pumpHistoryEntry = this.validEntries.get(0); - // - // if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.EndResultTotals) - // return pumpHistoryEntry; - // else - // return this.validEntries.get(1); - } + get() = if (validEntries.size == 0) null else validEntries[0] - val isSearchRequired: Boolean - get() = searchType != SearchType.None - fun getValidEntries(): List? { - return validEntries - } + // val isSearchRequired: Boolean + // get() = searchType != SearchType.None + internal enum class SearchType { None, // @@ -139,6 +126,6 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis } // this.unprocessedEntries = new ArrayList<>(); - validEntries = ArrayList() + //validEntries = ArrayList() } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt index 3683f4e7c5..166a668d3e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt @@ -67,13 +67,13 @@ class PumpMessage : RLMessage { override fun getTxData(): ByteArray { 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) return rval } 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 // check if displayed length is invalid @@ -91,7 +91,7 @@ class PumpMessage : RLMessage { val data = messageBody!!.txData var length = ByteUtil.asUINT8(data!![0]) // length is not always correct so, we check whole array if we have // data, after length - val originalLength = length + //val originalLength = length // check if displayed length is invalid if (length > data.size - 1) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java deleted file mode 100644 index 0eed54e71f..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.java +++ /dev/null @@ -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(); - } -} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt new file mode 100644 index 0000000000..4cdb5766ec --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt @@ -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?): 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 + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java deleted file mode 100644 index 8022384731..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.java +++ /dev/null @@ -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 settings = (Map) 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); - } - - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt new file mode 100644 index 0000000000..21945e1707 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -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? + 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) + } + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java deleted file mode 100644 index f8ef1ee190..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.java +++ /dev/null @@ -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; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt new file mode 100644 index 0000000000..815ca14549 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt @@ -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? = 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?) { + this.injector = injector + this.injector.androidInjector().inject(this) + this.commandType = commandType + this.parameters = parameters //as Array + } + + 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] + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java index 9b3315e838..070bfb1a38 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java @@ -580,7 +580,8 @@ public class MedtronicHistoryData { 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 tddsIn) { @@ -972,7 +973,7 @@ public class MedtronicHistoryData { detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.getAtechDateTime())); detailedBolusInfo.setPumpType(PumpType.MEDTRONIC_512_712); // TODO grab real model - detailedBolusInfo.setPumpSerial(medtronicPumpStatus.serialNumber); + detailedBolusInfo.setPumpSerial(medtronicPumpStatus.getSerialNumber()); detailedBolusInfo.setBolusPumpId(bolus.getPumpId()); detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount(); @@ -1046,7 +1047,7 @@ public class MedtronicHistoryData { if (doubleBolusDebug) 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 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(); } @@ -1480,7 +1481,7 @@ public class MedtronicHistoryData { aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. item found, setting new basalProfileLocally: " + newProfile); BasalProfile basalProfile = (BasalProfile) newProfile.getDecodedData().get("Object"); - mdtPumpStatus.basalsByHour = basalProfile.getProfilesByHour(pumpType); + mdtPumpStatus.setBasalsByHour( basalProfile.getProfilesByHour(pumpType)); } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt index 3777c30559..489e2b2c36 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -55,18 +55,18 @@ class BasalProfile { } private fun setRawData(data: ByteArray): Boolean { - var data: ByteArray? = data - if (data == null) { + var dataInternal: ByteArray? = data + if (dataInternal == null) { aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") return false } // if we have just one entry through all day it looks like just length 1 - if (data.size == 1) { - data = MedtronicUtil.createByteArray(data[0], 0.toByte(), 0.toByte()) + if (dataInternal.size == 1) { + dataInternal = byteArrayOf(dataInternal[0], 0, 0) } - if (data!!.size == MAX_RAW_DATA_SIZE) { - rawData = data + if (dataInternal.size == MAX_RAW_DATA_SIZE) { + rawData = dataInternal } else { val len = Math.min(MAX_RAW_DATA_SIZE, data.size) rawData = ByteArray(MAX_RAW_DATA_SIZE) @@ -233,10 +233,10 @@ class BasalProfile { // return this.mRawData; } - fun getProfilesByHour(pumpType: PumpType?): Array { - var entries: List? = null + fun getProfilesByHour(pumpType: PumpType): Array { + var entriesCopy: List? = null try { - entries = entries + entriesCopy = entries } catch (ex: Exception) { aapsLogger.error(LTag.PUMPCOMM, "=============================================================================") aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: $ex", ex) @@ -245,40 +245,43 @@ class BasalProfile { //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); } - if (entries == null || entries.size == 0) { + if (entriesCopy == null || entriesCopy.size == 0) { val basalByHour = arrayOfNulls(24) for (i in 0..23) { basalByHour[i] = 0.0 } - return basalByHour + return basalByHour as Array } val basalByHour = arrayOfNulls(24) - for (i in entries.indices) { - val current = entries[i] + for (i in entriesCopy.indices) { + val current = entriesCopy[i] var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1 currentTime = currentTime * 30 / 60 var lastHour: Int - lastHour = if (i + 1 == entries.size) { + lastHour = if (i + 1 == entriesCopy.size) { 24 } 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 rawTime * 30 / 60 } // System.out.println("Current time: " + currentTime + " Next Time: " + 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 } override fun toString(): String { return basalProfileToString() } - fun verify(pumpType: PumpType?): Boolean { + fun verify(pumpType: PumpType): Boolean { try { entries } catch (ex: Exception) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java deleted file mode 100644 index 835d43c072..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.java +++ /dev/null @@ -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 - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.kt new file mode 100644 index 0000000000..60128d51a5 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BatteryStatusDTO.kt @@ -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 + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java deleted file mode 100644 index 8574bd831a..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.java +++ /dev/null @@ -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) - *

- * 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} - */ - -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() + "]"; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt new file mode 100644 index 0000000000..671aae39a5 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt @@ -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 + "]" + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java deleted file mode 100644 index 24b63015c4..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.java +++ /dev/null @@ -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() + "]"; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.kt new file mode 100644 index 0000000000..cf73a0506d --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusWizardDTO.kt @@ -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 + "]" + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java deleted file mode 100644 index 1623e03ff5..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.java +++ /dev/null @@ -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) -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt new file mode 100644 index 0000000000..32f52281a9 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt @@ -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 +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java deleted file mode 100644 index f32464b105..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.java +++ /dev/null @@ -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; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt new file mode 100644 index 0000000000..37284cffe1 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt @@ -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() + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java deleted file mode 100644 index 1868064d8b..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.java +++ /dev/null @@ -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() + "]"; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.kt new file mode 100644 index 0000000000..824151320e --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpSettingDTO.kt @@ -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 + "]" + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java deleted file mode 100644 index 84ad0914b3..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.java +++ /dev/null @@ -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); - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt new file mode 100644 index 0000000000..8d0bd646b7 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt @@ -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) + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.java deleted file mode 100644 index b171f5a061..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.java +++ /dev/null @@ -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); - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.kt new file mode 100644 index 0000000000..4a99585508 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/RLHistoryItemMedtronic.kt @@ -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) + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java deleted file mode 100644 index 418770d4b6..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java +++ /dev/null @@ -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. - *

- * 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 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() + "]"; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt new file mode 100644 index 0000000000..1cd5f8dab7 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt @@ -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 = 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 + "]") + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java deleted file mode 100644 index f35a5b43c0..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.java +++ /dev/null @@ -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 - } - - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt new file mode 100644 index 0000000000..a7705f8c2f --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt @@ -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 + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java deleted file mode 100644 index 0710e6ca4c..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.java +++ /dev/null @@ -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, // - ; - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.kt new file mode 100644 index 0000000000..5bce7a4d71 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BasalProfileStatus.kt @@ -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 + // +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java deleted file mode 100644 index 503074e640..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.java +++ /dev/null @@ -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; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.kt new file mode 100644 index 0000000000..a1c0aad63b --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/BatteryType.kt @@ -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 // + ); + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java deleted file mode 100644 index f061b860cf..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/CommandValueDefinitionMDTType.java +++ /dev/null @@ -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; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java deleted file mode 100755 index dfa4e83867..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.java +++ /dev/null @@ -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) - *

- * 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} - */ -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 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 getDeviceTypesArray(MedtronicDeviceType... types) { - HashMap hashMap = new HashMap(); - - 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 // - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt new file mode 100755 index 0000000000..47d4f4f1ba --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -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 = HashMap() + + private fun getDeviceTypesArray(vararg types: MedtronicDeviceType): HashMap { + val hashMap = HashMap() + 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 // + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java deleted file mode 100644 index af0be33cfa..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.java +++ /dev/null @@ -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(); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.kt new file mode 100644 index 0000000000..80713a7fa5 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCustomActionType.kt @@ -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 + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java deleted file mode 100644 index 6623a6f9d8..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.java +++ /dev/null @@ -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) - *

- * 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 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; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt new file mode 100644 index 0000000000..6f4cf7704c --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt @@ -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? = 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? = null + private set + + constructor(pumpModel: String?) { + isFamily = false + this.pumpModel = pumpModel + } + + constructor(vararg familyMembers: MedtronicDeviceType) { + this.familyMembers = familyMembers as Array? + isFamily = true + } + + val isMedtronic_523orHigher: Boolean + get() = isSameDevice(this, Medtronic_523andHigher) + + val bolusStrokes: Int + get() = if (isMedtronic_523orHigher) 40 else 10 + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java deleted file mode 100644 index b05fce81fc..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.java +++ /dev/null @@ -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 - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.kt new file mode 100644 index 0000000000..aad989679d --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicNotificationType.kt @@ -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) {} +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java deleted file mode 100644 index f84f6d3678..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.java +++ /dev/null @@ -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; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt new file mode 100644 index 0000000000..5a416b80a8 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt @@ -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 + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java deleted file mode 100644 index 8ab1fc0871..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.java +++ /dev/null @@ -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 - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.kt new file mode 100644 index 0000000000..6067085071 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicUIResponseType.kt @@ -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 +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java deleted file mode 100644 index 820bff8a5b..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.java +++ /dev/null @@ -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) - *

- * 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: PumpBolusType Description: Pump Bolus Types - *

- * 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 translationMapping = new HashMap(); - static HashMap codeMapping = new HashMap(); - 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(); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.kt new file mode 100644 index 0000000000..02e3bdbd2b --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpBolusType.kt @@ -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() + + 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 +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java deleted file mode 100644 index 1c69641c98..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.java +++ /dev/null @@ -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(); - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.kt new file mode 100644 index 0000000000..6a1c13a628 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/PumpConfigurationGroup.kt @@ -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); + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java deleted file mode 100644 index 905a005e29..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java +++ /dev/null @@ -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 medtronicPumpMap = null; - private Map 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 getMedtronicPumpMap() { - return medtronicPumpMap; - } - - public Map 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 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)); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt new file mode 100644 index 0000000000..e0b65dcf54 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -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 = HashMap() + var medtronicDeviceTypeMap: MutableMap = 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 = 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() + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java deleted file mode 100644 index 2c5274ba0b..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java +++ /dev/null @@ -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); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt new file mode 100644 index 0000000000..89a31552d2 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -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? = 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) + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java deleted file mode 100644 index b09f0f80a1..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.java +++ /dev/null @@ -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"; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.kt new file mode 100644 index 0000000000..80d284f80a --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicConst.kt @@ -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" + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java deleted file mode 100644 index 680896751c..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.java +++ /dev/null @@ -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 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 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> getBasalProfileFrames(byte[] data) { - - boolean done = false; - int start = 0; - int frame = 1; - - List> 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 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 frameData = new ArrayList<>(); - - byte b = (byte) frame; - b |= 0b1000_0000; - // b |= doneBit; - - frameData.add(b); - - checkAndAppenLastFrame(frameData); - } - - return frames; - - } - - - private void checkAndAppenLastFrame(List 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 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 getSettings() { - return settings; - } - - public void setSettings(Map settings) { - this.settings = settings; - } - - public void setPumpTime(ClockDTO pumpTime) { - this.pumpTime = pumpTime; - } - - public ClockDTO getPumpTime() { - return this.pumpTime; - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt new file mode 100644 index 0000000000..ac690be476 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt @@ -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? = 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> { + var done = false + var start = 0 + var frame = 1 + val frames: MutableList> = 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 = ArrayList() + var b = frame.toByte() + b = b or 128.toByte() + // b |= doneBit; + frameData.add(b) + checkAndAppenLastFrame(frameData) + } + return frames + } + + private fun checkAndAppenLastFrame(frameData: MutableList) { + 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): 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): 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 + } + } + +} \ No newline at end of file diff --git a/medtronic/src/main/res/values/strings.xml b/medtronic/src/main/res/values/strings.xml index 32715ce7b4..801413be38 100644 --- a/medtronic/src/main/res/values/strings.xml +++ b/medtronic/src/main/res/values/strings.xml @@ -95,6 +95,9 @@ Get History - Page %1$d (%2$d/16) Get History - Page %1$d Get Pump Time + Set Pump Time + Get Battery Status + Get Settings Get Pump Model Get Basal Profile @@ -115,8 +118,7 @@ set_neutral_temps Set neutral temp basals 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. - - + %1$.1f U/h (%2$d min remaining) ^\\d{6} \ No newline at end of file diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java index da5e99596c..ac4f6d24af 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java @@ -186,22 +186,6 @@ public class ByteUtil { } - // public static byte[] fromByteList(List 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 toByteList(byte[] data) { - // ArrayList 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 getListFromByteArray(byte[] array) { List listOut = new ArrayList(); @@ -340,6 +324,9 @@ public class ByteUtil { 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) { return toInt(b1, b2, null, null, flag); From 6b7efdcb95abee1240098a6a6487e233700cd654 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Tue, 20 Apr 2021 16:45:29 +0100 Subject: [PATCH 06/39] - more kotlinize, MedtronicHistoryActivity not yet working --- app/build.gradle | 2 +- .../pump/common/PumpPluginAbstract.java | 529 ------ .../plugins/pump/common/PumpPluginAbstract.kt | 431 +++++ .../plugins/pump/common/data/PumpDbEntry.java | 21 - .../plugins/pump/common/data/PumpDbEntry.kt | 9 + .../pump/medtronic/MedtronicPumpPlugin.java | 1627 ----------------- .../pump/medtronic/MedtronicPumpPlugin.kt | 1179 ++++++++++++ .../comm/MedtronicCommunicationManager.java | 38 + .../pump/medtronic/data/dto/BasalProfile.kt | 25 +- .../dialog/MedtronicHistoryActivity.java | 250 --- .../dialog/MedtronicHistoryActivity.kt | 200 ++ .../RileyLinkStatusDeviceMedtronic.java | 166 -- .../dialog/RileyLinkStatusDeviceMedtronic.kt | 137 ++ .../service/RileyLinkMedtronicService.kt | 11 +- .../pump/common/defs/PumpHistoryEntryGroup.kt | 4 +- .../res/layout/rileylink_status_device.xml | 2 +- 16 files changed, 2016 insertions(+), 2615 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt diff --git a/app/build.gradle b/app/build.gradle index e4d4c5be8b..ce044fe703 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,7 +111,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "2.8.2.1-dev-e3" + version "2.8.2.1-meallink-mdt" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java deleted file mode 100644 index ca9100a086..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java +++ /dev/null @@ -1,529 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.common; - -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; - -import androidx.annotation.NonNull; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.Map; - -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.db.TemporaryBasal; -import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.events.EventCustomActionsChanged; -import info.nightscout.androidaps.extensions.PumpStateExtensionKt; -import info.nightscout.androidaps.interfaces.ActivePlugin; -import info.nightscout.androidaps.interfaces.CommandQueueProvider; -import info.nightscout.androidaps.interfaces.Constraints; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PumpDescription; -import info.nightscout.androidaps.interfaces.Pump; -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.plugins.pump.medtronic.util.MedtronicConst; -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; - -import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute; -import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes; - -/** - * 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 Pump, Constraints { - private final CompositeDisposable disposable = new CompositeDisposable(); - - protected HasAndroidInjector injector; - protected AAPSLogger aapsLogger; - protected RxBusWrapper rxBus; - protected ActivePlugin 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; - protected Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); - - protected PumpPluginAbstract( - PluginDescription pluginDescription, - PumpType pumpType, - HasAndroidInjector injector, - ResourceHelper resourceHelper, - AAPSLogger aapsLogger, - CommandQueueProvider commandQueue, - RxBusWrapper rxBus, - ActivePlugin 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().getLastConnection(); - } - - - 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 - - - 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().getLastConnection() + 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().getBatteryRemaining()); - status.put("status", getPumpStatusData().getPumpStatusType() != null ? getPumpStatusData().getPumpStatusType().getStatus() : "normal"); - extended.put("Version", version); - try { - extended.put("ActiveProfile", profileName); - } catch (Exception ignored) { - } - - PumpSync.PumpState.TemporaryBasal tb = pumpSync.expectedPumpState().getTemporaryBasal(); - if (tb != null) { - extended.put("TempBasalAbsoluteRate", convertedToAbsolute(tb, now, profile)); - extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.getTimestamp())); - extended.put("TempBasalRemaining", getPlannedRemainingMinutes(tb)); - } - - PumpSync.PumpState.ExtendedBolus eb = pumpSync.expectedPumpState().getExtendedBolus(); - 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().getReservoirRemainingUnits()); - 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().getLastConnection() != 0) { - long agoMsec = System.currentTimeMillis() - getPumpStatusData().getLastConnection(); - int agoMin = (int) (agoMsec / 60d / 1000d); - ret += "LastConn: " + agoMin + " min ago\n"; - } - if (getPumpStatusData().getLastBolusTime() != null && getPumpStatusData().getLastBolusTime().getTime() != 0) { - ret += "LastBolus: " + DecimalFormatter.INSTANCE.to2Decimal(getPumpStatusData().getLastBolusAmount()) + "U @" + // - android.text.format.DateFormat.format("HH:mm", getPumpStatusData().getLastBolusTime()) + "\n"; - } - PumpSync.PumpState.TemporaryBasal activeTemp = pumpSync.expectedPumpState().getTemporaryBasal(); - if (activeTemp != null) { - ret += "Temp: " + PumpStateExtensionKt.toStringFull(activeTemp, dateUtil) + "\n"; - } - PumpSync.PumpState.ExtendedBolus activeExtendedBolus = pumpSync.expectedPumpState().getExtendedBolus(); - 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().getIob() + "U\n"; - ret += "Reserv: " + DecimalFormatter.INSTANCE.to0Decimal(getPumpStatusData().getReservoirRemainingUnits()) + "U\n"; - ret += "Batt: " + getPumpStatusData().getBatteryRemaining() + "\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 driverHistory = new HashMap<>(); - - public abstract long generateTempId(long timeMillis); - - protected boolean addBolusWithTempId(DetailedBolusInfo detailedBolusInfo, boolean writeToInternalHistory) { - long temporaryId = generateTempId(detailedBolusInfo.timestamp); - boolean response = pumpSync.addBolusWithTempId(detailedBolusInfo.timestamp, detailedBolusInfo.insulin, - temporaryId, detailedBolusInfo.getBolusType(), - getPumpType(), serialNumber()); - - if (response && writeToInternalHistory) { - driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); - sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); - } - - return response; - } - - protected void addTemporaryBasalRateWithTempId(TemporaryBasal temporaryBasal, boolean b) { -// long temporaryId = generateTempId(temporaryBasal.timestamp); -// boolean response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, -// generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), -// getPumpType(), serialNumber()); -// -// if (response && writeToInternalHistory) { -// driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); -// sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); -// } -// -// return response; - } - - - public void removeTemporaryId(long temporaryId) { - driverHistory.remove(temporaryId); - } - - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt new file mode 100644 index 0000000000..26660c4936 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -0,0 +1,431 @@ +package info.nightscout.androidaps.plugins.pump.common + +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.text.format.DateFormat +import com.google.gson.GsonBuilder +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.db.TemporaryBasal +import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.events.EventCustomActionsChanged +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.plannedRemainingMinutes +import info.nightscout.androidaps.extensions.toStringFull +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.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.plugins.pump.medtronic.util.MedtronicConst +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal +import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal +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 +import org.json.JSONException +import org.json.JSONObject +import java.util.* + +/** + * Created by andy on 23.04.18. + */ +// When using this class, make sure that your first step is to create mConnection (see MedtronicPumpPlugin) +abstract class PumpPluginAbstract protected constructor( + pluginDescription: PluginDescription?, + pumpType: PumpType, + injector: HasAndroidInjector?, + resourceHelper: ResourceHelper, + aapsLogger: AAPSLogger, + commandQueue: CommandQueueProvider, + var rxBus: RxBusWrapper, + var activePlugin: ActivePlugin, + var sp: SP, + var context: Context, + var fabricPrivacy: FabricPrivacy, + dateUtil: DateUtil, + aapsSchedulers: AapsSchedulers, + pumpSync: PumpSync +) : PumpPluginBase(pluginDescription!!, injector!!, aapsLogger, resourceHelper, commandQueue), Pump, Constraints { + + private val disposable = CompositeDisposable() + //protected override var injector: HasAndroidInjector? = null + protected var dateUtil: DateUtil + + // Pump capabilities + final override var pumpDescription = PumpDescription() + //protected set + + @JvmField protected var serviceConnection: ServiceConnection? = null + @JvmField protected var serviceRunning = false + @JvmField protected var pumpState = PumpDriverState.NotInitialized + @JvmField protected var displayConnectionMessages = false + + var pumpType: PumpType? = null + get() = field + set(value) { + field = value + pumpDescription.setPumpDescription(value!!) + } + + + protected var aapsSchedulers: AapsSchedulers + protected var pumpSync: PumpSync + protected var gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() + + abstract fun initPumpStatusData() + + override fun onStart() { + super.onStart() + initPumpStatusData() + val intent = Intent(context, serviceClass) + context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) + serviceRunning = true + disposable.add(rxBus + .toObservable(EventAppExit::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ event: EventAppExit? -> context.unbindService(serviceConnection) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } + ) + onStartCustomActions() + } + + override fun onStop() { + aapsLogger.debug(LTag.PUMP, deviceID() + " onStop()") + context.unbindService(serviceConnection) + serviceRunning = false + disposable.clear() + super.onStop() + } + + /** + * If we need to run any custom actions in onStart (triggering events, etc) + */ + abstract fun onStartCustomActions() + + /** + * Service class (same one you did serviceConnection for) + * + * @return Class + */ + abstract val serviceClass: Class<*>? + abstract val pumpStatusData: PumpStatus + + override fun isInitialized(): Boolean { + return pumpState.isInitialized() + } + + override fun isSuspended(): Boolean { + return pumpState === PumpDriverState.Suspended + } + + override fun isBusy(): Boolean { + return pumpState === PumpDriverState.Busy + } + + override fun isConnected(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "isConnected [PumpPluginAbstract].") + return pumpState.isConnected() + } + + override fun isConnecting(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "isConnecting [PumpPluginAbstract].") + return pumpState === PumpDriverState.Connecting + } + + override fun connect(reason: String) { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "connect (reason={}) [PumpPluginAbstract] - default (empty) implementation.$reason") + } + + override fun disconnect(reason: String) { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "disconnect (reason={}) [PumpPluginAbstract] - default (empty) implementation.$reason") + } + + override fun stopConnecting() { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "stopConnecting [PumpPluginAbstract] - default (empty) implementation.") + } + + override fun isHandshakeInProgress(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "isHandshakeInProgress [PumpPluginAbstract] - default (empty) implementation.") + return false + } + + override fun finishHandshaking() { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "finishHandshaking [PumpPluginAbstract] - default (empty) implementation.") + } + + // Upload to pump new basal profile + override fun setNewBasalProfile(profile: Profile): PumpEnactResult { + aapsLogger.debug(LTag.PUMP, "setNewBasalProfile [PumpPluginAbstract] - Not implemented.") + return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver) + } + + override fun isThisProfileSet(profile: Profile): Boolean { + aapsLogger.debug(LTag.PUMP, "isThisProfileSet [PumpPluginAbstract] - Not implemented.") + return true + } + + override fun lastDataTime(): Long { + aapsLogger.debug(LTag.PUMP, "lastDataTime [PumpPluginAbstract].") + return pumpStatusData.lastConnection + } + + // base basal rate, not temp basal + override val baseBasalRate: Double + get() { + aapsLogger.debug(LTag.PUMP, "getBaseBasalRate [PumpPluginAbstract] - Not implemented.") + return 0.0 + } + + override fun stopBolusDelivering() { + aapsLogger.debug(LTag.PUMP, "stopBolusDelivering [PumpPluginAbstract] - Not implemented.") + } + + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { + aapsLogger.debug(LTag.PUMP, "setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.") + return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver) + } + + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { + aapsLogger.debug(LTag.PUMP, "setTempBasalPercent [PumpPluginAbstract] - Not implemented.") + return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver) + } + + override fun setExtendedBolus(insulin: Double, durationInMinutes: Int): PumpEnactResult { + 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 + override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { + aapsLogger.debug(LTag.PUMP, "cancelTempBasal [PumpPluginAbstract] - Not implemented.") + return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver) + } + + override fun cancelExtendedBolus(): PumpEnactResult { + 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); + // } + open fun deviceID(): String { + aapsLogger.debug(LTag.PUMP, "deviceID [PumpPluginAbstract] - Not implemented.") + return "FakeDevice" + } + + // Short info for SMS, Wear etc + override val isFakingTempsByExtendedBoluses: Boolean + get() { + aapsLogger.debug(LTag.PUMP, "isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.") + return false + } + + override fun loadTDDs(): PumpEnactResult { + aapsLogger.debug(LTag.PUMP, "loadTDDs [PumpPluginAbstract] - Not implemented.") + return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver) + } + + override fun getJSONStatus(profile: Profile, profileName: String, version: String): JSONObject { + if (pumpStatusData.lastConnection + 60 * 60 * 1000L < System.currentTimeMillis()) { + return JSONObject() + } + val now = System.currentTimeMillis() + val pump = JSONObject() + val battery = JSONObject() + val status = JSONObject() + val extended = JSONObject() + try { + battery.put("percent", pumpStatusData.batteryRemaining) + status.put("status", if (pumpStatusData.pumpStatusType != null) pumpStatusData.pumpStatusType.status else "normal") + extended.put("Version", version) + try { + extended.put("ActiveProfile", profileName) + } catch (ignored: Exception) { + } + val tb = pumpSync.expectedPumpState().temporaryBasal + if (tb != null) { + extended.put("TempBasalAbsoluteRate", tb.convertedToAbsolute(now, profile)) + extended.put("TempBasalStart", dateUtil.dateAndTimeString(tb.timestamp)) + extended.put("TempBasalRemaining", tb.plannedRemainingMinutes) + } + val eb = pumpSync.expectedPumpState().extendedBolus + if (eb != null) { + extended.put("ExtendedBolusAbsoluteRate", eb.rate) + extended.put("ExtendedBolusStart", dateUtil.dateAndTimeString(eb.timestamp)) + extended.put("ExtendedBolusRemaining", eb.plannedRemainingMinutes) + } + status.put("timestamp", dateUtil.toISOString(dateUtil.now())) + pump.put("battery", battery) + pump.put("status", status) + pump.put("extended", extended) + pump.put("reservoir", pumpStatusData.reservoirRemainingUnits) + pump.put("clock", dateUtil.toISOString(dateUtil.now())) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + return pump + } + + // FIXME i18n, null checks: iob, TDD + override fun shortStatus(veryShort: Boolean): String { + var ret = "" + + if (pumpStatusData.lastConnection==0L) { + ret += "LastConn: never\n" + } else { + val agoMsec = System.currentTimeMillis() - pumpStatusData.lastConnection + val agoMin = (agoMsec / 60.0 / 1000.0).toInt() + ret += "LastConn: $agoMin min ago\n" + } + + if (pumpStatusData.lastBolusTime != null && pumpStatusData.lastBolusTime!!.time != 0L) { + ret += """ + LastBolus: ${to2Decimal(pumpStatusData.lastBolusAmount!!)}U @${DateFormat.format("HH:mm", pumpStatusData.lastBolusTime)} + + """.trimIndent() + } + val activeTemp = pumpSync.expectedPumpState().temporaryBasal + if (activeTemp != null) { + ret += """ + Temp: ${activeTemp.toStringFull(dateUtil)} + + """.trimIndent() + } + val activeExtendedBolus = pumpSync.expectedPumpState().extendedBolus + if (activeExtendedBolus != null) { + ret += """ + Extended: ${activeExtendedBolus.toStringFull(dateUtil)} + + """.trimIndent() + } + // if (!veryShort) { + // ret += "TDD: " + DecimalFormatter.to0Decimal(pumpStatus.dailyTotalUnits) + " / " + // + pumpStatus.maxDailyTotalUnits + " U\n"; + // } + ret += """ + IOB: ${pumpStatusData.iob}U + + """.trimIndent() + ret += """ + Reserv: ${to0Decimal(pumpStatusData.reservoirRemainingUnits)}U + + """.trimIndent() + ret += """ + Batt: ${pumpStatusData.batteryRemaining} + + """.trimIndent() + return ret + } + + override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { + return try { + if (detailedBolusInfo.insulin == 0.0 && detailedBolusInfo.carbs == 0.0) { + // neither carbs nor bolus requested + aapsLogger.error("deliverTreatment: Invalid input") + PumpEnactResult(injector).success(false).enacted(false).bolusDelivered(0.0).carbsDelivered(0.0) + .comment(R.string.invalidinput) + } else if (detailedBolusInfo.insulin > 0) { + // bolus needed, ask pump to deliver it + deliverBolus(detailedBolusInfo) + } else { + + // TODO fix + // no bolus required, carb only treatment + activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) + val bolusingEvent = EventOverviewBolusProgress + bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) + bolusingEvent.percent = 100 + rxBus.send(bolusingEvent) + aapsLogger.debug(LTag.PUMP, "deliverTreatment: Carb only treatment.") + PumpEnactResult(injector).success(true).enacted(true).bolusDelivered(0.0) + .carbsDelivered(detailedBolusInfo.carbs).comment(R.string.common_resultok) + } + } finally { + triggerUIChange() + } + } + + protected fun refreshCustomActionsList() { + rxBus.send(EventCustomActionsChanged()) + } + + override fun manufacturer(): ManufacturerType { + return pumpType!!.manufacturer!! + } + + override fun model(): PumpType { + return pumpType!! + } + + + override fun canHandleDST(): Boolean { + return false + } + + protected abstract fun deliverBolus(detailedBolusInfo: DetailedBolusInfo?): PumpEnactResult + + protected abstract fun triggerUIChange() + + private fun getOperationNotSupportedWithCustomText(resourceId: Int): PumpEnactResult { + return PumpEnactResult(injector).success(false).enacted(false).comment(resourceId) + } + + // PumpSync + var driverHistory: MutableMap = HashMap() + + abstract fun generateTempId(timeMillis: Long): Long + + protected fun addBolusWithTempId(detailedBolusInfo: DetailedBolusInfo, writeToInternalHistory: Boolean): Boolean { + val temporaryId = generateTempId(detailedBolusInfo.timestamp) + val response = pumpSync.addBolusWithTempId(detailedBolusInfo.timestamp, detailedBolusInfo.insulin, + temporaryId, detailedBolusInfo.bolusType, + pumpType!!, serialNumber()) + if (response && writeToInternalHistory) { + driverHistory[temporaryId] = PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo) + sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)) + } + return response + } + + protected fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal?, b: Boolean) { +// long temporaryId = generateTempId(temporaryBasal.timestamp); +// boolean response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, +// generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), +// getPumpType(), serialNumber()); +// +// if (response && writeToInternalHistory) { +// driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); +// sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); +// } +// +// return response; + } + + fun removeTemporaryId(temporaryId: Long) { + driverHistory.remove(temporaryId) + } + + init { + pumpDescription.setPumpDescription(pumpType) + this.pumpType = pumpType + this.dateUtil = dateUtil + this.aapsSchedulers = aapsSchedulers + this.pumpSync = pumpSync + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java deleted file mode 100644 index f67a9741f8..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.java +++ /dev/null @@ -1,21 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.common.data; - -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; - -public class PumpDbEntry { - - long temporaryId; - PumpType pumpType; - String serialNumber; - DetailedBolusInfo detailedBolusInfo; - - public PumpDbEntry(long temporaryId, PumpType pumpType, String serialNumber, DetailedBolusInfo detailedBolusInfo) { - this.temporaryId = temporaryId; - this.pumpType = pumpType; - this.serialNumber = serialNumber; - this.detailedBolusInfo = detailedBolusInfo; - } - - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt new file mode 100644 index 0000000000..6dfe38133a --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.plugins.pump.common.data + +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType + +data class PumpDbEntry(var temporaryId: Long, + var pumpType: PumpType, + var serialNumber: String, + var detailedBolusInfo: DetailedBolusInfo) \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java deleted file mode 100644 index c86e7c95a3..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java +++ /dev/null @@ -1,1627 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic; - -import android.content.ComponentName; -import android.content.Context; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.os.SystemClock; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.preference.Preference; - -import org.joda.time.LocalDateTime; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.activities.ErrorHelperActivity; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.PumpEnactResult; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.interfaces.ActivePlugin; -import info.nightscout.androidaps.interfaces.CommandQueueProvider; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.Pump; -import info.nightscout.androidaps.interfaces.PumpDescription; -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.actions.defs.CustomAction; -import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType; -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.PumpPluginAbstract; -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.plugins.pump.common.events.EventRefreshButtonState; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpInfo; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask; -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUITask; -import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfileEntry; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; -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.MedtronicCustomActionType; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicStatusRefreshType; -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.EventMedtronicPumpConfigurationChanged; -import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged; -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 info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.TimeChangeType; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.rx.AapsSchedulers; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - - -/** - * Created by andy on 23.04.18. - * - * @author Andy Rozman (andy.rozman@gmail.com) - */ -@Singleton -public class MedtronicPumpPlugin extends PumpPluginAbstract implements Pump, RileyLinkPumpDevice { - - private final MedtronicUtil medtronicUtil; - private final MedtronicPumpStatus medtronicPumpStatus; - private final MedtronicHistoryData medtronicHistoryData; - private final RileyLinkServiceData rileyLinkServiceData; - private final ServiceTaskExecutor serviceTaskExecutor; - - private RileyLinkMedtronicService rileyLinkMedtronicService; - - // variables for handling statuses and history - private boolean firstRun = true; - private boolean isRefresh = false; - private final Map statusRefreshMap = new HashMap<>(); - private boolean isInitialized = false; - private PumpHistoryEntry lastPumpHistoryEntry; - - public static boolean isBusy = false; - private final List busyTimestamps = new ArrayList<>(); - private boolean hasTimeDateOrTimeZoneChanged = false; - private boolean usePumpSync = false; - - @Inject - public MedtronicPumpPlugin( - HasAndroidInjector injector, - AAPSLogger aapsLogger, - RxBusWrapper rxBus, - Context context, - ResourceHelper resourceHelper, - ActivePlugin activePlugin, - SP sp, - CommandQueueProvider commandQueue, - FabricPrivacy fabricPrivacy, - MedtronicUtil medtronicUtil, - MedtronicPumpStatus medtronicPumpStatus, - MedtronicHistoryData medtronicHistoryData, - RileyLinkServiceData rileyLinkServiceData, - ServiceTaskExecutor serviceTaskExecutor, - DateUtil dateUtil, - AapsSchedulers aapsSchedulers, - PumpSync pumpSync - ) { - - super(new PluginDescription() // - .mainType(PluginType.PUMP) // - .fragmentClass(MedtronicFragment.class.getName()) // - .pluginIcon(R.drawable.ic_veo_128) - .pluginName(R.string.medtronic_name) // - .shortName(R.string.medtronic_name_short) // - .preferencesId(R.xml.pref_medtronic) - .description(R.string.description_pump_medtronic), // - PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later - injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync - ); - - this.medtronicUtil = medtronicUtil; - this.medtronicPumpStatus = medtronicPumpStatus; - this.medtronicHistoryData = medtronicHistoryData; - this.rileyLinkServiceData = rileyLinkServiceData; - this.serviceTaskExecutor = serviceTaskExecutor; - - displayConnectionMessages = false; - } - - - @Override - protected void onStart() { - aapsLogger.debug(LTag.PUMP, this.deviceID() + " started."); - - serviceConnection = new ServiceConnection() { - - public void onServiceDisconnected(ComponentName name) { - aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is disconnected"); - rileyLinkMedtronicService = null; - } - - public void onServiceConnected(ComponentName name, IBinder service) { - aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is connected"); - RileyLinkMedtronicService.LocalBinder mLocalBinder = (RileyLinkMedtronicService.LocalBinder) service; - rileyLinkMedtronicService = mLocalBinder.getServiceInstance(); - rileyLinkMedtronicService.verifyConfiguration(); - - new Thread(() -> { - - for (int i = 0; i < 20; i++) { - SystemClock.sleep(5000); - - aapsLogger.debug(LTag.PUMP, "Starting Medtronic-RileyLink service"); - if (rileyLinkMedtronicService.setNotInPreInit()) { - break; - } - } - }).start(); - } - }; - - super.onStart(); - } - - @Override - public void updatePreferenceSummary(@NonNull Preference pref) { - super.updatePreferenceSummary(pref); - - if (pref.getKey().equals(getResourceHelper().gs(R.string.key_rileylink_mac_address))) { - String value = sp.getStringOrNull(R.string.key_rileylink_mac_address, null); - pref.setSummary(value == null ? getResourceHelper().gs(R.string.not_set_short) : value); - } - } - - private String getLogPrefix() { - return "MedtronicPumpPlugin::"; - } - -// public PumpDescription getPumpDescription() { -// return super.pumpDescription; -// } - - - @Override - public void initPumpStatusData() { - - medtronicPumpStatus.setLastConnection(sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L)); - medtronicPumpStatus.setLastDataTime(medtronicPumpStatus.getLastConnection()); - medtronicPumpStatus.setPreviousConnection( medtronicPumpStatus.getLastConnection()); - - //if (rileyLinkMedtronicService != null) rileyLinkMedtronicService.verifyConfiguration(); - - aapsLogger.debug(LTag.PUMP, "initPumpStatusData: " + this.medtronicPumpStatus); - - // this is only thing that can change, by being configured - pumpDescription.setMaxTempAbsolute((medtronicPumpStatus.getMaxBasal() != null) ? medtronicPumpStatus.getMaxBasal() : 35.0d); - - // set first Medtronic Pump Start - if (!sp.contains(MedtronicConst.Statistics.FirstPumpStart)) { - sp.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis()); - } - - migrateSettings(); - - } - - @Override - public void triggerPumpConfigurationChangedEvent() { - rxBus.send(new EventMedtronicPumpConfigurationChanged()); - } - - private void migrateSettings() { - - if ("US (916 MHz)".equals(sp.getString(MedtronicConst.Prefs.PumpFrequency, "US (916 MHz)"))) { - sp.putString(MedtronicConst.Prefs.PumpFrequency, getResourceHelper().gs(R.string.key_medtronic_pump_frequency_us_ca)); - } - - String encoding = sp.getString(MedtronicConst.Prefs.Encoding, "RileyLink 4b6b Encoding"); - - if ("RileyLink 4b6b Encoding".equals(encoding)) { - sp.putString(MedtronicConst.Prefs.Encoding, getResourceHelper().gs(R.string.key_medtronic_pump_encoding_4b6b_rileylink)); - } - - if ("Local 4b6b Encoding".equals(encoding)) { - sp.putString(MedtronicConst.Prefs.Encoding, getResourceHelper().gs(R.string.key_medtronic_pump_encoding_4b6b_local)); - } - } - - - public void onStartCustomActions() { - - // check status every minute (if any status needs refresh we send readStatus command) - new Thread(() -> { - - do { - SystemClock.sleep(60000); - - if (this.isInitialized) { - - Map statusRefresh = workWithStatusRefresh( - StatusRefreshAction.GetData, null, null); - - if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { - if (!getCommandQueue().statusInQueue()) { - getCommandQueue().readStatus("Scheduled Status Refresh", null); - } - } - - clearBusyQueue(); - } - - } while (serviceRunning); - - }).start(); - } - - - public Class getServiceClass() { - return RileyLinkMedtronicService.class; - } - - @Override public PumpStatus getPumpStatusData() { - return medtronicPumpStatus; - } - - @Override - public String deviceID() { - return "Medtronic"; - } - - - @Override - public boolean isFakingTempsByExtendedBoluses() { - return false; - } - - - @Override - public boolean canHandleDST() { - return false; - } - - - // Pump Plugin - - private boolean isServiceSet() { - return rileyLinkMedtronicService != null; - } - - @Nullable - public RileyLinkMedtronicService getRileyLinkService() { - return rileyLinkMedtronicService; - } - - @Override - public RileyLinkPumpInfo getPumpInfo() { - 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 model = medtronicPumpStatus.getMedtronicDeviceType() == null ? "???" : "Medtronic " + medtronicPumpStatus.getMedtronicDeviceType().getPumpModel(); - String serialNumber = medtronicPumpStatus.getSerialNumber(); - return new RileyLinkPumpInfo(frequency, model, serialNumber); - } - - @Override public long getLastConnectionTimeMillis() { - return medtronicPumpStatus.getLastConnection(); - } - - @Override public void setLastCommunicationToNow() { - medtronicPumpStatus.setLastCommunicationToNow(); - } - - @Override - public boolean isInitialized() { - if (displayConnectionMessages) - aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isInitialized"); - return isServiceSet() && isInitialized; - } - - - @Override - public void setBusy(boolean busy) { - isBusy = busy; - } - - @Override - public boolean isBusy() { - if (displayConnectionMessages) - aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isBusy"); - - if (isServiceSet()) { - - if (isBusy) - return true; - - if (busyTimestamps.size() > 0) { - - clearBusyQueue(); - - return busyTimestamps.size() > 0; - } - } - - return false; - } - - - private synchronized void clearBusyQueue() { - - if (busyTimestamps.size() == 0) { - return; - } - - Set deleteFromQueue = new HashSet<>(); - - for (Long busyTimestamp : busyTimestamps) { - - if (System.currentTimeMillis() > busyTimestamp) { - deleteFromQueue.add(busyTimestamp); - } - } - - if (deleteFromQueue.size() == busyTimestamps.size()) { - busyTimestamps.clear(); - setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, false); - } - - if (deleteFromQueue.size() > 0) { - busyTimestamps.removeAll(deleteFromQueue); - } - - } - - - @Override - public boolean isConnected() { - if (displayConnectionMessages) - aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnected"); - return isServiceSet() && rileyLinkMedtronicService.isInitialized(); - } - - - @Override - public boolean isConnecting() { - if (displayConnectionMessages) - aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnecting"); - return !isServiceSet() || !rileyLinkMedtronicService.isInitialized(); - } - - - @Override - public void getPumpStatus(String reason) { - boolean needRefresh = true; - - if (firstRun) { - needRefresh = initializePump(!isRefresh); - } else { - refreshAnyStatusThatNeedsToBeRefreshed(); - } - - if (needRefresh) - rxBus.send(new EventMedtronicPumpValuesChanged()); - } - - - void resetStatusState() { - firstRun = true; - isRefresh = true; - } - - - private boolean isPumpNotReachable() { - - RileyLinkServiceState rileyLinkServiceState = rileyLinkServiceData.rileyLinkServiceState; - - if (rileyLinkServiceState == null) { - aapsLogger.debug(LTag.PUMP, "RileyLink unreachable. RileyLinkServiceState is null."); - return false; - } - - if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady // - && rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady // - && rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice) { - aapsLogger.debug(LTag.PUMP, "RileyLink unreachable."); - return false; - } - - return (!rileyLinkMedtronicService.getDeviceCommunicationManager().isDeviceReachable()); - } - - - private void refreshAnyStatusThatNeedsToBeRefreshed() { - - Map statusRefresh = workWithStatusRefresh(StatusRefreshAction.GetData, null, - null); - - if (!doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { - return; - } - - boolean resetTime = false; - - if (isPumpNotReachable()) { - aapsLogger.error("Pump unreachable."); - medtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable, getResourceHelper(), rxBus); - - return; - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - - - if (hasTimeDateOrTimeZoneChanged) { - - checkTimeAndOptionallySetTime(); - - // read time if changed, set new time - hasTimeDateOrTimeZoneChanged = false; - } - - - // execute - Set refreshTypesNeededToReschedule = new HashSet<>(); - - for (Map.Entry refreshType : statusRefresh.entrySet()) { - - if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) { - - switch (refreshType.getKey()) { - case PumpHistory: { - readPumpHistory(); - } - break; - - case PumpTime: { - checkTimeAndOptionallySetTime(); - refreshTypesNeededToReschedule.add(refreshType.getKey()); - resetTime = true; - } - break; - - case BatteryStatus: - case RemainingInsulin: { - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(refreshType.getKey().getCommandType(medtronicUtil.getMedtronicPumpModel())); - refreshTypesNeededToReschedule.add(refreshType.getKey()); - resetTime = true; - } - break; - - case Configuration: { - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(refreshType.getKey().getCommandType(medtronicUtil.getMedtronicPumpModel())); - resetTime = true; - } - break; - } - } - - // reschedule - for (MedtronicStatusRefreshType refreshType2 : refreshTypesNeededToReschedule) { - scheduleNextRefresh(refreshType2); - } - - } - - if (resetTime) - medtronicPumpStatus.setLastCommunicationToNow(); - - } - - - private boolean doWeHaveAnyStatusNeededRefereshing(Map statusRefresh) { - - for (Map.Entry refreshType : statusRefresh.entrySet()) { - - if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) { - return true; - } - } - - return hasTimeDateOrTimeZoneChanged; - } - - - private void setRefreshButtonEnabled(boolean enabled) { - rxBus.send(new EventRefreshButtonState(enabled)); - } - - - private boolean initializePump(boolean realInit) { - - if (rileyLinkMedtronicService == null) - return false; - - aapsLogger.info(LTag.PUMP, getLogPrefix() + "initializePump - start"); - - rileyLinkMedtronicService.getDeviceCommunicationManager().setDoWakeUpBeforeCommand(false); - - setRefreshButtonEnabled(false); - - if (isRefresh) { - if (isPumpNotReachable()) { - aapsLogger.error(getLogPrefix() + "initializePump::Pump unreachable."); - medtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable, getResourceHelper(), rxBus); - - setRefreshButtonEnabled(true); - - return true; - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - } - - // model (once) - if (medtronicUtil.getMedtronicPumpModel() == null) { - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.PumpModel); - } else { - if (medtronicPumpStatus.getMedtronicDeviceType() != medtronicUtil.getMedtronicPumpModel()) { - aapsLogger.warn(LTag.PUMP, getLogPrefix() + "Configured pump is not the same as one detected."); - medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, getResourceHelper(), rxBus); - } - } - - this.pumpState = PumpDriverState.Connected; - - // time (1h) - checkTimeAndOptionallySetTime(); - - readPumpHistory(); - - // remaining insulin (>50 = 4h; 50-20 = 1h; 15m) - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetRemainingInsulin); - scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10); - - // remaining power (1h) - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetBatteryStatus); - scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20); - - // configuration (once and then if history shows config changes) - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.getSettings(medtronicUtil.getMedtronicPumpModel())); - - // read profile (once, later its controlled by isThisProfileSet method) - getBasalProfiles(); - - int errorCount = rileyLinkMedtronicService.getMedtronicUIComm().getInvalidResponsesCount(); - - if (errorCount >= 5) { - aapsLogger.error("Number of error counts was 5 or more. Starting tunning."); - setRefreshButtonEnabled(true); - serviceTaskExecutor.startTask(new WakeAndTuneTask(getInjector())); - return true; - } - - medtronicPumpStatus.setLastCommunicationToNow(); - setRefreshButtonEnabled(true); - - if (!isRefresh) { - pumpState = PumpDriverState.Initialized; - } - - isInitialized = true; - // this.pumpState = PumpDriverState.Initialized; - - this.firstRun = false; - - return true; - } - - private void getBasalProfiles() { - - MedtronicUITask medtronicUITask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetBasalProfileSTD); - - if (medtronicUITask.getResponseType() == MedtronicUIResponseType.Error) { - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetBasalProfileSTD); - } - } - - - @Override - public boolean isThisProfileSet(@NonNull Profile profile) { - aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.getBasalProfileStatus()); - - if (!isInitialized) - return true; - - if (medtronicPumpStatus.getBasalProfileStatus() == BasalProfileStatus.NotInitialized) { - // this shouldn't happen, but if there was problem we try again - getBasalProfiles(); - return isProfileSame(profile); - } else if (medtronicPumpStatus.getBasalProfileStatus() == BasalProfileStatus.ProfileChanged) { - return false; - } - - return (medtronicPumpStatus.getBasalProfileStatus() != BasalProfileStatus.ProfileOK) || isProfileSame(profile); - } - - - private boolean isProfileSame(Profile profile) { - - boolean invalid = false; - Double[] basalsByHour = medtronicPumpStatus.getBasalsByHour(); - - aapsLogger.debug(LTag.PUMP, "Current Basals (h): " - + (basalsByHour == null ? "null" : BasalProfile.getProfilesByHourToString(basalsByHour))); - - // int index = 0; - - if (basalsByHour == null) - return true; // we don't want to set profile again, unless we are sure - - StringBuilder stringBuilder = new StringBuilder("Requested Basals (h): "); - - for (Profile.ProfileValue basalValue : profile.getBasalValues()) { - - double basalValueValue = pumpDescription.getPumpType().determineCorrectBasalSize(basalValue.value); - - int hour = basalValue.timeAsSeconds / (60 * 60); - - if (!MedtronicUtil.isSame(basalsByHour[hour], basalValueValue)) { - invalid = true; - } - - stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)); - stringBuilder.append(" "); - } - - aapsLogger.debug(LTag.PUMP, stringBuilder.toString()); - - if (!invalid) { - aapsLogger.debug(LTag.PUMP, "Basal profile is same as AAPS one."); - } else { - aapsLogger.debug(LTag.PUMP, "Basal profile on Pump is different than the AAPS one."); - } - - return (!invalid); - } - - - @Override - public long lastDataTime() { - - if (medtronicPumpStatus.getLastConnection() != 0) { - return medtronicPumpStatus.getLastConnection(); - } - - return System.currentTimeMillis(); - } - - - @Override - public double getBaseBasalRate() { - return medtronicPumpStatus.getBasalProfileForHour(); - } - - - @Override - public double getReservoirLevel() { - return medtronicPumpStatus.getReservoirRemainingUnits(); - } - - - @Override - public int getBatteryLevel() { - return medtronicPumpStatus.getBatteryRemaining(); - } - - protected void triggerUIChange() { - rxBus.send(new EventMedtronicPumpValuesChanged()); - } - - @Override public long generateTempId(long timeMillis) { - return 0; - } - -// @Override public String getSerial() { -// return null; -// } - - private BolusDeliveryType bolusDeliveryType = BolusDeliveryType.Idle; - - private enum BolusDeliveryType { - Idle, // - DeliveryPrepared, // - Delivering, // - CancelDelivery - } - - - private void checkTimeAndOptionallySetTime() { - - aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Start"); - - setRefreshButtonEnabled(false); - - if (isPumpNotReachable()) { - aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Pump Unreachable."); - setRefreshButtonEnabled(true); - return; - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetRealTimeClock); - - ClockDTO clock = medtronicUtil.getPumpTime(); - - if (clock == null) { // retry - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetRealTimeClock); - - clock = medtronicUtil.getPumpTime(); - } - - if (clock == null) - return; - - int timeDiff = Math.abs(clock.getTimeDifference()); - - if (timeDiff > 20) { - - 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)); - - rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetRealTimeClock); - - if (clock.getTimeDifference() == 0) { - Notification notification = new Notification(Notification.INSIGHT_DATE_TIME_UPDATED, getResourceHelper().gs(R.string.pump_time_updated), Notification.INFO, 60); - rxBus.send(new EventNewNotification(notification)); - } - } else { - if ((clock.getLocalDeviceTime().getYear() > 2015)) { - 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); - } - } - - } else { - aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Do nothing.", timeDiff)); - } - - scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0); - } - - - @NonNull - protected PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) { - - aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - " + BolusDeliveryType.DeliveryPrepared); - - setRefreshButtonEnabled(false); - - if (detailedBolusInfo.insulin > medtronicPumpStatus.getReservoirRemainingUnits()) { - return new PumpEnactResult(getInjector()) // - .success(false) // - .enacted(false) // - .comment(getResourceHelper().gs(R.string.medtronic_cmd_bolus_could_not_be_delivered_no_insulin, - medtronicPumpStatus.getReservoirRemainingUnits(), - detailedBolusInfo.insulin)); - } - - bolusDeliveryType = BolusDeliveryType.DeliveryPrepared; - - if (isPumpNotReachable()) { - aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - Pump Unreachable."); - return setNotReachable(true, false); - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - - if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled."); - return setNotReachable(true, true); - } - - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Starting wait period."); - - int sleepTime = sp.getInt(MedtronicConst.Prefs.BolusDelay, 10) * 1000; - - SystemClock.sleep(sleepTime); - - if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled, before wait period."); - return setNotReachable(true, true); - } - - // LOG.debug("MedtronicPumpPlugin::deliverBolus - End wait period. Start delivery"); - - try { - - bolusDeliveryType = BolusDeliveryType.Delivering; - - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); - - MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetBolus, - Arrays.asList(detailedBolusInfo.insulin)); - - Boolean response = (Boolean) responseTask.getResult(); - - setRefreshButtonEnabled(true); - - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Response: {}", response); - - if (response) { - - if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled after Bolus started."); - - new Thread(() -> { - // Looper.prepare(); - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog - before"); - SystemClock.sleep(2000); - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog. Context: " - // + MainApp.instance().getApplicationContext()); - - ErrorHelperActivity.Companion.runAlarm(context, getResourceHelper().gs(R.string.medtronic_cmd_cancel_bolus_not_supported), getResourceHelper().gs(R.string.medtronic_warning), R.raw.boluserror); - }).start(); - } - - long now = System.currentTimeMillis(); - - detailedBolusInfo.timestamp = now; - detailedBolusInfo.deliverAtTheLatest = now; // not sure about that one - - // TODO fix - if (usePumpSync) { - addBolusWithTempId(detailedBolusInfo, true); - } else { - activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true); - } - - // we subtract insulin, exact amount will be visible with next remainingInsulin update. - medtronicPumpStatus.setReservoirRemainingUnits(medtronicPumpStatus.getReservoirRemainingUnits() - detailedBolusInfo.insulin); - - incrementStatistics(detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB ? MedtronicConst.Statistics.SMBBoluses - : MedtronicConst.Statistics.StandardBoluses); - - - // calculate time for bolus and set driver to busy for that time - int bolusTime = (int) (detailedBolusInfo.insulin * 42.0d); - long time = now + (bolusTime * 1000); - - this.busyTimestamps.add(time); - setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, true); - - return new PumpEnactResult(getInjector()).success(true) // - .enacted(true) // - .bolusDelivered(detailedBolusInfo.insulin) // - .carbsDelivered(detailedBolusInfo.carbs); - - } else { - return new PumpEnactResult(getInjector()) // - .success(bolusDeliveryType == BolusDeliveryType.CancelDelivery) // - .enacted(false) // - .comment(R.string.medtronic_cmd_bolus_could_not_be_delivered); - } - - } finally { - finishAction("Bolus"); - this.bolusDeliveryType = BolusDeliveryType.Idle; - } - } - - - private PumpEnactResult setNotReachable(boolean isBolus, boolean success) { - setRefreshButtonEnabled(true); - - if (isBolus) { - bolusDeliveryType = BolusDeliveryType.Idle; - } - - if (success) { - return new PumpEnactResult(getInjector()) // - .success(true) // - .enacted(false); - } else { - return new PumpEnactResult(getInjector()) // - .success(false) // - .enacted(false) // - .comment(R.string.medtronic_pump_status_pump_unreachable); - } - } - - - public void stopBolusDelivering() { - - this.bolusDeliveryType = BolusDeliveryType.CancelDelivery; - - // if (isLoggingEnabled()) - // LOG.warn("MedtronicPumpPlugin::deliverBolus - Stop Bolus Delivery."); - } - - - private void incrementStatistics(String statsKey) { - long currentCount = sp.getLong(statsKey, 0L); - currentCount++; - sp.putLong(statsKey, currentCount); - } - - - // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged), - // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed - @NonNull @Override - public PumpEnactResult setTempBasalAbsolute(double absoluteRate, int durationInMinutes, Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) { - - setRefreshButtonEnabled(false); - - if (isPumpNotReachable()) { - - setRefreshButtonEnabled(true); - - return new PumpEnactResult(getInjector()) // - .success(false) // - .enacted(false) // - .comment(R.string.medtronic_pump_status_pump_unreachable); - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute: rate: " + absoluteRate + ", duration=" + durationInMinutes); - - // read current TBR - TempBasalPair tbrCurrent = readTBR(); - - if (tbrCurrent == null) { - aapsLogger.warn(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - Could not read current TBR, canceling operation."); - finishAction("TBR"); - return new PumpEnactResult(getInjector()).success(false).enacted(false) - .comment(R.string.medtronic_cmd_cant_read_tbr); - } else { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute: Current Basal: duration: " + tbrCurrent.getDurationMinutes() + " min, rate=" + tbrCurrent.getInsulinRate()); - } - - if (!enforceNew) { - - if (MedtronicUtil.isSame(tbrCurrent.getInsulinRate(), absoluteRate)) { - - boolean sameRate = true; - if (MedtronicUtil.isSame(0.0d, absoluteRate) && durationInMinutes > 0) { - // if rate is 0.0 and duration>0 then the rate is not the same - sameRate = false; - } - - if (sameRate) { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - No enforceNew and same rate. Exiting."); - finishAction("TBR"); - return new PumpEnactResult(getInjector()).success(true).enacted(false); - } - } - // if not the same rate, we cancel and start new - } - - // if TBR is running we will cancel it. - if (tbrCurrent.getInsulinRate() != 0.0f && tbrCurrent.getDurationMinutes() > 0) { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - TBR running - so canceling it."); - - // CANCEL - - MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR); - - Boolean response = (Boolean) responseTask2.getResult(); - - if (response) { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled."); - } else { - aapsLogger.error(getLogPrefix() + "setTempBasalAbsolute - Cancel TBR failed."); - - finishAction("TBR"); - - return new PumpEnactResult(getInjector()).success(false).enacted(false) - .comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op); - } - } - - // now start new TBR - MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetTemporaryBasal, - Arrays.asList(absoluteRate, durationInMinutes)); - - Boolean response = (Boolean) responseTask.getResult(); - - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response); - - if (response) { - // FIXME put this into UIPostProcessor - medtronicPumpStatus.setTempBasalStart(new Date()); - medtronicPumpStatus.setTempBasalAmount(absoluteRate); - medtronicPumpStatus.setTempBasalLength(durationInMinutes); - - TemporaryBasal tempStart = new TemporaryBasal(getInjector()) // - .date(System.currentTimeMillis()) // - .duration(durationInMinutes) // - .absolute(absoluteRate) // - .source(Source.USER); - - // TODO fix - if (usePumpSync) { - addTemporaryBasalRateWithTempId(tempStart, true); - } else { - activePlugin.getActiveTreatments().addToHistoryTempBasal(tempStart); - } - - - incrementStatistics(MedtronicConst.Statistics.TBRsSet); - - finishAction("TBR"); - - return new PumpEnactResult(getInjector()).success(true).enacted(true) // - .absolute(absoluteRate).duration(durationInMinutes); - - } else { - finishAction("TBR"); - - return new PumpEnactResult(getInjector()).success(false).enacted(false) // - .comment(R.string.medtronic_cmd_tbr_could_not_be_delivered); - } - - } - - - @NonNull @Override - public PumpEnactResult setTempBasalPercent(int percent, int durationInMinutes, @NonNull Profile profile, boolean enforceNew, @NonNull PumpSync.TemporaryBasalType tbrType) { - if (percent == 0) { - return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew, tbrType); - } else { - double absoluteValue = profile.getBasal() * (percent / 100.0d); - absoluteValue = pumpDescription.getPumpType().determineCorrectBasalSize(absoluteValue); - aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [MedtronicPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (" + percent + "). This will start setTempBasalAbsolute, with calculated value (" + absoluteValue + "). Result might not be 100% correct."); - return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew, tbrType); - } - } - - - private void finishAction(String overviewKey) { - - if (overviewKey != null) - rxBus.send(new EventRefreshOverview(overviewKey, false)); - - triggerUIChange(); - - setRefreshButtonEnabled(true); - } - - - private void readPumpHistory() { - -// if (isLoggingEnabled()) -// LOG.error(getLogPrefix() + "readPumpHistory WIP."); - - readPumpHistoryLogic(); - - scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory); - - if (medtronicHistoryData.hasRelevantConfigurationChanged()) { - scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1); - } - - if (medtronicHistoryData.hasPumpTimeChanged()) { - scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1); - } - - if (this.medtronicPumpStatus.getBasalProfileStatus() != BasalProfileStatus.NotInitialized - && medtronicHistoryData.hasBasalProfileChanged()) { - medtronicHistoryData.processLastBasalProfileChange(pumpDescription.getPumpType(), medtronicPumpStatus); - } - - PumpDriverState previousState = this.pumpState; - - if (medtronicHistoryData.isPumpSuspended()) { - this.pumpState = PumpDriverState.Suspended; - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "isPumpSuspended: true"); - } else { - if (previousState == PumpDriverState.Suspended) { - this.pumpState = PumpDriverState.Ready; - } - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "isPumpSuspended: false"); - } - - medtronicHistoryData.processNewHistoryData(); - - this.medtronicHistoryData.finalizeNewHistoryRecords(); - // this.medtronicHistoryData.setLastHistoryRecordTime(this.lastPumpHistoryEntry.atechDateTime); - - } - - - private void readPumpHistoryLogic() { - - boolean debugHistory = false; - - LocalDateTime targetDate = null; - - if (lastPumpHistoryEntry == null) { - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: null"); - - Long lastPumpHistoryEntryTime = getLastPumpEntryTime(); - - LocalDateTime timeMinus36h = new LocalDateTime(); - timeMinus36h = timeMinus36h.minusHours(36); - medtronicHistoryData.setIsInInit(true); - - if (lastPumpHistoryEntryTime == 0L) { - if (debugHistory) - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: 0L - targetDate: " - + targetDate); - targetDate = timeMinus36h; - } else { - // LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: " + lastPumpHistoryEntryTime + " - targetDate: " + targetDate); - - medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntryTime); - - LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); - - lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12); // we get last 12 hours of history to - // determine pump state - // (we don't process that data), we process only - - if (timeMinus36h.isAfter(lastHistoryRecordTime)) { - targetDate = timeMinus36h; - } - - targetDate = (timeMinus36h.isAfter(lastHistoryRecordTime) ? timeMinus36h : lastHistoryRecordTime); - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): targetDate: " + targetDate); - } - } else { - if (debugHistory) - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.getGsonInstance().toJson(lastPumpHistoryEntry)); - medtronicHistoryData.setIsInInit(false); - // medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime); - - // targetDate = lastPumpHistoryEntry.atechDateTime; - } - - //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); - - MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.GetHistoryData, - Arrays.asList(lastPumpHistoryEntry, targetDate)); - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, "HST: After task"); - - PumpHistoryResult historyResult = (PumpHistoryResult) responseTask2.getResult(); - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString()); - - PumpHistoryEntry latestEntry = historyResult.getLatestEntry(); - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, getLogPrefix() + "Last entry: " + latestEntry); - - if (latestEntry == null) // no new history to read - return; - - this.lastPumpHistoryEntry = latestEntry; - sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.getAtechDateTime()); - - if (debugHistory) - aapsLogger.debug(LTag.PUMP, "HST: History: valid=" + historyResult.getValidEntries().size() + ", unprocessed=" + historyResult.getUnprocessedEntries().size()); - - this.medtronicHistoryData.addNewHistory(historyResult); - this.medtronicHistoryData.filterNewEntries(); - - // determine if first run, if yes detrmine how much of update do we need - // first run: - // get last hiostory entry, if not there download 1.5 days of data - // - there: check if last entry is older than 1.5 days - // - yes: download 1.5 days - // - no: download with last entry - // - not there: download 1.5 days - // - // upload all new entries to NightScout (TBR, Bolus) - // determine pump status - // - // save last entry - // - // not first run: - // update to last entry - // - save - // - determine pump status - } - - - private Long getLastPumpEntryTime() { - Long lastPumpEntryTime = sp.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, 0L); - - try { - LocalDateTime localDateTime = DateTimeUtil.toLocalDateTime(lastPumpEntryTime); - - if (localDateTime.getYear() != (new GregorianCalendar().get(Calendar.YEAR))) { - aapsLogger.warn(LTag.PUMP, "Saved LastPumpHistoryEntry was invalid. Year was not the same."); - return 0L; - } - - return lastPumpEntryTime; - - } catch (Exception ex) { - aapsLogger.warn(LTag.PUMP, "Saved LastPumpHistoryEntry was invalid."); - return 0L; - } - - } - - - private void scheduleNextRefresh(MedtronicStatusRefreshType refreshType) { - scheduleNextRefresh(refreshType, 0); - } - - - private void scheduleNextRefresh(MedtronicStatusRefreshType refreshType, int additionalTimeInMinutes) { - switch (refreshType) { - - case RemainingInsulin: { - double remaining = medtronicPumpStatus.getReservoirRemainingUnits(); - int min; - if (remaining > 50) - min = 4 * 60; - else if (remaining > 20) - min = 60; - else - min = 15; - - workWithStatusRefresh(StatusRefreshAction.Add, refreshType, getTimeInFutureFromMinutes(min)); - } - break; - - case PumpTime: - case Configuration: - case BatteryStatus: - case PumpHistory: { - workWithStatusRefresh(StatusRefreshAction.Add, refreshType, - getTimeInFutureFromMinutes(refreshType.getRefreshTime() + additionalTimeInMinutes)); - } - break; - } - } - - private enum StatusRefreshAction { - Add, // - GetData - } - - - private synchronized Map workWithStatusRefresh(StatusRefreshAction action, // - MedtronicStatusRefreshType statusRefreshType, // - Long time) { - - switch (action) { - - case Add: { - statusRefreshMap.put(statusRefreshType, time); - return null; - } - - case GetData: { - return new HashMap<>(statusRefreshMap); - } - - default: - return null; - - } - - } - - - private long getTimeInFutureFromMinutes(int minutes) { - return System.currentTimeMillis() + getTimeInMs(minutes); - } - - - private long getTimeInMs(int minutes) { - return minutes * 60 * 1000L; - } - - - private TempBasalPair readTBR() { - MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.ReadTemporaryBasal); - - if (responseTask.hasData()) { - TempBasalPair tbr = (TempBasalPair) responseTask.getResult(); - - // we sometimes get rate returned even if TBR is no longer running - if (tbr.getDurationMinutes() == 0) { - tbr.setInsulinRate(0.0d); - } - - return tbr; - } else { - return null; - } - } - - - @NonNull @Override - public PumpEnactResult cancelTempBasal(boolean enforceNew) { - - aapsLogger.info(LTag.PUMP, getLogPrefix() + "cancelTempBasal - started"); - - if (isPumpNotReachable()) { - - setRefreshButtonEnabled(true); - - return new PumpEnactResult(getInjector()) // - .success(false) // - .enacted(false) // - .comment(R.string.medtronic_pump_status_pump_unreachable); - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - setRefreshButtonEnabled(false); - - TempBasalPair tbrCurrent = readTBR(); - - if (tbrCurrent != null) { - if (tbrCurrent.getInsulinRate() == 0.0f && tbrCurrent.getDurationMinutes() == 0) { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "cancelTempBasal - TBR already canceled."); - finishAction("TBR"); - return new PumpEnactResult(getInjector()).success(true).enacted(false); - } - } else { - aapsLogger.warn(LTag.PUMP, getLogPrefix() + "cancelTempBasal - Could not read currect TBR, canceling operation."); - finishAction("TBR"); - return new PumpEnactResult(getInjector()).success(false).enacted(false) - .comment(R.string.medtronic_cmd_cant_read_tbr); - } - - MedtronicUITask responseTask2 = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.CancelTBR); - - Boolean response = (Boolean) responseTask2.getResult(); - - finishAction("TBR"); - - if (response) { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "cancelTempBasal - Cancel TBR successful."); - - TemporaryBasal tempBasal = new TemporaryBasal(getInjector()) // - .date(System.currentTimeMillis()) // - .duration(0) // - .source(Source.USER); - - // TODO fix - activePlugin.getActiveTreatments().addToHistoryTempBasal(tempBasal); - - return new PumpEnactResult(getInjector()).success(true).enacted(true) // - .isTempCancel(true); - } else { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "cancelTempBasal - Cancel TBR failed."); - - return new PumpEnactResult(getInjector()).success(response).enacted(response) // - .comment(R.string.medtronic_cmd_cant_cancel_tbr); - } - } - - @NonNull @Override - public ManufacturerType manufacturer() { - return pumpDescription.getPumpType().getManufacturer(); - } - - @NonNull @Override - public PumpType model() { - return pumpDescription.getPumpType(); - } - - @NonNull @Override - public String serialNumber() { - return medtronicPumpStatus.getSerialNumber(); - } - - @NonNull @Override - public PumpEnactResult setNewBasalProfile(@NonNull Profile profile) { - aapsLogger.info(LTag.PUMP, getLogPrefix() + "setNewBasalProfile"); - - // this shouldn't be needed, but let's do check if profile setting we are setting is same as current one - if (isProfileSame(profile)) { - return new PumpEnactResult(getInjector()) // - .success(true) // - .enacted(false) // - .comment(R.string.medtronic_cmd_basal_profile_not_set_is_same); - } - - setRefreshButtonEnabled(false); - - if (isPumpNotReachable()) { - - setRefreshButtonEnabled(true); - - return new PumpEnactResult(getInjector()) // - .success(false) // - .enacted(false) // - .comment(R.string.medtronic_pump_status_pump_unreachable); - } - - medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus); - - BasalProfile basalProfile = convertProfileToMedtronicProfile(profile); - - aapsLogger.debug("Basal Profile: " + basalProfile); - - String profileInvalid = isProfileValid(basalProfile); - - if (profileInvalid != null) { - return new PumpEnactResult(getInjector()) // - .success(false) // - .enacted(false) // - .comment(getResourceHelper().gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid)); - } - - MedtronicUITask responseTask = rileyLinkMedtronicService.getMedtronicUIComm().executeCommand(MedtronicCommandType.SetBasalProfileSTD, - Arrays.asList(basalProfile)); - - Boolean response = (Boolean) responseTask.getResult(); - - aapsLogger.info(LTag.PUMP, getLogPrefix() + "Basal Profile was set: " + response); - - if (response) { - return new PumpEnactResult(getInjector()).success(true).enacted(true); - } else { - return new PumpEnactResult(getInjector()).success(response).enacted(response) // - .comment(R.string.medtronic_cmd_basal_profile_could_not_be_set); - } - } - - - private String isProfileValid(BasalProfile basalProfile) { - - StringBuilder stringBuilder = new StringBuilder(); - - if (medtronicPumpStatus.getMaxBasal() == null) - return null; - - for (BasalProfileEntry profileEntry : basalProfile.getEntries()) { - - if (profileEntry.getRate() > medtronicPumpStatus.getMaxBasal()) { - stringBuilder.append(profileEntry.getStartTime().toString("HH:mm")); - stringBuilder.append("="); - stringBuilder.append(profileEntry.getRate()); - } - } - - return stringBuilder.length() == 0 ? null : stringBuilder.toString(); - } - - - @NonNull - private BasalProfile convertProfileToMedtronicProfile(Profile profile) { - - BasalProfile basalProfile = new BasalProfile(aapsLogger); - - for (int i = 0; i < 24; i++) { - double rate = profile.getBasalTimeFromMidnight(i * 60 * 60); - - double v = pumpDescription.getPumpType().determineCorrectBasalSize(rate); - - BasalProfileEntry basalEntry = new BasalProfileEntry(v, i, 0); - basalProfile.addEntry(basalEntry); - - } - - basalProfile.generateRawDataFromEntries(); - - return basalProfile; - } - - // OPERATIONS not supported by Pump or Plugin - - private List customActions = null; - - private final CustomAction customActionWakeUpAndTune = new CustomAction(R.string.medtronic_custom_action_wake_and_tune, - MedtronicCustomActionType.WakeUpAndTune); - - private final CustomAction customActionClearBolusBlock = new CustomAction( - R.string.medtronic_custom_action_clear_bolus_block, MedtronicCustomActionType.ClearBolusBlock, false); - - private final CustomAction customActionResetRLConfig = new CustomAction( - R.string.medtronic_custom_action_reset_rileylink, MedtronicCustomActionType.ResetRileyLinkConfiguration, true); - - - @Override - public List getCustomActions() { - - if (customActions == null) { - this.customActions = Arrays.asList(customActionWakeUpAndTune, // - customActionClearBolusBlock, // - customActionResetRLConfig); - } - - return this.customActions; - } - - - @Override - public void executeCustomAction(@NonNull CustomActionType customActionType) { - - MedtronicCustomActionType mcat = (MedtronicCustomActionType) customActionType; - - switch (mcat) { - - case WakeUpAndTune: { - if (rileyLinkMedtronicService.verifyConfiguration()) { - serviceTaskExecutor.startTask(new WakeAndTuneTask(getInjector())); - } else { - ErrorHelperActivity.Companion.runAlarm(context, getResourceHelper().gs(R.string.medtronic_error_operation_not_possible_no_configuration), getResourceHelper().gs(R.string.medtronic_warning), R.raw.boluserror); - } - } - break; - - case ClearBolusBlock: { - this.busyTimestamps.clear(); - this.customActionClearBolusBlock.setEnabled(false); - refreshCustomActionsList(); - } - break; - - case ResetRileyLinkConfiguration: { - serviceTaskExecutor.startTask(new ResetRileyLinkConfigurationTask(getInjector())); - } - break; - - default: - break; - } - - } - - @Override - public void timezoneOrDSTChanged(@NonNull TimeChangeType changeType) { - - aapsLogger.warn(LTag.PUMP, getLogPrefix() + "Time or TimeZone changed. "); - - this.hasTimeDateOrTimeZoneChanged = true; - } - - @Override - public boolean setNeutralTempAtFullHour() { - return sp.getBoolean(R.string.key_set_neutral_temps, true); - } - - - @SuppressWarnings("SameParameterValue") private void setEnableCustomAction(MedtronicCustomActionType customAction, boolean isEnabled) { - - if (customAction == MedtronicCustomActionType.ClearBolusBlock) { - this.customActionClearBolusBlock.setEnabled(isEnabled); - } else if (customAction == MedtronicCustomActionType.ResetRileyLinkConfiguration) { - this.customActionResetRLConfig.setEnabled(isEnabled); - } - - refreshCustomActionsList(); - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt new file mode 100644 index 0000000000..803f281b45 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -0,0 +1,1179 @@ +package info.nightscout.androidaps.plugins.pump.medtronic + +import android.content.ComponentName +import android.content.Context +import android.content.ServiceConnection +import android.os.IBinder +import android.os.SystemClock +import androidx.preference.Preference +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAlarm +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.data.PumpEnactResult +import info.nightscout.androidaps.db.Source +import info.nightscout.androidaps.db.TemporaryBasal +import info.nightscout.androidaps.events.EventRefreshOverview +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.common.ManufacturerType +import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction +import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract +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.plugins.pump.common.events.EventRefreshButtonState +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpInfo +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile.Companion.getProfilesByHourToString +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfileEntry +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair +import info.nightscout.androidaps.plugins.pump.medtronic.defs.* +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType.Companion.getSettings +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpConfigurationChanged +import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged +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 info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil.Companion.isSame +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.TimeChangeType +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.joda.time.LocalDateTime +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Created by andy on 23.04.18. + * + * @author Andy Rozman (andy.rozman@gmail.com) + */ +@Singleton +class MedtronicPumpPlugin @Inject constructor( + injector: HasAndroidInjector, + aapsLogger: AAPSLogger, + rxBus: RxBusWrapper, + context: Context, + resourceHelper: ResourceHelper, + activePlugin: ActivePlugin, + sp: SP, + commandQueue: CommandQueueProvider, + fabricPrivacy: FabricPrivacy, + private val medtronicUtil: MedtronicUtil, + private val medtronicPumpStatus: MedtronicPumpStatus, + private val medtronicHistoryData: MedtronicHistoryData, + private val rileyLinkServiceData: RileyLinkServiceData, + private val serviceTaskExecutor: ServiceTaskExecutor, + dateUtil: DateUtil, + aapsSchedulers: AapsSchedulers, + pumpSync: PumpSync +) : PumpPluginAbstract(PluginDescription() // + .mainType(PluginType.PUMP) // + .fragmentClass(MedtronicFragment::class.java.name) // + .pluginIcon(R.drawable.ic_veo_128) + .pluginName(R.string.medtronic_name) // + .shortName(R.string.medtronic_name_short) // + .preferencesId(R.xml.pref_medtronic) + .description(R.string.description_pump_medtronic), // + PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later + injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers!!, pumpSync!! +), Pump, RileyLinkPumpDevice { + + private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null + + // variables for handling statuses and history + private var firstRun = true + private var isRefresh = false + private val statusRefreshMap: MutableMap = HashMap() + private var isInitialized = false + private var lastPumpHistoryEntry: PumpHistoryEntry? = null + private val busyTimestamps: MutableList = ArrayList() + private var hasTimeDateOrTimeZoneChanged = false + private val usePumpSync = false + + override fun onStart() { + aapsLogger.debug(LTag.PUMP, deviceID() + " started.") + serviceConnection = object : ServiceConnection { + override fun onServiceDisconnected(name: ComponentName) { + aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is disconnected") + rileyLinkMedtronicService = null + } + + override fun onServiceConnected(name: ComponentName, service: IBinder) { + aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is connected") + val mLocalBinder = service as RileyLinkMedtronicService.LocalBinder + rileyLinkMedtronicService = mLocalBinder.serviceInstance + rileyLinkMedtronicService!!.verifyConfiguration() + Thread(Runnable { + for (i in 0..19) { + SystemClock.sleep(5000) + aapsLogger.debug(LTag.PUMP, "Starting Medtronic-RileyLink service") + if (rileyLinkMedtronicService!!.setNotInPreInit()) { + break + } + } + }).start() + } + } + super.onStart() + } + + override fun updatePreferenceSummary(pref: Preference) { + super.updatePreferenceSummary(pref) + if (pref.key == resourceHelper.gs(R.string.key_rileylink_mac_address)) { + val value = sp.getStringOrNull(R.string.key_rileylink_mac_address, null) + pref.summary = value ?: resourceHelper.gs(R.string.not_set_short) + } + } + + private val logPrefix: String + private get() = "MedtronicPumpPlugin::" + + override fun initPumpStatusData() { + medtronicPumpStatus.lastConnection = sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L) + medtronicPumpStatus.lastDataTime = medtronicPumpStatus.lastConnection + medtronicPumpStatus.previousConnection = medtronicPumpStatus.lastConnection + + //if (rileyLinkMedtronicService != null) rileyLinkMedtronicService.verifyConfiguration(); + aapsLogger.debug(LTag.PUMP, "initPumpStatusData: " + medtronicPumpStatus) + + // this is only thing that can change, by being configured + pumpDescription.maxTempAbsolute = if (medtronicPumpStatus.maxBasal != null) medtronicPumpStatus.maxBasal!! else 35.0 + + // set first Medtronic Pump Start + if (!sp.contains(MedtronicConst.Statistics.FirstPumpStart)) { + sp.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis()) + } + migrateSettings() + } + + override fun triggerPumpConfigurationChangedEvent() { + rxBus.send(EventMedtronicPumpConfigurationChanged()) + } + + private fun migrateSettings() { + if ("US (916 MHz)" == sp.getString(MedtronicConst.Prefs.PumpFrequency, "US (916 MHz)")) { + sp.putString(MedtronicConst.Prefs.PumpFrequency, resourceHelper.gs(R.string.key_medtronic_pump_frequency_us_ca)) + } + val encoding = sp.getString(MedtronicConst.Prefs.Encoding, "RileyLink 4b6b Encoding") + if ("RileyLink 4b6b Encoding" == encoding) { + sp.putString(MedtronicConst.Prefs.Encoding, resourceHelper.gs(R.string.key_medtronic_pump_encoding_4b6b_rileylink)) + } + if ("Local 4b6b Encoding" == encoding) { + sp.putString(MedtronicConst.Prefs.Encoding, resourceHelper.gs(R.string.key_medtronic_pump_encoding_4b6b_local)) + } + } + + override fun onStartCustomActions() { + + // check status every minute (if any status needs refresh we send readStatus command) + Thread(Runnable { + do { + SystemClock.sleep(60000) + if (this.isInitialized) { + val statusRefresh = workWithStatusRefresh( + StatusRefreshAction.GetData, null, null) + if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { + if (!commandQueue.statusInQueue()) { + commandQueue.readStatus("Scheduled Status Refresh", null) + } + } + clearBusyQueue() + } + } while (serviceRunning) + }).start() + } + + override val serviceClass: Class<*> + get() = RileyLinkMedtronicService::class.java + + override val pumpStatusData: PumpStatus + get() = medtronicPumpStatus + + override fun deviceID(): String { + return "Medtronic" + } + + override val isFakingTempsByExtendedBoluses: Boolean + get() = false + + override fun canHandleDST(): Boolean { + return false + } + + // Pump Plugin + private val isServiceSet: Boolean + private get() = rileyLinkMedtronicService != null + + override fun getRileyLinkService(): RileyLinkMedtronicService? { + return rileyLinkMedtronicService + } + + override fun getPumpInfo(): RileyLinkPumpInfo { + val frequency = resourceHelper.gs(if (medtronicPumpStatus.pumpFrequency == "medtronic_pump_frequency_us_ca") R.string.medtronic_pump_frequency_us_ca else R.string.medtronic_pump_frequency_worldwide) + val model = if (medtronicPumpStatus.medtronicDeviceType == null) "???" else "Medtronic " + medtronicPumpStatus.medtronicDeviceType!!.pumpModel + val serialNumber = medtronicPumpStatus.serialNumber + return RileyLinkPumpInfo(frequency, model, serialNumber) + } + + override fun getLastConnectionTimeMillis(): Long { + return medtronicPumpStatus.lastConnection + } + + override fun setLastCommunicationToNow() { + medtronicPumpStatus.setLastCommunicationToNow() + } + + override fun isInitialized(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isInitialized") + return isServiceSet && isInitialized + } + + override fun setBusy(busy: Boolean) { + isBusy = busy + } + + override fun isBusy(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isBusy") + if (isServiceSet) { + if (isBusy) return true + if (busyTimestamps.size > 0) { + clearBusyQueue() + return busyTimestamps.size > 0 + } + } + return false + } + + @Synchronized + private fun clearBusyQueue() { + if (busyTimestamps.size == 0) { + return + } + val deleteFromQueue: MutableSet = HashSet() + for (busyTimestamp in busyTimestamps) { + if (System.currentTimeMillis() > busyTimestamp) { + deleteFromQueue.add(busyTimestamp) + } + } + if (deleteFromQueue.size == busyTimestamps.size) { + busyTimestamps.clear() + setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, false) + } + if (deleteFromQueue.size > 0) { + busyTimestamps.removeAll(deleteFromQueue) + } + } + + override fun isConnected(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnected") + return isServiceSet && rileyLinkMedtronicService!!.isInitialized + } + + override fun isConnecting(): Boolean { + if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnecting") + return !isServiceSet || !rileyLinkMedtronicService!!.isInitialized + } + + override fun getPumpStatus(reason: String) { + var needRefresh = true + if (firstRun) { + needRefresh = initializePump(!isRefresh) + } else { + refreshAnyStatusThatNeedsToBeRefreshed() + } + if (needRefresh) rxBus.send(EventMedtronicPumpValuesChanged()) + } + + fun resetStatusState() { + firstRun = true + isRefresh = true + }// + + private val isPumpNotReachable: Boolean + private get() { + val rileyLinkServiceState = rileyLinkServiceData.rileyLinkServiceState + if (rileyLinkServiceState == null) { + aapsLogger.debug(LTag.PUMP, "RileyLink unreachable. RileyLinkServiceState is null.") + return false + } + if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady // + && rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady // + && rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice) { + aapsLogger.debug(LTag.PUMP, "RileyLink unreachable.") + return false + } + return !rileyLinkMedtronicService!!.deviceCommunicationManager.isDeviceReachable + } + + private fun refreshAnyStatusThatNeedsToBeRefreshed() { + val statusRefresh = workWithStatusRefresh(StatusRefreshAction.GetData, null, + null) + if (!doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { + return + } + var resetTime = false + if (isPumpNotReachable) { + aapsLogger.error("Pump unreachable.") + medtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable, resourceHelper, rxBus) + return + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + if (hasTimeDateOrTimeZoneChanged) { + checkTimeAndOptionallySetTime() + + // read time if changed, set new time + hasTimeDateOrTimeZoneChanged = false + } + + // execute + val refreshTypesNeededToReschedule: MutableSet = HashSet() + for ((key, value) in statusRefresh!!) { + if (value!! > 0 && System.currentTimeMillis() > value) { + when (key) { + MedtronicStatusRefreshType.PumpHistory -> { + readPumpHistory() + } + + MedtronicStatusRefreshType.PumpTime -> { + checkTimeAndOptionallySetTime() + refreshTypesNeededToReschedule.add(key) + resetTime = true + } + + MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.RemainingInsulin -> { + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + refreshTypesNeededToReschedule.add(key) + resetTime = true + } + + MedtronicStatusRefreshType.Configuration -> { + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + resetTime = true + } + } + } + + // reschedule + for (refreshType2 in refreshTypesNeededToReschedule) { + scheduleNextRefresh(refreshType2) + } + } + + if (resetTime) medtronicPumpStatus.setLastCommunicationToNow() + } + + private fun doWeHaveAnyStatusNeededRefereshing(statusRefresh: Map?): Boolean { + for ((_, value) in statusRefresh!!) { + if (value!! > 0 && System.currentTimeMillis() > value) { + return true + } + } + return hasTimeDateOrTimeZoneChanged + } + + private fun setRefreshButtonEnabled(enabled: Boolean) { + rxBus.send(EventRefreshButtonState(enabled)) + } + + private fun initializePump(realInit: Boolean): Boolean { + if (rileyLinkMedtronicService == null) return false + aapsLogger.info(LTag.PUMP, logPrefix + "initializePump - start") + rileyLinkMedtronicService!!.deviceCommunicationManager.setDoWakeUpBeforeCommand(false) + setRefreshButtonEnabled(false) + if (isRefresh) { + if (isPumpNotReachable) { + aapsLogger.error(logPrefix + "initializePump::Pump unreachable.") + medtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable, resourceHelper, rxBus) + setRefreshButtonEnabled(true) + return true + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + } + + // model (once) + if (medtronicUtil.medtronicPumpModel == null) { + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.PumpModel) + } else { + if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) { + aapsLogger.warn(LTag.PUMP, logPrefix + "Configured pump is not the same as one detected.") + medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, resourceHelper, rxBus) + } + } + pumpState = PumpDriverState.Connected + + // time (1h) + checkTimeAndOptionallySetTime() + readPumpHistory() + + // remaining insulin (>50 = 4h; 50-20 = 1h; 15m) + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetRemainingInsulin) + scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10) + + // remaining power (1h) + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetBatteryStatus) + scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20) + + // configuration (once and then if history shows config changes) + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) + + // read profile (once, later its controlled by isThisProfileSet method) + basalProfiles + val errorCount = rileyLinkMedtronicService!!.medtronicUIComm!!.invalidResponsesCount + if (errorCount >= 5) { + aapsLogger.error("Number of error counts was 5 or more. Starting tunning.") + setRefreshButtonEnabled(true) + serviceTaskExecutor.startTask(WakeAndTuneTask(injector)) + return true + } + medtronicPumpStatus.setLastCommunicationToNow() + setRefreshButtonEnabled(true) + if (!isRefresh) { + pumpState = PumpDriverState.Initialized + } + isInitialized = true + // this.pumpState = PumpDriverState.Initialized; + firstRun = false + return true + } + + private val basalProfiles: Unit + private get() { + val medtronicUITask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + if (medtronicUITask.responseType === MedtronicUIResponseType.Error) { + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + } + } + + override fun isThisProfileSet(profile: Profile): Boolean { + aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.basalProfileStatus) + if (!isInitialized) return true + if (medtronicPumpStatus.basalProfileStatus === BasalProfileStatus.NotInitialized) { + // this shouldn't happen, but if there was problem we try again + basalProfiles + return isProfileSame(profile) + } else if (medtronicPumpStatus.basalProfileStatus === BasalProfileStatus.ProfileChanged) { + return false + } + return medtronicPumpStatus.basalProfileStatus !== BasalProfileStatus.ProfileOK || isProfileSame(profile) + } + + private fun isProfileSame(profile: Profile): Boolean { + var invalid = false + val basalsByHour: Array? = medtronicPumpStatus.basalsByHour + aapsLogger.debug(LTag.PUMP, "Current Basals (h): " + + (basalsByHour?.let { getProfilesByHourToString(it) } ?: "null")) + + // int index = 0; + if (basalsByHour == null) return true // we don't want to set profile again, unless we are sure + val stringBuilder = StringBuilder("Requested Basals (h): ") + for (basalValue in profile.basalValues) { + val basalValueValue = pumpDescription.pumpType.determineCorrectBasalSize(basalValue.value) + val hour = basalValue.timeAsSeconds / (60 * 60) + if (!isSame(basalsByHour[hour]!!, basalValueValue)) { + invalid = true + } + stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) + stringBuilder.append(" ") + } + aapsLogger.debug(LTag.PUMP, stringBuilder.toString()) + if (!invalid) { + aapsLogger.debug(LTag.PUMP, "Basal profile is same as AAPS one.") + } else { + aapsLogger.debug(LTag.PUMP, "Basal profile on Pump is different than the AAPS one.") + } + return !invalid + } + + override fun lastDataTime(): Long { + return if (medtronicPumpStatus.lastConnection > 0) { + medtronicPumpStatus.lastConnection + } else System.currentTimeMillis() + } + + override val baseBasalRate: Double + get() = medtronicPumpStatus.basalProfileForHour + + override val reservoirLevel: Double + get() = medtronicPumpStatus.reservoirRemainingUnits + + override val batteryLevel: Int + get() = medtronicPumpStatus.batteryRemaining + + override fun triggerUIChange() { + rxBus.send(EventMedtronicPumpValuesChanged()) + } + + override fun generateTempId(timeMillis: Long): Long { + return 0 + } + + // @Override public String getSerial() { + // return null; + // } + private var bolusDeliveryType = BolusDeliveryType.Idle + + private enum class BolusDeliveryType { + Idle, // + DeliveryPrepared, // + Delivering, // + CancelDelivery + } + + private fun checkTimeAndOptionallySetTime() { + aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Start") + setRefreshButtonEnabled(false) + if (isPumpNotReachable) { + aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Pump Unreachable.") + setRefreshButtonEnabled(true) + return + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetRealTimeClock) + var clock = medtronicUtil.pumpTime + if (clock == null) { // retry + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetRealTimeClock) + clock = medtronicUtil.pumpTime + } + if (clock == null) return + val timeDiff = Math.abs(clock.timeDifference) + if (timeDiff > 20) { + if (clock.localDeviceTime!!.year <= 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)) + rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetRealTimeClock) + if (clock.timeDifference == 0) { + val notification = Notification(Notification.INSIGHT_DATE_TIME_UPDATED, resourceHelper.gs(R.string.pump_time_updated), Notification.INFO, 60) + rxBus.send(EventNewNotification(notification)) + } + } else { + if (clock.localDeviceTime!!.year > 2015) { + aapsLogger.error(String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference over 24h requested [diff=%d s]. Doing nothing.", timeDiff)) + medtronicUtil.sendNotification(MedtronicNotificationType.TimeChangeOver24h, resourceHelper, rxBus) + } + } + } else { + aapsLogger.info(LTag.PUMP, String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference is %d s. Do nothing.", timeDiff)) + } + scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0) + } + + override fun deliverBolus(detailedBolusInfo: DetailedBolusInfo?): PumpEnactResult { + aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - " + BolusDeliveryType.DeliveryPrepared) + setRefreshButtonEnabled(false) + if (detailedBolusInfo!!.insulin > medtronicPumpStatus.reservoirRemainingUnits) { + return PumpEnactResult(injector) // + .success(false) // + .enacted(false) // + .comment(resourceHelper.gs(R.string.medtronic_cmd_bolus_could_not_be_delivered_no_insulin, + medtronicPumpStatus.reservoirRemainingUnits, + detailedBolusInfo.insulin)) + } + bolusDeliveryType = BolusDeliveryType.DeliveryPrepared + if (isPumpNotReachable) { + aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - Pump Unreachable.") + return setNotReachable(true, false) + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled."); + return setNotReachable(true, true) + } + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Starting wait period."); + val sleepTime = sp.getInt(MedtronicConst.Prefs.BolusDelay, 10) * 1000 + SystemClock.sleep(sleepTime.toLong()) + return if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled, before wait period."); + setNotReachable(true, true) + } else try { + bolusDeliveryType = BolusDeliveryType.Delivering + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetBolus, + Arrays.asList(detailedBolusInfo.insulin)) + val response = responseTask.result as Boolean? + setRefreshButtonEnabled(true) + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Response: {}", response); + if (response!!) { + if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled after Bolus started."); + Thread(Runnable { + + // Looper.prepare(); + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog - before"); + SystemClock.sleep(2000) + // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog. Context: " + // + MainApp.instance().getApplicationContext()); + runAlarm(context, resourceHelper.gs(R.string.medtronic_cmd_cancel_bolus_not_supported), resourceHelper.gs(R.string.medtronic_warning), R.raw.boluserror) + }).start() + } + val now = System.currentTimeMillis() + detailedBolusInfo.timestamp = now + detailedBolusInfo.deliverAtTheLatest = now // not sure about that one + + // TODO fix + if (usePumpSync) { + addBolusWithTempId(detailedBolusInfo, true) + } else { + activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) + } + + // we subtract insulin, exact amount will be visible with next remainingInsulin update. + medtronicPumpStatus.reservoirRemainingUnits = medtronicPumpStatus.reservoirRemainingUnits - detailedBolusInfo.insulin + incrementStatistics(if (detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) MedtronicConst.Statistics.SMBBoluses else MedtronicConst.Statistics.StandardBoluses) + + // calculate time for bolus and set driver to busy for that time + val bolusTime = (detailedBolusInfo.insulin * 42.0).toInt() + val time = now + bolusTime * 1000 + busyTimestamps.add(time) + setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, true) + PumpEnactResult(injector).success(true) // + .enacted(true) // + .bolusDelivered(detailedBolusInfo.insulin) // + .carbsDelivered(detailedBolusInfo.carbs) + } else { + PumpEnactResult(injector) // + .success(bolusDeliveryType == BolusDeliveryType.CancelDelivery) // + .enacted(false) // + .comment(R.string.medtronic_cmd_bolus_could_not_be_delivered) + } + } finally { + finishAction("Bolus") + bolusDeliveryType = BolusDeliveryType.Idle + } + + // LOG.debug("MedtronicPumpPlugin::deliverBolus - End wait period. Start delivery"); + } + + private fun setNotReachable(isBolus: Boolean, success: Boolean): PumpEnactResult { + setRefreshButtonEnabled(true) + if (isBolus) { + bolusDeliveryType = BolusDeliveryType.Idle + } + return if (success) { + PumpEnactResult(injector) // + .success(true) // + .enacted(false) + } else { + PumpEnactResult(injector) // + .success(false) // + .enacted(false) // + .comment(R.string.medtronic_pump_status_pump_unreachable) + } + } + + override fun stopBolusDelivering() { + bolusDeliveryType = BolusDeliveryType.CancelDelivery + + // if (isLoggingEnabled()) + // LOG.warn("MedtronicPumpPlugin::deliverBolus - Stop Bolus Delivery."); + } + + private fun incrementStatistics(statsKey: String) { + var currentCount = sp.getLong(statsKey, 0L) + currentCount++ + sp.putLong(statsKey, currentCount) + } + + // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged), + // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed + override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { + setRefreshButtonEnabled(false) + if (isPumpNotReachable) { + setRefreshButtonEnabled(true) + return PumpEnactResult(injector) // + .success(false) // + .enacted(false) // + .comment(R.string.medtronic_pump_status_pump_unreachable) + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute: rate: " + absoluteRate + ", duration=" + durationInMinutes) + + // read current TBR + val tbrCurrent = readTBR() + if (tbrCurrent == null) { + aapsLogger.warn(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Could not read current TBR, canceling operation.") + finishAction("TBR") + return PumpEnactResult(injector).success(false).enacted(false) + .comment(R.string.medtronic_cmd_cant_read_tbr) + } else { + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute: Current Basal: duration: " + tbrCurrent.durationMinutes + " min, rate=" + tbrCurrent.insulinRate) + } + if (!enforceNew) { + if (isSame(tbrCurrent.insulinRate, absoluteRate)) { + var sameRate = true + if (isSame(0.0, absoluteRate) && durationInMinutes > 0) { + // if rate is 0.0 and duration>0 then the rate is not the same + sameRate = false + } + if (sameRate) { + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - No enforceNew and same rate. Exiting.") + finishAction("TBR") + return PumpEnactResult(injector).success(true).enacted(false) + } + } + // if not the same rate, we cancel and start new + } + + // if TBR is running we will cancel it. + if (tbrCurrent.insulinRate > 0.0 && tbrCurrent.durationMinutes > 0) { + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - TBR running - so canceling it.") + + // CANCEL + val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.CancelTBR) + val response = responseTask2.result as Boolean? + if (response!!) { + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") + } else { + aapsLogger.error(logPrefix + "setTempBasalAbsolute - Cancel TBR failed.") + finishAction("TBR") + return PumpEnactResult(injector).success(false).enacted(false) + .comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op) + } + } + + // now start new TBR + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetTemporaryBasal, + Arrays.asList(absoluteRate, durationInMinutes)) + val response = responseTask.result as Boolean? + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - setTBR. Response: " + response) + return if (response!!) { + // FIXME put this into UIPostProcessor + medtronicPumpStatus.tempBasalStart = Date() + medtronicPumpStatus.tempBasalAmount = absoluteRate + medtronicPumpStatus.tempBasalLength = durationInMinutes + val tempStart = TemporaryBasal(injector) // + .date(System.currentTimeMillis()) // + .duration(durationInMinutes) // + .absolute(absoluteRate) // + .source(Source.USER) + + // TODO fix + if (usePumpSync) { + addTemporaryBasalRateWithTempId(tempStart, true) + } else { + activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) + } + incrementStatistics(MedtronicConst.Statistics.TBRsSet) + finishAction("TBR") + PumpEnactResult(injector).success(true).enacted(true) // + .absolute(absoluteRate).duration(durationInMinutes) + } else { + finishAction("TBR") + PumpEnactResult(injector).success(false).enacted(false) // + .comment(R.string.medtronic_cmd_tbr_could_not_be_delivered) + } + } + + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { + return if (percent == 0) { + setTempBasalAbsolute(0.0, durationInMinutes, profile, enforceNew, tbrType) + } else { + var absoluteValue = profile.basal * (percent / 100.0) + absoluteValue = pumpDescription.pumpType.determineCorrectBasalSize(absoluteValue) + aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [MedtronicPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% ($percent). This will start setTempBasalAbsolute, with calculated value ($absoluteValue). Result might not be 100% correct.") + setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew, tbrType) + } + } + + private fun finishAction(overviewKey: String?) { + if (overviewKey != null) rxBus.send(EventRefreshOverview(overviewKey, false)) + triggerUIChange() + setRefreshButtonEnabled(true) + } + + private fun readPumpHistory() { + +// if (isLoggingEnabled()) +// LOG.error(getLogPrefix() + "readPumpHistory WIP."); + readPumpHistoryLogic() + scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory) + if (medtronicHistoryData.hasRelevantConfigurationChanged()) { + scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1) + } + if (medtronicHistoryData.hasPumpTimeChanged()) { + scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1) + } + if (medtronicPumpStatus.basalProfileStatus !== BasalProfileStatus.NotInitialized + && medtronicHistoryData.hasBasalProfileChanged()) { + medtronicHistoryData.processLastBasalProfileChange(pumpDescription.pumpType, medtronicPumpStatus) + } + val previousState = pumpState + if (medtronicHistoryData.isPumpSuspended) { + pumpState = PumpDriverState.Suspended + aapsLogger.debug(LTag.PUMP, logPrefix + "isPumpSuspended: true") + } else { + if (previousState === PumpDriverState.Suspended) { + pumpState = PumpDriverState.Ready + } + aapsLogger.debug(LTag.PUMP, logPrefix + "isPumpSuspended: false") + } + medtronicHistoryData.processNewHistoryData() + medtronicHistoryData.finalizeNewHistoryRecords() + // this.medtronicHistoryData.setLastHistoryRecordTime(this.lastPumpHistoryEntry.atechDateTime); + } + + private fun readPumpHistoryLogic() { + + val debugHistory = false + var targetDate: LocalDateTime? = null + if (lastPumpHistoryEntry == null) { + if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntry: null") + val lastPumpHistoryEntryTime = lastPumpEntryTime + var timeMinus36h = LocalDateTime() + timeMinus36h = timeMinus36h.minusHours(36) + medtronicHistoryData.setIsInInit(true) + if (lastPumpHistoryEntryTime == 0L) { + if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: 0L - targetDate: " + + targetDate) + targetDate = timeMinus36h + } else { + // LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); + if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: " + lastPumpHistoryEntryTime + " - targetDate: " + targetDate) + medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntryTime) + var lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime) + lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12) // we get last 12 hours of history to + // determine pump state + // (we don't process that data), we process only + if (timeMinus36h.isAfter(lastHistoryRecordTime)) { + targetDate = timeMinus36h + } + targetDate = if (timeMinus36h.isAfter(lastHistoryRecordTime)) timeMinus36h else lastHistoryRecordTime + if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): targetDate: " + targetDate) + } + } else { + if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.gsonInstance.toJson(lastPumpHistoryEntry)) + medtronicHistoryData.setIsInInit(false) + // medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime); + + // targetDate = lastPumpHistoryEntry.atechDateTime; + } + + //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); + val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetHistoryData, + Arrays.asList(lastPumpHistoryEntry, targetDate) as List?) + if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task") + val historyResult = responseTask2.result as PumpHistoryResult? + if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString()) + val latestEntry = historyResult!!.latestEntry + if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "Last entry: " + latestEntry) + if (latestEntry == null) // no new history to read + return + lastPumpHistoryEntry = latestEntry + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.atechDateTime!!) + if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History: valid=" + historyResult.validEntries.size + ", unprocessed=" + historyResult.unprocessedEntries.size) + medtronicHistoryData.addNewHistory(historyResult) + medtronicHistoryData.filterNewEntries() + + // determine if first run, if yes detrmine how much of update do we need + // first run: + // get last hiostory entry, if not there download 1.5 days of data + // - there: check if last entry is older than 1.5 days + // - yes: download 1.5 days + // - no: download with last entry + // - not there: download 1.5 days + // + // upload all new entries to NightScout (TBR, Bolus) + // determine pump status + // + // save last entry + // + // not first run: + // update to last entry + // - save + // - determine pump status + } + + private val lastPumpEntryTime: Long + private get() { + val lastPumpEntryTime = sp.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, 0L) + return try { + val localDateTime = DateTimeUtil.toLocalDateTime(lastPumpEntryTime) + if (localDateTime.year != GregorianCalendar()[Calendar.YEAR]) { + aapsLogger.warn(LTag.PUMP, "Saved LastPumpHistoryEntry was invalid. Year was not the same.") + return 0L + } + lastPumpEntryTime + } catch (ex: Exception) { + aapsLogger.warn(LTag.PUMP, "Saved LastPumpHistoryEntry was invalid.") + 0L + } + } + + private fun scheduleNextRefresh(refreshType: MedtronicStatusRefreshType?, additionalTimeInMinutes: Int = 0) { + when (refreshType) { + MedtronicStatusRefreshType.RemainingInsulin -> { + val remaining = medtronicPumpStatus.reservoirRemainingUnits + val min: Int + min = if (remaining > 50) 4 * 60 else if (remaining > 20) 60 else 15 + workWithStatusRefresh(StatusRefreshAction.Add, refreshType, getTimeInFutureFromMinutes(min)) + } + + MedtronicStatusRefreshType.PumpTime, MedtronicStatusRefreshType.Configuration, MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.PumpHistory -> { + workWithStatusRefresh(StatusRefreshAction.Add, refreshType, + getTimeInFutureFromMinutes(refreshType.refreshTime + additionalTimeInMinutes)) + } + } + } + + private enum class StatusRefreshAction { + Add, // + GetData + } + + @Synchronized + private fun workWithStatusRefresh(action: StatusRefreshAction, // + statusRefreshType: MedtronicStatusRefreshType?, // + time: Long?): Map? { + return when (action) { + StatusRefreshAction.Add -> { + statusRefreshMap[statusRefreshType] = time + null + } + + StatusRefreshAction.GetData -> { + HashMap(statusRefreshMap) + } + + else -> null + } + } + + private fun getTimeInFutureFromMinutes(minutes: Int): Long { + return System.currentTimeMillis() + getTimeInMs(minutes) + } + + private fun getTimeInMs(minutes: Int): Long { + return minutes * 60 * 1000L + } + + private fun readTBR(): TempBasalPair? { + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.ReadTemporaryBasal) + return if (responseTask.hasData()) { + val tbr = responseTask.result as TempBasalPair? + + // we sometimes get rate returned even if TBR is no longer running + if (tbr!!.durationMinutes == 0) { + tbr.insulinRate = 0.0 + } + tbr + } else { + null + } + } + + override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - started") + if (isPumpNotReachable) { + setRefreshButtonEnabled(true) + return PumpEnactResult(injector) // + .success(false) // + .enacted(false) // + .comment(R.string.medtronic_pump_status_pump_unreachable) + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + setRefreshButtonEnabled(false) + val tbrCurrent = readTBR() + if (tbrCurrent != null) { + if (tbrCurrent.insulinRate > 0.0f && tbrCurrent.durationMinutes == 0) { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - TBR already canceled.") + finishAction("TBR") + return PumpEnactResult(injector).success(true).enacted(false) + } + } else { + aapsLogger.warn(LTag.PUMP, logPrefix + "cancelTempBasal - Could not read currect TBR, canceling operation.") + finishAction("TBR") + return PumpEnactResult(injector).success(false).enacted(false) + .comment(R.string.medtronic_cmd_cant_read_tbr) + } + val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.CancelTBR) + val response = responseTask2.result as Boolean? + finishAction("TBR") + return if (response!!) { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR successful.") + val tempBasal = TemporaryBasal(injector) // + .date(System.currentTimeMillis()) // + .duration(0) // + .source(Source.USER) + + // TODO fix + activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) + PumpEnactResult(injector).success(true).enacted(true) // + .isTempCancel(true) + } else { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR failed.") + PumpEnactResult(injector).success(response).enacted(response) // + .comment(R.string.medtronic_cmd_cant_cancel_tbr) + } + } + + override fun manufacturer(): ManufacturerType { + return pumpDescription.pumpType.manufacturer!! + } + + override fun model(): PumpType { + return pumpDescription.pumpType + } + + override fun serialNumber(): String { + return medtronicPumpStatus.serialNumber!! + } + + override fun setNewBasalProfile(profile: Profile): PumpEnactResult { + aapsLogger.info(LTag.PUMP, logPrefix + "setNewBasalProfile") + + // this shouldn't be needed, but let's do check if profile setting we are setting is same as current one + if (isProfileSame(profile)) { + return PumpEnactResult(injector) // + .success(true) // + .enacted(false) // + .comment(R.string.medtronic_cmd_basal_profile_not_set_is_same) + } + setRefreshButtonEnabled(false) + if (isPumpNotReachable) { + setRefreshButtonEnabled(true) + return PumpEnactResult(injector) // + .success(false) // + .enacted(false) // + .comment(R.string.medtronic_pump_status_pump_unreachable) + } + medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) + val basalProfile = convertProfileToMedtronicProfile(profile) + aapsLogger.debug("Basal Profile: $basalProfile") + val profileInvalid = isProfileValid(basalProfile) + if (profileInvalid != null) { + return PumpEnactResult(injector) // + .success(false) // + .enacted(false) // + .comment(resourceHelper.gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid)) + } + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetBasalProfileSTD, + Arrays.asList(basalProfile)) + val response = responseTask.result as Boolean? + aapsLogger.info(LTag.PUMP, logPrefix + "Basal Profile was set: " + response) + return if (response!!) { + PumpEnactResult(injector).success(true).enacted(true) + } else { + PumpEnactResult(injector).success(response).enacted(response) // + .comment(R.string.medtronic_cmd_basal_profile_could_not_be_set) + } + } + + private fun isProfileValid(basalProfile: BasalProfile): String? { + val stringBuilder = StringBuilder() + if (medtronicPumpStatus.maxBasal == null) return null + for (profileEntry in basalProfile.entries) { + if (profileEntry.rate > medtronicPumpStatus.maxBasal!!) { + stringBuilder.append(profileEntry.startTime!!.toString("HH:mm")) + stringBuilder.append("=") + stringBuilder.append(profileEntry.rate) + } + } + return if (stringBuilder.length == 0) null else stringBuilder.toString() + } + + private fun convertProfileToMedtronicProfile(profile: Profile): BasalProfile { + val basalProfile = BasalProfile(aapsLogger) + for (i in 0..23) { + val rate = profile.getBasalTimeFromMidnight(i * 60 * 60) + val v = pumpDescription.pumpType.determineCorrectBasalSize(rate) + val basalEntry = BasalProfileEntry(v, i, 0) + basalProfile.addEntry(basalEntry) + } + basalProfile.generateRawDataFromEntries() + return basalProfile + } + + // OPERATIONS not supported by Pump or Plugin + private var customActions: List? = null + private val customActionWakeUpAndTune = CustomAction(R.string.medtronic_custom_action_wake_and_tune, + MedtronicCustomActionType.WakeUpAndTune) + private val customActionClearBolusBlock = CustomAction( + R.string.medtronic_custom_action_clear_bolus_block, MedtronicCustomActionType.ClearBolusBlock, false) + private val customActionResetRLConfig = CustomAction( + R.string.medtronic_custom_action_reset_rileylink, MedtronicCustomActionType.ResetRileyLinkConfiguration, true) + + override fun getCustomActions(): List? { + if (customActions == null) { + customActions = Arrays.asList(customActionWakeUpAndTune, // + customActionClearBolusBlock, // + customActionResetRLConfig) + } + return customActions + } + + override fun executeCustomAction(customActionType: CustomActionType) { + val mcat = customActionType as MedtronicCustomActionType + when (mcat) { + MedtronicCustomActionType.WakeUpAndTune -> { + if (rileyLinkMedtronicService!!.verifyConfiguration()) { + serviceTaskExecutor.startTask(WakeAndTuneTask(injector)) + } else { + runAlarm(context, resourceHelper.gs(R.string.medtronic_error_operation_not_possible_no_configuration), resourceHelper.gs(R.string.medtronic_warning), R.raw.boluserror) + } + } + + MedtronicCustomActionType.ClearBolusBlock -> { + busyTimestamps.clear() + customActionClearBolusBlock.isEnabled = false + refreshCustomActionsList() + } + + MedtronicCustomActionType.ResetRileyLinkConfiguration -> { + serviceTaskExecutor.startTask(ResetRileyLinkConfigurationTask(injector)) + } + + else -> { + } + } + } + + override fun timezoneOrDSTChanged(changeType: TimeChangeType) { + aapsLogger.warn(LTag.PUMP, logPrefix + "Time or TimeZone changed. ") + hasTimeDateOrTimeZoneChanged = true + } + + override fun setNeutralTempAtFullHour(): Boolean { + return sp.getBoolean(R.string.key_set_neutral_temps, true) + } + + private fun setEnableCustomAction(customAction: MedtronicCustomActionType, isEnabled: Boolean) { + if (customAction === MedtronicCustomActionType.ClearBolusBlock) { + customActionClearBolusBlock.isEnabled = isEnabled + } else if (customAction === MedtronicCustomActionType.ResetRileyLinkConfiguration) { + customActionResetRLConfig.isEnabled = isEnabled + } + refreshCustomActionsList() + } + + companion object { + var isBusy = false + } + + init { + displayConnectionMessages = false + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java index 7773f28ba7..4e855dafa3 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java @@ -599,6 +599,44 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager } + private T sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData, Class clazz) { + + aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: " + commandType); + + for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { + + try { + PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); + + String check = checkResponseContent(response, commandType.getCommandDescription(), commandType.getExpectedLength()); + + if (check == null) { + + T dataResponse = (T)medtronicConverter.convertResponse(medtronicPumpPlugin.getPumpDescription().getPumpType(), commandType, response.getRawContent()); + + if (dataResponse != null) { + this.errorMessage = null; + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name(), dataResponse)); + + return dataResponse; + } else { + this.errorMessage = "Error decoding response."; + } + } else { + this.errorMessage = check; + // return null; + } + + } catch (RileyLinkCommunicationException e) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.getMessage(), retries + 1)); + } + + } + + return null; + } + + private String checkResponseContent(PumpMessage response, String method, int expectedLength) { if (!response.isValid()) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt index 489e2b2c36..92720b72f2 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -32,7 +32,8 @@ class BasalProfile { private val aapsLogger: AAPSLogger - @Expose var rawData : ByteArray? = null // store as byte array to make transport (via parcel) easier + @Expose + lateinit var rawData : ByteArray // store as byte array to make transport (via parcel) easier private set private var listEntries: MutableList? = null @@ -48,14 +49,11 @@ class BasalProfile { } fun init() { - rawData = ByteArray(MAX_RAW_DATA_SIZE) - rawData!![0] = 0 - rawData!![1] = 0 - rawData!![2] = 0x3f + rawData = byteArrayOf(0,0,0x3f) } private fun setRawData(data: ByteArray): Boolean { - var dataInternal: ByteArray? = data + var dataInternal: ByteArray = data if (dataInternal == null) { aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") return false @@ -81,17 +79,16 @@ class BasalProfile { return false } rawData = ByteArray(MAX_RAW_DATA_SIZE) - val item = 0 var i = 0 while (i < data.size - 2) { if (data[i] == 0.toByte() && data[i + 1] == 0.toByte() && data[i + 2] == 0.toByte()) { - rawData!![i] = 0 - rawData!![i + 1] = 0 - rawData!![i + 2] = 0 + rawData[i] = 0 + rawData[i + 1] = 0 + rawData[i + 2] = 0 } - rawData!![i] = data[i + 1] - rawData!![i + 1] = data[i + 2] - rawData!![i + 2] = data[i] + rawData[i] = data[i + 1] + rawData[i + 1] = data[i + 2] + rawData[i + 2] = data[i] i += 3 } return true @@ -306,7 +303,7 @@ class BasalProfile { } @JvmStatic - fun getProfilesByHourToString(data: Array): String { + fun getProfilesByHourToString(data: Array): String { val stringBuilder = StringBuilder() for (value in data) { stringBuilder.append(String.format("%.3f", value)) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java deleted file mode 100644 index fc986f4f83..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.java +++ /dev/null @@ -1,250 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.dialog; - -import android.os.Bundle; -import android.os.SystemClock; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Spinner; -import android.widget.TextView; - -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup; -import info.nightscout.androidaps.plugins.pump.medtronic.R; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; -import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; -import info.nightscout.androidaps.utils.resources.ResourceHelper; - - -public class MedtronicHistoryActivity extends NoSplashAppCompatActivity { - - @Inject MedtronicHistoryData medtronicHistoryData; - @Inject ResourceHelper resourceHelper; - - Spinner historyTypeSpinner; - TextView statusView; - RecyclerView recyclerView; - LinearLayoutManager llm; - - static TypeList showingType = null; - static PumpHistoryEntryGroup selectedGroup = PumpHistoryEntryGroup.All; - List filteredHistoryList = new ArrayList<>(); - - RecyclerViewAdapter recyclerViewAdapter; - boolean manualChange = false; - - List typeListFull; - - - private void filterHistory(PumpHistoryEntryGroup group) { - - this.filteredHistoryList.clear(); - - List list = new ArrayList<>(); - list.addAll(medtronicHistoryData.getAllHistory()); - - //LOG.debug("Items on full list: {}", list.size()); - - if (group == PumpHistoryEntryGroup.All) { - this.filteredHistoryList.addAll(list); - } else { - for (PumpHistoryEntry pumpHistoryEntry : list) { - if (pumpHistoryEntry.getEntryType().getGroup() == group) { - this.filteredHistoryList.add(pumpHistoryEntry); - } - } - } - - if (this.recyclerViewAdapter != null) { - this.recyclerViewAdapter.setHistoryList(this.filteredHistoryList); - this.recyclerViewAdapter.notifyDataSetChanged(); - } - - //LOG.debug("Items on filtered list: {}", filteredHistoryList.size()); - } - - - @Override - protected void onResume() { - super.onResume(); - filterHistory(selectedGroup); - setHistoryTypeSpinner(); - } - - - private void setHistoryTypeSpinner() { - this.manualChange = true; - - for (int i = 0; i < typeListFull.size(); i++) { - if (typeListFull.get(i).entryGroup == selectedGroup) { - historyTypeSpinner.setSelection(i); - break; - } - } - - SystemClock.sleep(200); - this.manualChange = false; - } - - - @Override - protected void onPause() { - super.onPause(); - } - - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.medtronic_history_activity); - - historyTypeSpinner = findViewById(R.id.medtronic_historytype); - statusView = findViewById(R.id.medtronic_historystatus); - recyclerView = findViewById(R.id.medtronic_history_recyclerview); - - recyclerView.setHasFixedSize(true); - llm = new LinearLayoutManager(this); - recyclerView.setLayoutManager(llm); - - recyclerViewAdapter = new RecyclerViewAdapter(filteredHistoryList); - recyclerView.setAdapter(recyclerViewAdapter); - - statusView.setVisibility(View.GONE); - - typeListFull = getTypeList(PumpHistoryEntryGroup.getTranslatedList(resourceHelper)); - - ArrayAdapter spinnerAdapter = new ArrayAdapter<>(this, R.layout.spinner_centered, typeListFull); - historyTypeSpinner.setAdapter(spinnerAdapter); - - historyTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - if (manualChange) - return; - TypeList selected = (TypeList) historyTypeSpinner.getSelectedItem(); - showingType = selected; - selectedGroup = selected.entryGroup; - filterHistory(selectedGroup); - } - - - @Override - public void onNothingSelected(AdapterView parent) { - if (manualChange) - return; - filterHistory(PumpHistoryEntryGroup.All); - } - }); - - } - - - private List getTypeList(List list) { - - ArrayList typeList = new ArrayList<>(); - - for (PumpHistoryEntryGroup pumpHistoryEntryGroup : list) { - typeList.add(new TypeList(pumpHistoryEntryGroup)); - } - - return typeList; - } - - public static class TypeList { - - PumpHistoryEntryGroup entryGroup; - String name; - - - TypeList(PumpHistoryEntryGroup entryGroup) { - this.entryGroup = entryGroup; - this.name = entryGroup.getTranslated(); - } - - - @Override - public String toString() { - return name; - } - } - - public static class RecyclerViewAdapter extends RecyclerView.Adapter { - - List historyList; - - - RecyclerViewAdapter(List historyList) { - this.historyList = historyList; - } - - - public void setHistoryList(List historyList) { - // this.historyList.clear(); - // this.historyList.addAll(historyList); - - this.historyList = historyList; - - // this.notifyDataSetChanged(); - } - - - @Override - public HistoryViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.medtronic_history_item, // - viewGroup, false); - return new HistoryViewHolder(v); - } - - - @Override - public void onBindViewHolder(HistoryViewHolder holder, int position) { - PumpHistoryEntry record = historyList.get(position); - - if (record != null) { - holder.timeView.setText(record.getDateTimeString()); - holder.typeView.setText(record.getEntryType().getDescription()); - holder.valueView.setText(record.getDisplayableValue()); - } - } - - - @Override - public int getItemCount() { - return historyList.size(); - } - - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - } - - static class HistoryViewHolder extends RecyclerView.ViewHolder { - - TextView timeView; - TextView typeView; - TextView valueView; - - - HistoryViewHolder(View itemView) { - super(itemView); - // cv = (CardView)itemView.findViewById(R.id.rileylink_history_item); - timeView = itemView.findViewById(R.id.medtronic_history_time); - typeView = itemView.findViewById(R.id.medtronic_history_source); - valueView = itemView.findViewById(R.id.medtronic_history_description); - } - } - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt new file mode 100644 index 0000000000..e5a047ab97 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt @@ -0,0 +1,200 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.dialog + +import android.os.Bundle +import android.os.SystemClock +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.Spinner +import android.widget.TextView +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import dagger.android.DaggerActivity +import dagger.android.DispatchingAndroidInjector +import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup +import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup.Companion.getTranslatedList +import info.nightscout.androidaps.plugins.pump.medtronic.R +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData +import info.nightscout.androidaps.plugins.pump.medtronic.databinding.MedtronicHistoryActivityBinding +import info.nightscout.androidaps.utils.resources.ResourceHelper +import java.util.* +import javax.inject.Inject + +class MedtronicHistoryActivity : DaggerActivity() { + + @Inject lateinit var medtronicHistoryData: MedtronicHistoryData + @Inject lateinit var resourceHelper: ResourceHelper + + lateinit var historyTypeSpinner: Spinner + lateinit var statusView: TextView + lateinit var recyclerView: RecyclerView + lateinit var llm: LinearLayoutManager + lateinit var recyclerViewAdapter: RecyclerViewAdapter + + var filteredHistoryList: MutableList = ArrayList() + var manualChange = false + var typeListFull: List? = null + + private var _binding: MedtronicHistoryActivityBinding? = null + + //@Inject + //var fragmentInjector: DispatchingAndroidInjector? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + private fun filterHistory(group: PumpHistoryEntryGroup) { + filteredHistoryList.clear() + val list: MutableList = ArrayList() + list.addAll(medtronicHistoryData.allHistory) + + //LOG.debug("Items on full list: {}", list.size()); + if (group === PumpHistoryEntryGroup.All) { + filteredHistoryList.addAll(list) + } else { + for (pumpHistoryEntry in list) { + if (pumpHistoryEntry.entryType!!.group === group) { + filteredHistoryList.add(pumpHistoryEntry) + } + } + } + + recyclerViewAdapter.setHistoryListInternal(filteredHistoryList) + recyclerViewAdapter.notifyDataSetChanged() + + //LOG.debug("Items on filtered list: {}", filteredHistoryList.size()); + } + + override fun onResume() { + super.onResume() + filterHistory(selectedGroup) + setHistoryTypeSpinner() + } + + private fun setHistoryTypeSpinner() { + manualChange = true + for (i in typeListFull!!.indices) { + if (typeListFull!![i].entryGroup === selectedGroup) { + historyTypeSpinner.setSelection(i) + break + } + } + SystemClock.sleep(200) + manualChange = false + } + + override fun onPause() { + super.onPause() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + //setContentView(R.layout.medtronic_history_activity) + + _binding = MedtronicHistoryActivityBinding.inflate(getLayoutInflater()) //(inflater, container, false) + + historyTypeSpinner = binding.medtronicHistorytype //findViewById(R.id.medtronic_historytype) + statusView = binding.medtronicHistorystatus //findViewById(R.id.medtronic_historystatus) + recyclerView = binding.medtronicHistoryRecyclerview //findViewById(R.id.medtronic_history_recyclerview) + recyclerView.setHasFixedSize(true) + llm = LinearLayoutManager(this) + recyclerView.setLayoutManager(llm) + recyclerViewAdapter = RecyclerViewAdapter(filteredHistoryList) + recyclerView.setAdapter(recyclerViewAdapter) + statusView.setVisibility(View.GONE) + typeListFull = getTypeList(getTranslatedList(resourceHelper!!)) + val spinnerAdapter = ArrayAdapter(this, R.layout.spinner_centered, typeListFull) + historyTypeSpinner.setAdapter(spinnerAdapter) + historyTypeSpinner.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) { + if (manualChange) return + val selected = historyTypeSpinner.getSelectedItem() as TypeList + showingType = selected + selectedGroup = selected.entryGroup + filterHistory(selectedGroup) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + if (manualChange) return + filterHistory(PumpHistoryEntryGroup.All) + } + }) + } + + private fun getTypeList(list: List?): List { + val typeList = ArrayList() + for (pumpHistoryEntryGroup in list!!) { + typeList.add(TypeList(pumpHistoryEntryGroup)) + } + return typeList + } + + class TypeList internal constructor(var entryGroup: PumpHistoryEntryGroup) { + var name: String + override fun toString(): String { + return name + } + + init { + name = entryGroup.translated!! + } + } + + class RecyclerViewAdapter internal constructor(var historyList: List) : RecyclerView.Adapter() { + + + fun setHistoryListInternal(historyList: List) { + // this.historyList.clear(); + // this.historyList.addAll(historyList); + this.historyList = historyList + + // this.notifyDataSetChanged(); + } + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): HistoryViewHolder { + val v = LayoutInflater.from(viewGroup.context).inflate(R.layout.medtronic_history_item, // + viewGroup, false) + return HistoryViewHolder(v) + } + + override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) { + val record = historyList[position] + if (record != null) { + holder.timeView.text = record.dateTimeString + holder.typeView.text = record.entryType!!.description + holder.valueView.text = record.displayableValue + } + } + + override fun getItemCount(): Int { + return historyList.size + } + + override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { + super.onAttachedToRecyclerView(recyclerView) + } + + class HistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var timeView: TextView + var typeView: TextView + var valueView: TextView + + init { + // cv = (CardView)itemView.findViewById(R.id.rileylink_history_item); + timeView = itemView.findViewById(R.id.medtronic_history_time) + typeView = itemView.findViewById(R.id.medtronic_history_source) + valueView = itemView.findViewById(R.id.medtronic_history_description) + } + } + + } + + companion object { + var showingType: TypeList? = null + var selectedGroup = PumpHistoryEntryGroup.All + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java deleted file mode 100644 index e4b6c0e13a..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.java +++ /dev/null @@ -1,166 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.dialog; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ListView; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import dagger.android.support.DaggerFragment; -import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; -import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.R; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.resources.ResourceHelper; - -/** - * Created by andy on 5/19/18. - *

- * This is for 3rd tab, called Medtronic (in RileyLink stats), that should work similarly as the one in Loop. - *

- * Showing currently selected RL, speed of RL, ability to issue simple commands (getModel, tuneUp, gerProfile) - */ - -// TODO needs to be implemented -public class RileyLinkStatusDeviceMedtronic extends DaggerFragment implements RefreshableInterface { - - @Inject ResourceHelper resourceHelper; - @Inject DateUtil dateUtil; - - // @BindView(R.id.rileylink_history_list) - ListView listView; - - RileyLinkCommandListAdapter adapter; - - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.rileylink_status_device, container, false); - - adapter = new RileyLinkCommandListAdapter(); - - return rootView; - } - - - @Override - public void onStart() { - super.onStart(); - - this.listView = getActivity().findViewById(R.id.rileylink_history_list); - - listView.setAdapter(adapter); - - refreshData(); - } - - - @Override - public void refreshData() { - // adapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); - } - - static class ViewHolder { - - TextView itemTime; - TextView itemSource; - TextView itemDescription; - } - - private class RileyLinkCommandListAdapter extends BaseAdapter { - - private final List historyItemList; - private final LayoutInflater mInflator; - - - public RileyLinkCommandListAdapter() { - super(); - historyItemList = new ArrayList<>(); - mInflator = RileyLinkStatusDeviceMedtronic.this.getLayoutInflater(); - } - - - public void addItem(RLHistoryItem item) { - if (!historyItemList.contains(item)) { - historyItemList.add(item); - notifyDataSetChanged(); - } - } - - - public RLHistoryItem getHistoryItem(int position) { - return historyItemList.get(position); - } - - - public void addItemsAndClean(List items) { - this.historyItemList.clear(); - - for (RLHistoryItem item : items) { - - if (!historyItemList.contains(item)) { - historyItemList.add(item); - } - } - - notifyDataSetChanged(); - } - - - public void clear() { - historyItemList.clear(); - notifyDataSetChanged(); - } - - - @Override - public int getCount() { - return historyItemList.size(); - } - - - @Override - public Object getItem(int i) { - return historyItemList.get(i); - } - - - @Override - public long getItemId(int i) { - return i; - } - - - @Override - public View getView(int i, View view, ViewGroup viewGroup) { - RileyLinkStatusDeviceMedtronic.ViewHolder viewHolder; - // General ListView optimization code. - if (view == null) { - view = mInflator.inflate(R.layout.rileylink_status_device_item, null); - viewHolder = new RileyLinkStatusDeviceMedtronic.ViewHolder(); - viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time); - viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source); - viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description); - view.setTag(viewHolder); - } else { - viewHolder = (RileyLinkStatusDeviceMedtronic.ViewHolder) view.getTag(); - } - - RLHistoryItem item = historyItemList.get(i); - viewHolder.itemTime.setText(StringUtil.toDateTimeString(dateUtil, item.getDateTime())); - viewHolder.itemSource.setText("Riley Link"); // for now - viewHolder.itemDescription.setText(item.getDescription(resourceHelper)); - - return view; - } - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt new file mode 100644 index 0000000000..b753ac5795 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt @@ -0,0 +1,137 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.dialog + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.ListView +import android.widget.TextView +import dagger.android.support.DaggerFragment +import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem +import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil +import info.nightscout.androidaps.plugins.pump.medtronic.R +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.resources.ResourceHelper +import io.reactivex.disposables.CompositeDisposable +import java.util.* +import javax.inject.Inject + +/** + * Created by andy on 5/19/18. + * NOTE: This class is not used yet, so it has no Bindings + * + * This is for 3rd tab, called Medtronic (in RileyLink stats), that should work similarly as the one in Loop. + * + * + * Showing currently selected RL, speed of RL, ability to issue simple commands (getModel, tuneUp, gerProfile) + */ +// TODO needs to be implemented +class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { + + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var dateUtil: DateUtil + + var listView: ListView? = null + var adapter: RileyLinkCommandListAdapter? = null + + private var disposable: CompositeDisposable = CompositeDisposable() + //private var _binding: RileyLinkStatusDeviceBinding? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + + // _binding = LoopFragmentBinding.inflate(inflater, container, false) + // return binding.root + + + val rootView = inflater.inflate(R.layout.rileylink_status_device, container, false) + adapter = RileyLinkCommandListAdapter() + return rootView + } + + override fun onStart() { + super.onStart() + //listView = activity!!.findViewById(R.id.rileylink_history_list) + //listView.setAdapter(adapter) + refreshData() + } + + override fun refreshData() { + // adapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); + } + + internal class ViewHolder { + var itemTime: TextView? = null + var itemSource: TextView? = null + var itemDescription: TextView? = null + } + + inner class RileyLinkCommandListAdapter : BaseAdapter() { + private val historyItemList: MutableList + private val mInflator: LayoutInflater + fun addItem(item: RLHistoryItem) { + if (!historyItemList.contains(item)) { + historyItemList.add(item) + notifyDataSetChanged() + } + } + + fun getHistoryItem(position: Int): RLHistoryItem { + return historyItemList[position] + } + + fun addItemsAndClean(items: List) { + historyItemList.clear() + for (item in items) { + if (!historyItemList.contains(item)) { + historyItemList.add(item) + } + } + notifyDataSetChanged() + } + + fun clear() { + historyItemList.clear() + notifyDataSetChanged() + } + + override fun getCount(): Int { + return historyItemList.size + } + + override fun getItem(i: Int): Any { + return historyItemList[i] + } + + override fun getItemId(i: Int): Long { + return i.toLong() + } + + override fun getView(i: Int, view: View, viewGroup: ViewGroup): View { + var view = view + val viewHolder: ViewHolder + // General ListView optimization code. + if (view == null) { + view = mInflator.inflate(R.layout.rileylink_status_device_item, null) + viewHolder = ViewHolder() + viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) + viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) + viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) + view.tag = viewHolder + } else { + viewHolder = view.tag as ViewHolder + } + val item = historyItemList[i] + viewHolder.itemTime!!.text = StringUtil.toDateTimeString(dateUtil, item.dateTime) + viewHolder.itemSource!!.text = "Riley Link" // for now + viewHolder.itemDescription!!.text = item.getDescription(resourceHelper) + return view + } + + init { + historyItemList = ArrayList() + mInflator = this@RileyLinkStatusDeviceMedtronic.layoutInflater + } + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt index 89a31552d2..205742a336 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -49,6 +49,7 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi 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") @@ -267,19 +268,19 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi } private fun checkParameterValue(key: Int, defaultValue: String, defaultValueDouble: Double): Double { - var `val`: Double + var valueDouble: Double val value = sp.getString(key, defaultValue) - `val` = try { + valueDouble = try { value.toDouble() } catch (ex: Exception) { aapsLogger.error("Error parsing setting: %s, value found %s", key, value) defaultValueDouble } - if (`val` > defaultValueDouble) { + if (valueDouble > defaultValueDouble) { sp.putString(key, defaultValue) - `val` = defaultValueDouble + valueDouble = defaultValueDouble } - return `val` + return valueDouble } fun setNotInPreInit(): Boolean { diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt index 8b856d7036..8c7cbafada 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt @@ -33,6 +33,7 @@ enum class PumpHistoryEntryGroup(val resourceId: Int) { companion object { private var translatedList: MutableList? = null + private fun doTranslation(resourceHelper: ResourceHelper) { translatedList = ArrayList() for (pumpHistoryEntryGroup in values()) { @@ -41,7 +42,8 @@ enum class PumpHistoryEntryGroup(val resourceId: Int) { } } - @JvmStatic fun getTranslatedList(resourceHelper: ResourceHelper): List? { + @JvmStatic + fun getTranslatedList(resourceHelper: ResourceHelper): List? { if (translatedList == null) doTranslation(resourceHelper) return translatedList } diff --git a/rileylink/src/main/res/layout/rileylink_status_device.xml b/rileylink/src/main/res/layout/rileylink_status_device.xml index edf3cbdd7e..f56c4b0d6d 100644 --- a/rileylink/src/main/res/layout/rileylink_status_device.xml +++ b/rileylink/src/main/res/layout/rileylink_status_device.xml @@ -2,7 +2,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusDevice"> + tools:context=".plugins.pump.medtronic.dialog.RileyLinkStatusDevice"> Date: Tue, 20 Apr 2021 23:23:03 +0100 Subject: [PATCH 07/39] - kotlin changes almost done, 1 file left --- .../plugins/treatments/TreatmentsPlugin.java | 57 +- medtronic/build.gradle | 3 + .../plugins/pump/common/PumpPluginAbstract.kt | 11 +- .../pump/medtronic/MedtronicFragment.kt | 1 - .../pump/medtronic/MedtronicPumpPlugin.kt | 14 +- .../comm/MedtronicCommunicationManager.java | 956 ------------------ .../comm/MedtronicCommunicationManager.kt | 664 ++++++++++++ .../comm/history/MedtronicHistoryDecoder.kt | 4 +- .../cgms/MedtronicCGMSHistoryDecoder.kt | 5 +- .../pump/MedtronicPumpHistoryDecoder.kt | 13 +- .../comm/history/pump/PumpHistoryEntry.kt | 8 +- .../comm/history/pump/PumpHistoryResult.kt | 4 +- .../pump/medtronic/comm/ui/MedtronicUITask.kt | 25 +- .../pump/medtronic/data/dto/BasalProfile.kt | 59 +- .../dialog/MedtronicHistoryActivity.kt | 21 +- .../dialog/RileyLinkStatusDeviceMedtronic.kt | 4 +- .../service/RileyLinkMedtronicService.kt | 1 + .../pump/medtronic/util/MedtronicUtil.kt | 4 +- 18 files changed, 793 insertions(+), 1061 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index 94673a29b6..c795ea4050 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -1,10 +1,13 @@ package info.nightscout.androidaps.plugins.treatments; import android.content.Context; +import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.google.firebase.analytics.FirebaseAnalytics; + import java.util.List; import java.util.stream.Collectors; @@ -14,9 +17,11 @@ import javax.inject.Singleton; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.ProfileIntervals; import info.nightscout.androidaps.database.AppRepository; +import info.nightscout.androidaps.database.embedments.InterfaceIDs; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; @@ -32,12 +37,16 @@ import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.ProfileStore; import info.nightscout.androidaps.interfaces.TreatmentServiceInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.interfaces.UpdateReturn; 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.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -67,6 +76,10 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface private final ProfileIntervals profiles = new ProfileIntervals<>(); + private final boolean useNewPumpSync = false; + + + @Inject public TreatmentsPlugin( HasAndroidInjector injector, @@ -245,38 +258,48 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface @Deprecated @Override public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { - throw new IllegalStateException("Migrate to new DB"); -/* + if (useNewPumpSync) { + throw new IllegalStateException("Migrate to new DB"); + } else { + getAapsLogger().error("!!! addToHistoryTempBasal: Need to migrate to new DB"); + } + //log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal); if (newRecordCreated) { - if (tempBasal.durationInMinutes == 0) - nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); - else if (tempBasal.isAbsolute) - nsUpload.uploadTempBasalStartAbsolute(tempBasal, null); - else - nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); +// if (tempBasal.durationInMinutes == 0) +// nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); +// else if (tempBasal.isAbsolute) +// nsUpload.uploadTempBasalStartAbsolute(tempBasal, null); +// else +// nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); } return newRecordCreated; - */ } @Deprecated public TreatmentUpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout) { - throw new IllegalStateException("Migrate to new DB"); -/* + if (useNewPumpSync) { + throw new IllegalStateException("Migrate to new DB"); + } else { + getAapsLogger().error("!!! createOrUpdateMedtronic: Need to migrate to new DB"); + } + UpdateReturn resultRecord = getService().createOrUpdateMedtronic(treatment, fromNightScout); return new TreatmentUpdateReturn(resultRecord.getSuccess(), resultRecord.getNewRecord()); - */ } // return true if new record is created @Deprecated @Override public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) { - throw new IllegalStateException("Migrate to new DB"); -/* + if (useNewPumpSync) { + throw new IllegalStateException("Migrate to new DB"); + } else { + getAapsLogger().error("!!! addToHistoryTreatment: Need to migrate to new DB"); + } + boolean medtronicPump = activePlugin.getActivePump() instanceof MedtronicPumpPlugin; getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={} " + medtronicPump); @@ -320,8 +343,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface getService().createOrUpdateMedtronic(carbsTreatment, false); //log.debug("Adding new Treatment record" + carbsTreatment); } - if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) - nsUpload.uploadTreatmentRecord(detailedBolusInfo); +// if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) +// nsUpload.uploadTreatmentRecord(detailedBolusInfo); if (!allowUpdate && !creatOrUpdateResult.getSuccess()) { getAapsLogger().error("Treatment could not be added to DB", new Exception()); @@ -337,7 +360,7 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } return newRecordCreated; - */ + } @Override diff --git a/medtronic/build.gradle b/medtronic/build.gradle index a3cb9f789e..0488efd078 100644 --- a/medtronic/build.gradle +++ b/medtronic/build.gradle @@ -12,6 +12,9 @@ android { versionCode 1 versionName "1.0" } + dataBinding { + enabled = true + } } dependencies { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index 26660c4936..6b7e738929 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -74,11 +74,11 @@ abstract class PumpPluginAbstract protected constructor( @JvmField protected var pumpState = PumpDriverState.NotInitialized @JvmField protected var displayConnectionMessages = false - var pumpType: PumpType? = null + var pumpType: PumpType = PumpType.GENERIC_AAPS get() = field set(value) { field = value - pumpDescription.setPumpDescription(value!!) + pumpDescription.setPumpDescription(value) } @@ -366,11 +366,11 @@ abstract class PumpPluginAbstract protected constructor( } override fun manufacturer(): ManufacturerType { - return pumpType!!.manufacturer!! + return pumpType.manufacturer!! } override fun model(): PumpType { - return pumpType!! + return pumpType } @@ -395,7 +395,7 @@ abstract class PumpPluginAbstract protected constructor( val temporaryId = generateTempId(detailedBolusInfo.timestamp) val response = pumpSync.addBolusWithTempId(detailedBolusInfo.timestamp, detailedBolusInfo.insulin, temporaryId, detailedBolusInfo.bolusType, - pumpType!!, serialNumber()) + pumpType, serialNumber()) if (response && writeToInternalHistory) { driverHistory[temporaryId] = PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo) sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)) @@ -403,6 +403,7 @@ abstract class PumpPluginAbstract protected constructor( return response } + // TODO protected fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal?, b: Boolean) { // long temporaryId = generateTempId(temporaryBasal.timestamp); // boolean response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index 49b2415264..c9d4009bf7 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -210,7 +210,6 @@ class MedtronicFragment : DaggerFragment() { } ?: "-" when (medtronicPumpStatus.pumpDeviceState) { - null, PumpDeviceState.Sleeping -> binding.pumpStatusIcon.text = "{fa-bed} " // + pumpStatus.pumpDeviceState.name()); PumpDeviceState.NeverContacted, PumpDeviceState.WakingUp, diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 803f281b45..64bb650744 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -98,7 +98,7 @@ class MedtronicPumpPlugin @Inject constructor( .preferencesId(R.xml.pref_medtronic) .description(R.string.description_pump_medtronic), // PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later - injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers!!, pumpSync!! + injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync ), Pump, RileyLinkPumpDevice { private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null @@ -149,7 +149,7 @@ class MedtronicPumpPlugin @Inject constructor( } private val logPrefix: String - private get() = "MedtronicPumpPlugin::" + get() = "MedtronicPumpPlugin::" override fun initPumpStatusData() { medtronicPumpStatus.lastConnection = sp.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L) @@ -225,7 +225,7 @@ class MedtronicPumpPlugin @Inject constructor( // Pump Plugin private val isServiceSet: Boolean - private get() = rileyLinkMedtronicService != null + get() = rileyLinkMedtronicService != null override fun getRileyLinkService(): RileyLinkMedtronicService? { return rileyLinkMedtronicService @@ -313,7 +313,7 @@ class MedtronicPumpPlugin @Inject constructor( }// private val isPumpNotReachable: Boolean - private get() { + get() { val rileyLinkServiceState = rileyLinkServiceData.rileyLinkServiceState if (rileyLinkServiceState == null) { aapsLogger.debug(LTag.PUMP, "RileyLink unreachable. RileyLinkServiceState is null.") @@ -908,7 +908,7 @@ class MedtronicPumpPlugin @Inject constructor( } private val lastPumpEntryTime: Long - private get() { + get() { val lastPumpEntryTime = sp.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, 0L) return try { val localDateTime = DateTimeUtil.toLocalDateTime(lastPumpEntryTime) @@ -1085,7 +1085,7 @@ class MedtronicPumpPlugin @Inject constructor( private fun isProfileValid(basalProfile: BasalProfile): String? { val stringBuilder = StringBuilder() if (medtronicPumpStatus.maxBasal == null) return null - for (profileEntry in basalProfile.entries) { + for (profileEntry in basalProfile.getEntries()) { if (profileEntry.rate > medtronicPumpStatus.maxBasal!!) { stringBuilder.append(profileEntry.startTime!!.toString("HH:mm")) stringBuilder.append("=") @@ -1099,7 +1099,7 @@ class MedtronicPumpPlugin @Inject constructor( val basalProfile = BasalProfile(aapsLogger) for (i in 0..23) { val rate = profile.getBasalTimeFromMidnight(i * 60 * 60) - val v = pumpDescription.pumpType.determineCorrectBasalSize(rate) + val v = pumpType.determineCorrectBasalSize(rate) val basalEntry = BasalProfileEntry(v, i, 0) basalProfile.addEntry(basalEntry) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java deleted file mode 100644 index 4e855dafa3..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java +++ /dev/null @@ -1,956 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm; - -import android.os.SystemClock; - -import org.joda.time.LocalDateTime; - -import java.util.Calendar; -import java.util.GregorianCalendar; -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.LTag; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RFSpyResponse; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioResponse; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask; -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RawHistoryPage; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.CarelinkLongMessageBody; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.CarelinkShortMessageBody; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.GetHistoryPageCarelinkMessageBody; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.MessageBody; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PacketType; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpAckMessageBody; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.PumpMessage; -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.data.dto.TempBasalPair; -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.driver.MedtronicPumpStatus; -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil; - -/** - * Original file created by geoff on 5/30/16. - *

- * Split into 2 implementations, so that we can split it by target device. - Andy - * This was mostly rewritten from Original version, and lots of commands and - * functionality added. - */ -@Singleton -public class MedtronicCommunicationManager extends RileyLinkCommunicationManager { - - @Inject MedtronicPumpStatus medtronicPumpStatus; - @Inject MedtronicPumpPlugin medtronicPumpPlugin; - @Inject MedtronicConverter medtronicConverter; - @Inject MedtronicUtil medtronicUtil; - @Inject MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder; - - private final int MAX_COMMAND_TRIES = 3; - private final int DEFAULT_TIMEOUT = 2000; - private final long RILEYLINK_TIMEOUT = 15 * 60 * 1000; // 15 min - - private String errorMessage; - private final boolean debugSetCommands = false; - - private boolean doWakeUpBeforeCommand = true; - - // This empty constructor must be kept, otherwise dagger injection might break! - @Inject - public MedtronicCommunicationManager() { - } - - @Inject - public void onInit() { - // we can't do this in the constructor, as sp only gets injected after the constructor has returned - medtronicPumpStatus.setPreviousConnection(sp.getLong( - RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L)); - } - - @Override - public PumpMessage createResponseMessage(byte[] payload) { - return new PumpMessage(aapsLogger, payload); - } - - @Override - public void setPumpDeviceState(PumpDeviceState pumpDeviceState) { - this.medtronicPumpStatus.setPumpDeviceState(pumpDeviceState); - } - - public void setDoWakeUpBeforeCommand(boolean doWakeUp) { - this.doWakeUpBeforeCommand = doWakeUp; - } - - - @Override - public boolean isDeviceReachable() { - return isDeviceReachable(false); - } - - - /** - * We do actual wakeUp and compare PumpModel with currently selected one. If returned model is - * not Unknown, pump is reachable. - * - * @return - */ - public boolean isDeviceReachable(boolean canPreventTuneUp) { - - PumpDeviceState state = medtronicPumpStatus.getPumpDeviceState(); - - if (state != PumpDeviceState.PumpUnreachable) - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.WakingUp); - - for (int retry = 0; retry < 5; retry++) { - - aapsLogger.debug(LTag.PUMPCOMM, "isDeviceReachable. Waking pump... " + (retry != 0 ? " (retry " + retry + ")" : "")); - - boolean connected = connectToDevice(); - - if (connected) - return true; - - SystemClock.sleep(1000); - - } - - if (state != PumpDeviceState.PumpUnreachable) - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.PumpUnreachable); - - if (!canPreventTuneUp) { - - long diff = System.currentTimeMillis() - medtronicPumpStatus.getLastConnection(); - - if (diff > RILEYLINK_TIMEOUT) { - serviceTaskExecutor.startTask(new WakeAndTuneTask(injector)); - } - } - - return false; - } - - - private boolean connectToDevice() { - - PumpDeviceState state = medtronicPumpStatus.getPumpDeviceState(); - - // check connection - - byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple - RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(injector, pumpMsgContent), (byte) 0, (byte) 200, - (byte) 0, (byte) 0, 25000, (byte) 0); - aapsLogger.info(LTag.PUMPCOMM, "wakeup: raw response is " + ByteUtil.shortHexString(rfSpyResponse.getRaw())); - - if (rfSpyResponse.wasTimeout()) { - aapsLogger.error(LTag.PUMPCOMM, "isDeviceReachable. Failed to find pump (timeout)."); - } else if (rfSpyResponse.looksLikeRadioPacket()) { - RadioResponse radioResponse = new RadioResponse(injector); - - try { - - radioResponse.init(rfSpyResponse.getRaw()); - - if (radioResponse.isValid()) { - - PumpMessage pumpResponse = createResponseMessage(radioResponse.getPayload()); - - if (!pumpResponse.isValid()) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Response is invalid ! [interrupted=%b, timeout=%b]", rfSpyResponse.wasInterrupted(), - rfSpyResponse.wasTimeout())); - } else { - - // radioResponse.rssi; - Object dataResponse = medtronicConverter.convertResponse(medtronicPumpPlugin.getPumpDescription().getPumpType(), MedtronicCommandType.PumpModel, - pumpResponse.getRawContent()); - - MedtronicDeviceType pumpModel = (MedtronicDeviceType) dataResponse; - boolean valid = (pumpModel != MedtronicDeviceType.Unknown_Device); - - if (medtronicUtil.getMedtronicPumpModel() == null && valid) { - medtronicUtil.setMedtronicPumpModel(pumpModel); - } - - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "isDeviceReachable. PumpModel is %s - Valid: %b (rssi=%d)", pumpModel.name(), valid, - radioResponse.rssi)); - - if (valid) { - if (state == PumpDeviceState.PumpUnreachable) - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.WakingUp); - else - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - - rememberLastGoodDeviceCommunicationTime(); - - return true; - - } else { - if (state != PumpDeviceState.PumpUnreachable) - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.PumpUnreachable); - } - - } - - } else { - aapsLogger.warn(LTag.PUMPCOMM, "isDeviceReachable. Failed to parse radio response: " - + ByteUtil.shortHexString(rfSpyResponse.getRaw())); - } - - } catch (RileyLinkCommunicationException e) { - aapsLogger.warn(LTag.PUMPCOMM, "isDeviceReachable. Failed to decode radio response: " - + ByteUtil.shortHexString(rfSpyResponse.getRaw())); - } - - } else { - aapsLogger.warn(LTag.PUMPCOMM, "isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw())); - } - - return false; - } - - - @Override - public boolean tryToConnectToDevice() { - return isDeviceReachable(true); - } - - - private PumpMessage runCommandWithArgs(PumpMessage msg) throws RileyLinkCommunicationException { - - if (debugSetCommands) - aapsLogger.debug(LTag.PUMPCOMM, "Run command with Args: "); - - PumpMessage rval; - PumpMessage shortMessage = makePumpMessage(msg.getCommandType(), new CarelinkShortMessageBody(new byte[]{0})); - // look for ack from short message - PumpMessage shortResponse = sendAndListen(shortMessage); - if (shortResponse.getCommandType() == MedtronicCommandType.CommandACK) { - if (debugSetCommands) - aapsLogger.debug(LTag.PUMPCOMM, "Run command with Args: Got ACK response"); - - rval = sendAndListen(msg); - if (debugSetCommands) - aapsLogger.debug(LTag.PUMPCOMM, "2nd Response: " + rval); - - return rval; - } else { - aapsLogger.error(LTag.PUMPCOMM, "runCommandWithArgs: Pump did not ack Attention packet"); - return new PumpMessage(aapsLogger, "No ACK after Attention packet."); - } - } - - - private PumpMessage runCommandWithFrames(MedtronicCommandType commandType, List> frames) - throws RileyLinkCommunicationException { - - aapsLogger.debug(LTag.PUMPCOMM, "Run command with Frames: " + commandType.name()); - - PumpMessage rval = null; - PumpMessage shortMessage = makePumpMessage(commandType, new CarelinkShortMessageBody(new byte[]{0})); - // look for ack from short message - PumpMessage shortResponse = sendAndListen(shortMessage); - - if (shortResponse.getCommandType() != MedtronicCommandType.CommandACK) { - aapsLogger.error(LTag.PUMPCOMM, "runCommandWithFrames: Pump did not ack Attention packet"); - - return new PumpMessage(aapsLogger, "No ACK after start message."); - } else { - aapsLogger.debug(LTag.PUMPCOMM, "Run command with Frames: Got ACK response for Attention packet"); - } - - int frameNr = 1; - - for (List frame : frames) { - - byte[] frameData = medtronicUtil.createByteArray(frame); - - // aapsLogger.debug(LTag.PUMPCOMM,"Frame {} data:\n{}", frameNr, ByteUtil.getCompactString(frameData)); - - PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(frameData)); - - rval = sendAndListen(msg); - - // aapsLogger.debug(LTag.PUMPCOMM,"PumpResponse: " + rval); - - if (rval.getCommandType() != MedtronicCommandType.CommandACK) { - aapsLogger.error(LTag.PUMPCOMM, "runCommandWithFrames: Pump did not ACK frame #" + frameNr); - - aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Run command with Frames FAILED (command=%s, response=%s)", commandType.name(), - rval.toString())); - - return new PumpMessage(aapsLogger, "No ACK after frame #" + frameNr); - } else { - aapsLogger.debug(LTag.PUMPCOMM, "Run command with Frames: Got ACK response for frame #" + frameNr); - } - - frameNr++; - } - - return rval; - - } - - - public PumpHistoryResult getPumpHistory(PumpHistoryEntry lastEntry, LocalDateTime targetDate) { - - PumpHistoryResult pumpTotalResult = new PumpHistoryResult(aapsLogger, lastEntry, targetDate == null ? null - : DateTimeUtil.toATechDate(targetDate)); - - if (doWakeUpBeforeCommand) - wakeUp(receiverDeviceAwakeForMinutes, false); - - aapsLogger.debug(LTag.PUMPCOMM, "Current command: " + medtronicUtil.getCurrentCommand()); - - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Active); - boolean doneWithError = false; - - for (int pageNumber = 0; pageNumber < 5; pageNumber++) { - - RawHistoryPage rawHistoryPage = new RawHistoryPage(aapsLogger); - // wakeUp(receiverDeviceAwakeForMinutes, false); - PumpMessage getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData, - new GetHistoryPageCarelinkMessageBody(pageNumber)); - - aapsLogger.info(LTag.PUMPCOMM, "getPumpHistory: Page " + pageNumber); - // aapsLogger.info(LTag.PUMPCOMM,"getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData())); - // Ask the pump to transfer history (we get first frame?) - - PumpMessage firstResponse = null; - boolean failed = false; - - medtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber, null); - - for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { - - try { - firstResponse = runCommandWithArgs(getHistoryMsg); - failed = false; - break; - } catch (RileyLinkCommunicationException e) { - aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "First call for PumpHistory failed (retry=%d)", retries)); - failed = true; - } - } - - if (failed) { - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - return pumpTotalResult; - } - - // aapsLogger.info(LTag.PUMPCOMM,"getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents())); - - PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody()); - GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse.getMessageBody().getTxData()); - int expectedFrameNum = 1; - boolean done = false; - // while (expectedFrameNum == currentResponse.getFrameNumber()) { - - int failures = 0; - while (!done) { - // examine current response for problems. - byte[] frameData = currentResponse.getFrameData(); - if ((frameData != null) && (frameData.length > 0) - && currentResponse.getFrameNumber() == expectedFrameNum) { - // success! got a frame. - if (frameData.length != 64) { - aapsLogger.warn(LTag.PUMPCOMM, "Expected frame of length 64, got frame of length " + frameData.length); - // but append it anyway? - } - // handle successful frame data - rawHistoryPage.appendData(currentResponse.getFrameData()); - // RileyLinkMedtronicService.getInstance().announceProgress(((100 / 16) * - // currentResponse.getFrameNumber() + 1)); - medtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber, - currentResponse.getFrameNumber()); - - aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Got frame %d of Page %d", currentResponse.getFrameNumber(), pageNumber)); - // Do we need to ask for the next frame? - if (expectedFrameNum < 16) { // This number may not be correct for pumps other than 522/722 - expectedFrameNum++; - } else { - done = true; // successful completion - } - } else { - if (frameData == null) { - aapsLogger.error(LTag.PUMPCOMM, "null frame data, retrying"); - } else if (currentResponse.getFrameNumber() != expectedFrameNum) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Expected frame number %d, received %d (retrying)", expectedFrameNum, - currentResponse.getFrameNumber())); - } else if (frameData.length == 0) { - aapsLogger.warn(LTag.PUMPCOMM, "Frame has zero length, retrying"); - } - failures++; - if (failures == 6) { - aapsLogger.error(LTag.PUMPCOMM, - String.format(Locale.ENGLISH, "getPumpHistory: 6 failures in attempting to download frame %d of page %d, giving up.", - expectedFrameNum, pageNumber)); - done = true; // failure completion. - doneWithError = true; - } - } - - if (!done) { - // ask for next frame - PumpMessage nextMsg = null; - - for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { - - try { - nextMsg = sendAndListen(ackMsg); - break; - } catch (RileyLinkCommunicationException e) { - aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Problem acknowledging frame response. (retry=%d)", retries)); - } - } - - if (nextMsg != null) - currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData()); - else { - aapsLogger.error(LTag.PUMPCOMM, "We couldn't acknowledge frame from pump, aborting operation."); - } - } - } - - if (rawHistoryPage.getLength() != 1024) { - aapsLogger.warn(LTag.PUMPCOMM, "getPumpHistory: short page. Expected length of 1024, found length of " - + rawHistoryPage.getLength()); - doneWithError = true; - } - - if (!rawHistoryPage.isChecksumOK()) { - aapsLogger.error(LTag.PUMPCOMM, "getPumpHistory: checksum is wrong"); - doneWithError = true; - } - - if (doneWithError) { - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - return pumpTotalResult; - } - - rawHistoryPage.dumpToDebug(); - - List medtronicHistoryEntries = medtronicPumpHistoryDecoder.processPageAndCreateRecords(rawHistoryPage); - - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Found %d history entries.", medtronicHistoryEntries.size())); - - pumpTotalResult.addHistoryEntries(medtronicHistoryEntries, pageNumber); - - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Search status: Search finished: %b", pumpTotalResult.isSearchFinished())); - - if (pumpTotalResult.isSearchFinished()) { - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - - return pumpTotalResult; - } - } - - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - - return pumpTotalResult; - - } - - - public String getErrorResponse() { - return this.errorMessage; - } - - - @Override - public byte[] createPumpMessageContent(RLMessageType type) { - switch (type) { - case PowerOn: - return medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.RFPowerOn, // - new byte[]{2, 1, (byte) receiverDeviceAwakeForMinutes}); // maybe this is better FIXME - - case ReadSimpleData: - return medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.PumpModel, null); - } - return new byte[0]; - } - - - private PumpMessage makePumpMessage(MedtronicCommandType messageType, byte[] body) { - return makePumpMessage(messageType, body == null ? new CarelinkShortMessageBody() - : new CarelinkShortMessageBody(body)); - } - - - private PumpMessage makePumpMessage(MedtronicCommandType messageType) { - return makePumpMessage(messageType, (byte[]) null); - } - - - private PumpMessage makePumpMessage(MedtronicCommandType messageType, MessageBody messageBody) { - PumpMessage msg = new PumpMessage(aapsLogger); - msg.init(PacketType.Carelink, rileyLinkServiceData.pumpIDBytes, messageType, messageBody); - return msg; - } - - - private PumpMessage sendAndGetResponse(MedtronicCommandType commandType) throws RileyLinkCommunicationException { - - return sendAndGetResponse(commandType, null, DEFAULT_TIMEOUT); - } - - - /** - * Main wrapper method for sending data - (for getting responses) - * - * @param commandType - * @param bodyData - * @param timeoutMs - * @return - */ - private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs) - throws RileyLinkCommunicationException { - // wakeUp - if (doWakeUpBeforeCommand) - wakeUp(receiverDeviceAwakeForMinutes, false); - - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Active); - - // create message - PumpMessage msg; - - if (bodyData == null) - msg = makePumpMessage(commandType); - else - msg = makePumpMessage(commandType, bodyData); - - // send and wait for response - PumpMessage response = sendAndListen(msg, timeoutMs); - - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - - return response; - } - - - private PumpMessage sendAndListen(PumpMessage msg) throws RileyLinkCommunicationException { - return sendAndListen(msg, 4000); // 2000 - } - - - // All pump communications go through this function. - @Override - protected PumpMessage sendAndListen(PumpMessage msg, int timeout_ms) throws RileyLinkCommunicationException { - return super.sendAndListen(msg, timeout_ms); - } - - - private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType) { - - return sendAndGetResponseWithCheck(commandType, null); - } - - - private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData) { - - aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: " + commandType); - - for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { - - try { - PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); - - String check = checkResponseContent(response, commandType.getCommandDescription(), commandType.getExpectedLength()); - - if (check == null) { - - Object dataResponse = medtronicConverter.convertResponse(medtronicPumpPlugin.getPumpDescription().getPumpType(), commandType, response.getRawContent()); - - if (dataResponse != null) { - this.errorMessage = null; - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name(), dataResponse)); - - return dataResponse; - } else { - this.errorMessage = "Error decoding response."; - } - } else { - this.errorMessage = check; - // return null; - } - - } catch (RileyLinkCommunicationException e) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.getMessage(), retries + 1)); - } - - } - - return null; - } - - - private T sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData, Class clazz) { - - aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: " + commandType); - - for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) { - - try { - PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); - - String check = checkResponseContent(response, commandType.getCommandDescription(), commandType.getExpectedLength()); - - if (check == null) { - - T dataResponse = (T)medtronicConverter.convertResponse(medtronicPumpPlugin.getPumpDescription().getPumpType(), commandType, response.getRawContent()); - - if (dataResponse != null) { - this.errorMessage = null; - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name(), dataResponse)); - - return dataResponse; - } else { - this.errorMessage = "Error decoding response."; - } - } else { - this.errorMessage = check; - // return null; - } - - } catch (RileyLinkCommunicationException e) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.getMessage(), retries + 1)); - } - - } - - return null; - } - - - private String checkResponseContent(PumpMessage response, String method, int expectedLength) { - - if (!response.isValid()) { - String responseData = String.format("%s: Invalid response.", method); - aapsLogger.warn(LTag.PUMPCOMM, responseData); - return responseData; - } - - byte[] contents = response.getRawContent(); - - if (contents != null) { - if (contents.length >= expectedLength) { - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: Content: %s", method, ByteUtil.shortHexString(contents))); - return null; - - } else { - String responseData = String.format( - "%s: Cannot return data. Data is too short [expected=%s, received=%s].", method, "" - + expectedLength, "" + contents.length); - - aapsLogger.warn(LTag.PUMPCOMM, responseData); - return responseData; - } - } else { - String responseData = String.format("%s: Cannot return data. Null response.", method); - aapsLogger.warn(LTag.PUMPCOMM, responseData); - return responseData; - } - } - - - // PUMP SPECIFIC COMMANDS - - public Double getRemainingInsulin() { - - Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin); - - return responseObject == null ? null : (Double) responseObject; - } - - - public MedtronicDeviceType getPumpModel() { - - Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel); - - return responseObject == null ? null : (MedtronicDeviceType) responseObject; - } - - - public BasalProfile getBasalProfile() { - - // wakeUp - if (doWakeUpBeforeCommand) - wakeUp(receiverDeviceAwakeForMinutes, false); - - MedtronicCommandType commandType = MedtronicCommandType.GetBasalProfileSTD; - - aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: " + commandType); - - medtronicUtil.setCurrentCommand(commandType); - - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Active); - - for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) { - - try { - // create message - PumpMessage msg; - - msg = makePumpMessage(commandType); - - // send and wait for response - - PumpMessage response = sendAndListen(msg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); - -// aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent())); -// aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData())); - - String check = checkResponseContent(response, commandType.getCommandDescription(), 1); - - byte[] data = null; - - if (check == null) { - - data = response.getRawContentOfFrame(); - - PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody()); - - while (checkIfWeHaveMoreData(commandType, response, data)) { - - response = sendAndListen(ackMsg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries)); - -// aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs, HexDump.toHexStringDisplayable(response2.getRawContent())); -// aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs, -// HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData())); - - String check2 = checkResponseContent(response, commandType.getCommandDescription(), 1); - - if (check2 == null) { - - data = ByteUtil.concat(data, response.getRawContentOfFrame()); - - } else { - this.errorMessage = check2; - aapsLogger.error(LTag.PUMPCOMM, "Error with response got GetProfile: " + check2); - } - } - - } else { - errorMessage = check; - } - - BasalProfile basalProfile = (BasalProfile) medtronicConverter.convertResponse(medtronicPumpPlugin.getPumpDescription().getPumpType(), commandType, data); - - if (basalProfile != null) { - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name(), basalProfile)); - - medtronicUtil.setCurrentCommand(null); - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - - return basalProfile; - } - - } catch (RileyLinkCommunicationException e) { - aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.getMessage(), retries + 1)); - } - } - - aapsLogger.warn(LTag.PUMPCOMM, "Error reading profile in max retries."); - medtronicUtil.setCurrentCommand(null); - medtronicPumpStatus.setPumpDeviceState(PumpDeviceState.Sleeping); - - return null; - - } - - - private boolean checkIfWeHaveMoreData(MedtronicCommandType commandType, PumpMessage response, byte[] data) { - - if (commandType == MedtronicCommandType.GetBasalProfileSTD || // - commandType == MedtronicCommandType.GetBasalProfileA || // - commandType == MedtronicCommandType.GetBasalProfileB) { - byte[] responseRaw = response.getRawContentOfFrame(); - - int last = responseRaw.length - 1; - - aapsLogger.debug(LTag.PUMPCOMM, "Length: " + data.length); - - if (data.length >= BasalProfile.MAX_RAW_DATA_SIZE) { - return false; - } - - if (responseRaw.length < 2) { - return false; - } - - return !(responseRaw[last] == 0x00 && responseRaw[last - 1] == 0x00 && responseRaw[last - 2] == 0x00); - } - - return false; - } - - - public ClockDTO getPumpTime() { - - ClockDTO clockDTO = new ClockDTO(); - clockDTO.setLocalDeviceTime(new LocalDateTime()); - - Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock); - - if (responseObject != null) { - clockDTO.setPumpTime((LocalDateTime) responseObject); - return clockDTO; - } - - return null; - } - - - public TempBasalPair getTemporaryBasal() { - - Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal); - - return responseObject == null ? null : (TempBasalPair) responseObject; - } - - - public Map getPumpSettings() { - - Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.getSettings(medtronicUtil - .getMedtronicPumpModel())); - - return responseObject == null ? null : (Map) responseObject; - } - - - public Boolean setBolus(double units) { - - aapsLogger.info(LTag.PUMPCOMM, "setBolus: " + units); - - return setCommand(MedtronicCommandType.SetBolus, medtronicUtil.getBolusStrokes(units)); - - } - - - public boolean setTBR(TempBasalPair tbr) { - - aapsLogger.info(LTag.PUMPCOMM, "setTBR: " + tbr.getDescription()); - - return setCommand(MedtronicCommandType.SetTemporaryBasal, tbr.getAsRawData()); - } - - - public Boolean setPumpTime() { - - GregorianCalendar gc = new GregorianCalendar(); - gc.add(Calendar.SECOND, 5); - - aapsLogger.info(LTag.PUMPCOMM, "setPumpTime: " + DateTimeUtil.toString(gc)); - - int i = 1; - byte[] data = new byte[8]; - data[0] = 7; - data[i] = (byte) gc.get(Calendar.HOUR_OF_DAY); - data[i + 1] = (byte) gc.get(Calendar.MINUTE); - data[i + 2] = (byte) gc.get(Calendar.SECOND); - - byte[] yearByte = MedtronicUtil.getByteArrayFromUnsignedShort(gc.get(Calendar.YEAR), true); - - data[i + 3] = yearByte[0]; - data[i + 4] = yearByte[1]; - - data[i + 5] = (byte) (gc.get(Calendar.MONTH) + 1); - data[i + 6] = (byte) gc.get(Calendar.DAY_OF_MONTH); - - //aapsLogger.info(LTag.PUMPCOMM,"setPumpTime: Body: " + ByteUtil.getHex(data)); - - return setCommand(MedtronicCommandType.SetRealTimeClock, data); - - } - - - private boolean setCommand(MedtronicCommandType commandType, byte[] body) { - - for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) { - - try { - if (this.doWakeUpBeforeCommand) - wakeUp(false); - - if (debugSetCommands) - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: Body - %s", commandType.getCommandDescription(), - ByteUtil.getHex(body))); - - PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(body)); - - PumpMessage pumpMessage = runCommandWithArgs(msg); - - if (debugSetCommands) - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: %s", commandType.getCommandDescription(), pumpMessage.getResponseContent())); - - if (pumpMessage.getCommandType() == MedtronicCommandType.CommandACK) { - return true; - } else { - aapsLogger.warn(LTag.PUMPCOMM, "We received non-ACK response from pump: " + pumpMessage.getResponseContent()); - } - - } catch (RileyLinkCommunicationException e) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.getMessage(), retries + 1)); - } - } - - return false; - } - - - public boolean cancelTBR() { - return setTBR(new TempBasalPair(0.0d, false, 0)); - } - - - public BatteryStatusDTO getRemainingBattery() { - - Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus); - - return responseObject == null ? null : (BatteryStatusDTO) responseObject; - } - - - public Boolean setBasalProfile(BasalProfile basalProfile) { - - List> basalProfileFrames = medtronicUtil.getBasalProfileFrames(basalProfile.getRawData()); - - for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) { - - PumpMessage responseMessage = null; - try { - responseMessage = runCommandWithFrames(MedtronicCommandType.SetBasalProfileSTD, - basalProfileFrames); - - if (responseMessage.getCommandType() == MedtronicCommandType.CommandACK) - return true; - - } catch (RileyLinkCommunicationException e) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.getMessage(), retries + 1)); - } - - if (responseMessage != null) - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Set Basal Profile: Invalid response: commandType=%s,rawData=%s", responseMessage.getCommandType(), ByteUtil.shortHexString(responseMessage.getRawContent()))); - else - aapsLogger.warn(LTag.PUMPCOMM, "Set Basal Profile: Null response."); - } - - return false; - - } -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt new file mode 100644 index 0000000000..e913ff52f7 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -0,0 +1,664 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm + +import android.os.SystemClock +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioPacket +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RadioResponse +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RawHistoryPage +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult +import info.nightscout.androidaps.plugins.pump.medtronic.comm.message.* +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.data.dto.TempBasalPair +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType.Companion.getSettings +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType +import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil.Companion.createByteArray +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil.Companion.getByteArrayFromUnsignedShort +import org.joda.time.LocalDateTime +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.jvm.Throws + +/** + * Original file created by geoff on 5/30/16. + * + * + * Split into 2 implementations, so that we can split it by target device. - Andy + * This was mostly rewritten from Original version, and lots of commands and + * functionality added. + */ +@Singleton +class MedtronicCommunicationManager // This empty constructor must be kept, otherwise dagger injection might break! +@Inject constructor() : RileyLinkCommunicationManager() { + + @Inject lateinit var medtronicPumpStatus: MedtronicPumpStatus + @Inject lateinit var medtronicPumpPlugin: MedtronicPumpPlugin + @Inject lateinit var medtronicConverter: MedtronicConverter + @Inject lateinit var medtronicUtil: MedtronicUtil + @Inject lateinit var medtronicPumpHistoryDecoder: MedtronicPumpHistoryDecoder + + private val MAX_COMMAND_TRIES = 3 + private val DEFAULT_TIMEOUT = 2000 + private val RILEYLINK_TIMEOUT: Long = 15 * 60 * 1000 // 15 min + + var errorResponse: String? = null + private set + private val debugSetCommands = false + private var doWakeUpBeforeCommand = true + + @Inject + open fun onInit(): Unit { + // we can't do this in the constructor, as sp only gets injected after the constructor has returned + medtronicPumpStatus.previousConnection = sp.getLong( + RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L) + } + + override fun createResponseMessage(payload: ByteArray): PumpMessage { + return PumpMessage(aapsLogger, payload) + } + + override fun setPumpDeviceState(pumpDeviceState: PumpDeviceState) { + medtronicPumpStatus.pumpDeviceState = pumpDeviceState + } + + fun setDoWakeUpBeforeCommand(doWakeUp: Boolean) { + doWakeUpBeforeCommand = doWakeUp + } + + override fun isDeviceReachable(): Boolean { + return isDeviceReachable(false) + } + + /** + * We do actual wakeUp and compare PumpModel with currently selected one. If returned model is + * not Unknown, pump is reachable. + * + * @return + */ + fun isDeviceReachable(canPreventTuneUp: Boolean): Boolean { + val state = medtronicPumpStatus.pumpDeviceState + if (state !== PumpDeviceState.PumpUnreachable) medtronicPumpStatus.pumpDeviceState = PumpDeviceState.WakingUp + for (retry in 0..4) { + aapsLogger.debug(LTag.PUMPCOMM, "isDeviceReachable. Waking pump... " + if (retry != 0) " (retry $retry)" else "") + val connected = connectToDevice() + if (connected) return true + SystemClock.sleep(1000) + } + if (state !== PumpDeviceState.PumpUnreachable) medtronicPumpStatus.pumpDeviceState = PumpDeviceState.PumpUnreachable + if (!canPreventTuneUp) { + val diff = System.currentTimeMillis() - medtronicPumpStatus.lastConnection + if (diff > RILEYLINK_TIMEOUT) { + serviceTaskExecutor.startTask(WakeAndTuneTask(injector)) + } + } + return false + } + + private fun connectToDevice(): Boolean { + val state = medtronicPumpStatus.pumpDeviceState + + // check connection + val pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData) // simple + val rfSpyResponse = rfspy.transmitThenReceive(RadioPacket(injector, pumpMsgContent), 0.toByte(), 200.toByte(), + 0.toByte(), 0.toByte(), 25000, 0.toByte()) + aapsLogger.info(LTag.PUMPCOMM, "wakeup: raw response is " + ByteUtil.shortHexString(rfSpyResponse.raw)) + if (rfSpyResponse.wasTimeout()) { + aapsLogger.error(LTag.PUMPCOMM, "isDeviceReachable. Failed to find pump (timeout).") + } else if (rfSpyResponse.looksLikeRadioPacket()) { + val radioResponse = RadioResponse(injector) + try { + radioResponse.init(rfSpyResponse.raw) + if (radioResponse.isValid) { + val pumpResponse = createResponseMessage(radioResponse.payload) + if (!pumpResponse.isValid) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Response is invalid ! [interrupted=%b, timeout=%b]", rfSpyResponse.wasInterrupted(), + rfSpyResponse.wasTimeout())) + } else { + + // radioResponse.rssi; + val dataResponse = medtronicConverter!!.convertResponse(medtronicPumpStatus.pumpType, MedtronicCommandType.PumpModel, + pumpResponse.rawContent) + val pumpModel = dataResponse as MedtronicDeviceType? + val valid = pumpModel !== MedtronicDeviceType.Unknown_Device + if (medtronicUtil.medtronicPumpModel == null && valid) { + medtronicUtil.medtronicPumpModel = pumpModel + } + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "isDeviceReachable. PumpModel is %s - Valid: %b (rssi=%d)", pumpModel!!.name, valid, + radioResponse.rssi)) + if (valid) { + if (state === PumpDeviceState.PumpUnreachable) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.WakingUp + else + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + rememberLastGoodDeviceCommunicationTime() + return true + } else { + if (state !== PumpDeviceState.PumpUnreachable) medtronicPumpStatus.pumpDeviceState = PumpDeviceState.PumpUnreachable + } + } + } else { + aapsLogger.warn(LTag.PUMPCOMM, "isDeviceReachable. Failed to parse radio response: " + + ByteUtil.shortHexString(rfSpyResponse.raw)) + } + } catch (e: RileyLinkCommunicationException) { + aapsLogger.warn(LTag.PUMPCOMM, "isDeviceReachable. Failed to decode radio response: " + + ByteUtil.shortHexString(rfSpyResponse.raw)) + } + } else { + aapsLogger.warn(LTag.PUMPCOMM, "isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.raw)) + } + return false + } + + override fun tryToConnectToDevice(): Boolean { + return isDeviceReachable(true) + } + + @Throws(RileyLinkCommunicationException::class) + private fun runCommandWithArgs(msg: PumpMessage): PumpMessage { + if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, "Run command with Args: ") + val rval: PumpMessage + val shortMessage = makePumpMessage(msg.commandType, CarelinkShortMessageBody(byteArrayOf(0))) + // look for ack from short message + val shortResponse = sendAndListen(shortMessage) + return if (shortResponse.commandType === MedtronicCommandType.CommandACK) { + if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, "Run command with Args: Got ACK response") + rval = sendAndListen(msg) + if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, "2nd Response: $rval") + rval + } else { + aapsLogger.error(LTag.PUMPCOMM, "runCommandWithArgs: Pump did not ack Attention packet") + PumpMessage(aapsLogger, "No ACK after Attention packet.") + } + } + + @Throws(RileyLinkCommunicationException::class) + private fun runCommandWithFrames(commandType: MedtronicCommandType, frames: List>): PumpMessage? { + aapsLogger.debug(LTag.PUMPCOMM, "Run command with Frames: " + commandType.name) + var rval: PumpMessage? = null + val shortMessage = makePumpMessage(commandType, CarelinkShortMessageBody(byteArrayOf(0))) + // look for ack from short message + val shortResponse = sendAndListen(shortMessage) + if (shortResponse.commandType !== MedtronicCommandType.CommandACK) { + aapsLogger.error(LTag.PUMPCOMM, "runCommandWithFrames: Pump did not ack Attention packet") + return PumpMessage(aapsLogger, "No ACK after start message.") + } else { + aapsLogger.debug(LTag.PUMPCOMM, "Run command with Frames: Got ACK response for Attention packet") + } + var frameNr = 1 + for (frame in frames) { + val frameData = createByteArray(frame) + + // aapsLogger.debug(LTag.PUMPCOMM,"Frame {} data:\n{}", frameNr, ByteUtil.getCompactString(frameData)); + val msg = makePumpMessage(commandType, CarelinkLongMessageBody(frameData)) + rval = sendAndListen(msg) + + // aapsLogger.debug(LTag.PUMPCOMM,"PumpResponse: " + rval); + if (rval.commandType !== MedtronicCommandType.CommandACK) { + aapsLogger.error(LTag.PUMPCOMM, "runCommandWithFrames: Pump did not ACK frame #$frameNr") + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Run command with Frames FAILED (command=%s, response=%s)", commandType.name, + rval.toString())) + return PumpMessage(aapsLogger, "No ACK after frame #$frameNr") + } else { + aapsLogger.debug(LTag.PUMPCOMM, "Run command with Frames: Got ACK response for frame #$frameNr") + } + frameNr++ + } + return rval + } + + fun getPumpHistory(lastEntry: PumpHistoryEntry?, targetDate: LocalDateTime?): PumpHistoryResult { + val pumpTotalResult = PumpHistoryResult(aapsLogger, lastEntry, if (targetDate == null) null else DateTimeUtil.toATechDate(targetDate)) + if (doWakeUpBeforeCommand) wakeUp(receiverDeviceAwakeForMinutes, false) + aapsLogger.debug(LTag.PUMPCOMM, "Current command: " + medtronicUtil.getCurrentCommand()) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Active + var doneWithError = false + for (pageNumber in 0..4) { + val rawHistoryPage = RawHistoryPage(aapsLogger) + // wakeUp(receiverDeviceAwakeForMinutes, false); + val getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData, + GetHistoryPageCarelinkMessageBody(pageNumber)) + aapsLogger.info(LTag.PUMPCOMM, "getPumpHistory: Page $pageNumber") + // aapsLogger.info(LTag.PUMPCOMM,"getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData())); + // Ask the pump to transfer history (we get first frame?) + var firstResponse: PumpMessage? = null + var failed = false + medtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber, null) + for (retries in 0 until MAX_COMMAND_TRIES) { + try { + firstResponse = runCommandWithArgs(getHistoryMsg) + failed = false + break + } catch (e: RileyLinkCommunicationException) { + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "First call for PumpHistory failed (retry=%d)", retries)) + failed = true + } + } + if (failed) { + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return pumpTotalResult + } + + // aapsLogger.info(LTag.PUMPCOMM,"getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents())); + val ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, PumpAckMessageBody()) + var currentResponse = GetHistoryPageCarelinkMessageBody(firstResponse!!.messageBody!!.txData) + var expectedFrameNum = 1 + var done = false + // while (expectedFrameNum == currentResponse.getFrameNumber()) { + var failures = 0 + while (!done) { + // examine current response for problems. + val frameData = currentResponse.frameData + if (frameData != null && frameData.size > 0 + && currentResponse.frameNumber == expectedFrameNum) { + // success! got a frame. + if (frameData.size != 64) { + aapsLogger.warn(LTag.PUMPCOMM, "Expected frame of length 64, got frame of length " + frameData.size) + // but append it anyway? + } + // handle successful frame data + rawHistoryPage.appendData(currentResponse.frameData) + // RileyLinkMedtronicService.getInstance().announceProgress(((100 / 16) * + // currentResponse.getFrameNumber() + 1)); + medtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber, + currentResponse.frameNumber) + aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Got frame %d of Page %d", currentResponse.frameNumber, pageNumber)) + // Do we need to ask for the next frame? + if (expectedFrameNum < 16) { // This number may not be correct for pumps other than 522/722 + expectedFrameNum++ + } else { + done = true // successful completion + } + } else { + if (frameData == null) { + aapsLogger.error(LTag.PUMPCOMM, "null frame data, retrying") + } else if (currentResponse.frameNumber != expectedFrameNum) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Expected frame number %d, received %d (retrying)", expectedFrameNum, + currentResponse.frameNumber)) + } else if (frameData.size == 0) { + aapsLogger.warn(LTag.PUMPCOMM, "Frame has zero length, retrying") + } + failures++ + if (failures == 6) { + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: 6 failures in attempting to download frame %d of page %d, giving up.", + expectedFrameNum, pageNumber)) + done = true // failure completion. + doneWithError = true + } + } + if (!done) { + // ask for next frame + var nextMsg: PumpMessage? = null + for (retries in 0 until MAX_COMMAND_TRIES) { + try { + nextMsg = sendAndListen(ackMsg) + break + } catch (e: RileyLinkCommunicationException) { + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Problem acknowledging frame response. (retry=%d)", retries)) + } + } + if (nextMsg != null) currentResponse = GetHistoryPageCarelinkMessageBody(nextMsg.messageBody!!.txData) else { + aapsLogger.error(LTag.PUMPCOMM, "We couldn't acknowledge frame from pump, aborting operation.") + } + } + } + if (rawHistoryPage.length != 1024) { + aapsLogger.warn(LTag.PUMPCOMM, "getPumpHistory: short page. Expected length of 1024, found length of " + + rawHistoryPage.length) + doneWithError = true + } + if (!rawHistoryPage.isChecksumOK) { + aapsLogger.error(LTag.PUMPCOMM, "getPumpHistory: checksum is wrong") + doneWithError = true + } + if (doneWithError) { + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return pumpTotalResult + } + rawHistoryPage.dumpToDebug() + val medtronicHistoryEntries = medtronicPumpHistoryDecoder.processPageAndCreateRecords(rawHistoryPage) + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Found %d history entries.", medtronicHistoryEntries.size)) + pumpTotalResult.addHistoryEntries(medtronicHistoryEntries, pageNumber) + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Search status: Search finished: %b", pumpTotalResult.isSearchFinished)) + if (pumpTotalResult.isSearchFinished) { + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return pumpTotalResult + } + } + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return pumpTotalResult + } + + override fun createPumpMessageContent(type: RLMessageType): ByteArray { + return when (type) { + RLMessageType.PowerOn -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.RFPowerOn, byteArrayOf(2, 1, receiverDeviceAwakeForMinutes.toByte())) // maybe this is better FIXME + RLMessageType.ReadSimpleData -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.PumpModel, null) + } + return ByteArray(0) + } + + private fun makePumpMessage(messageType: MedtronicCommandType, body: ByteArray? = null as ByteArray?): PumpMessage { + return makePumpMessage(messageType, body?.let { CarelinkShortMessageBody(it) } + ?: CarelinkShortMessageBody()) + } + + private fun makePumpMessage(messageType: MedtronicCommandType?, messageBody: MessageBody): PumpMessage { + val msg = PumpMessage(aapsLogger) + msg.init(PacketType.Carelink, rileyLinkServiceData.pumpIDBytes, messageType, messageBody) + return msg + } + + /** + * Main wrapper method for sending data - (for getting responses) + * + * @param commandType + * @param bodyData + * @param timeoutMs + * @return + */ + @Throws(RileyLinkCommunicationException::class) + private fun sendAndGetResponse(commandType: MedtronicCommandType, bodyData: ByteArray? = null, timeoutMs: Int = DEFAULT_TIMEOUT): PumpMessage { + // wakeUp + if (doWakeUpBeforeCommand) wakeUp(receiverDeviceAwakeForMinutes, false) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Active + + // create message + val msg: PumpMessage + msg = bodyData?.let { makePumpMessage(commandType, it) } ?: makePumpMessage(commandType) + + // send and wait for response + val response = sendAndListen(msg, timeoutMs) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return response + } + + @Throws(RileyLinkCommunicationException::class) + private fun sendAndListen(msg: PumpMessage): PumpMessage { + return sendAndListen(msg, 4000) // 2000 + } + + // All pump communications go through this function. + @Throws(RileyLinkCommunicationException::class) + protected /*override*/ fun sendAndListen(msg: PumpMessage, timeout_ms: Int): PumpMessage { + return super.sendAndListen(msg, timeout_ms)!! + } + + private fun sendAndGetResponseWithCheck(commandType: MedtronicCommandType, bodyData: ByteArray? = null): Any? { + aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") + for (retries in 0 until MAX_COMMAND_TRIES) { + try { + val response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * retries) + val check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength) + if (check == null) { + val dataResponse = medtronicConverter.convertResponse(medtronicPumpStatus.pumpType, commandType, response.rawContent) + if (dataResponse != null) { + errorResponse = null + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, dataResponse)) + return dataResponse + } else { + errorResponse = "Error decoding response." + } + } else { + errorResponse = check + // return null; + } + } catch (e: RileyLinkCommunicationException) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.message, retries + 1)) + } + } + return null + } + + // private fun sendAndGetResponseWithCheck(commandType: MedtronicCommandType, bodyData: ByteArray, clazz: Class): T? { + // aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") + // for (retries in 0 until MAX_COMMAND_TRIES) { + // try { + // val response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * retries) + // val check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength) + // if (check == null) { + // val dataResponse = medtronicConverter!!.convertResponse(medtronicPumpPlugin!!.pumpDescription.pumpType, commandType, response.rawContent) as T? + // if (dataResponse != null) { + // errorResponse = null + // aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, dataResponse)) + // return dataResponse + // } else { + // errorResponse = "Error decoding response." + // } + // } else { + // errorResponse = check + // // return null; + // } + // } catch (e: RileyLinkCommunicationException) { + // aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.message, retries + 1)) + // } + // } + // return null + // } + + private fun checkResponseContent(response: PumpMessage, method: String, expectedLength: Int): String? { + if (!response.isValid) { + val responseData = String.format("%s: Invalid response.", method) + aapsLogger.warn(LTag.PUMPCOMM, responseData) + return responseData + } + val contents = response.rawContent + return if (contents != null) { + if (contents.size >= expectedLength) { + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: Content: %s", method, ByteUtil.shortHexString(contents))) + null + } else { + val responseData = String.format( + "%s: Cannot return data. Data is too short [expected=%s, received=%s].", method, "" + + expectedLength, "" + contents.size) + aapsLogger.warn(LTag.PUMPCOMM, responseData) + responseData + } + } else { + val responseData = String.format("%s: Cannot return data. Null response.", method) + aapsLogger.warn(LTag.PUMPCOMM, responseData) + responseData + } + } + + // PUMP SPECIFIC COMMANDS + fun getRemainingInsulin(): Double? { + val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin) + return if (responseObject == null) null else responseObject as Double? + } + + fun getPumpModel(): MedtronicDeviceType? { + val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel) + return if (responseObject == null) null else responseObject as MedtronicDeviceType? + } + + + + fun getBasalProfile(): BasalProfile? { + + // wakeUp + if (doWakeUpBeforeCommand) wakeUp(receiverDeviceAwakeForMinutes, false) + val commandType = MedtronicCommandType.GetBasalProfileSTD + aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") + medtronicUtil.setCurrentCommand(commandType) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Active + for (retries in 0..MAX_COMMAND_TRIES) { + try { + // create message + var msg: PumpMessage + msg = makePumpMessage(commandType) + + // send and wait for response + var response = sendAndListen(msg, DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * retries) + +// aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent())); +// aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData())); + val check = checkResponseContent(response, commandType.commandDescription, 1) + var data: ByteArray? = null + if (check == null) { + data = response.rawContentOfFrame + val ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, PumpAckMessageBody()) + while (checkIfWeHaveMoreData(commandType, response, data)) { + response = sendAndListen(ackMsg, DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * retries) + +// aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs, HexDump.toHexStringDisplayable(response2.getRawContent())); +// aapsLogger.debug(LTag.PUMPCOMM,"{} Response: {}", runs, +// HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData())); + val check2 = checkResponseContent(response, commandType.commandDescription, 1) + if (check2 == null) { + data = ByteUtil.concat(data, response.rawContentOfFrame) + } else { + errorResponse = check2 + aapsLogger.error(LTag.PUMPCOMM, "Error with response got GetProfile: $check2") + } + } + } else { + errorResponse = check + } + val basalProfile = medtronicConverter.convertResponse(medtronicPumpPlugin.pumpType, commandType, data) as BasalProfile? + if (basalProfile != null) { + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, basalProfile)) + medtronicUtil.setCurrentCommand(null) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return basalProfile + } + } catch (e: RileyLinkCommunicationException) { + aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.message, retries + 1)) + } + } + aapsLogger.warn(LTag.PUMPCOMM, "Error reading profile in max retries.") + medtronicUtil.setCurrentCommand(null) + medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping + return null + } + + private fun checkIfWeHaveMoreData(commandType: MedtronicCommandType, response: PumpMessage, data: ByteArray?): Boolean { + if (commandType === MedtronicCommandType.GetBasalProfileSTD || // + commandType === MedtronicCommandType.GetBasalProfileA || // + commandType === MedtronicCommandType.GetBasalProfileB) { + val responseRaw = response.rawContentOfFrame + val last = responseRaw.size - 1 + aapsLogger.debug(LTag.PUMPCOMM, "Length: " + data!!.size) + if (data.size >= BasalProfile.MAX_RAW_DATA_SIZE) { + return false + } + return if (responseRaw.size < 2) { + false + } else !(responseRaw[last] == 0x00.toByte() && responseRaw[last - 1] == 0x00.toByte() && responseRaw[last - 2] == 0x00.toByte()) + } + return false + } + + fun getPumpTime(): ClockDTO? { + val clockDTO = ClockDTO() + clockDTO.localDeviceTime = LocalDateTime() + val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock) + if (responseObject != null) { + clockDTO.pumpTime = responseObject as LocalDateTime? + return clockDTO + } + return null + } + + fun getTemporaryBasal(): TempBasalPair? { + val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal) + return if (responseObject == null) null else responseObject as TempBasalPair? + } + + fun getPumpSettings(): Map? { + val responseObject = sendAndGetResponseWithCheck(getSettings(medtronicUtil.medtronicPumpModel)) + return if (responseObject == null) null else responseObject as Map? + } + + fun setBolus(units: Double): Boolean { + aapsLogger.info(LTag.PUMPCOMM, "setBolus: $units") + return setCommand(MedtronicCommandType.SetBolus, medtronicUtil.getBolusStrokes(units)) + } + + fun setTemporaryBasal(tbr: TempBasalPair): Boolean { + aapsLogger.info(LTag.PUMPCOMM, "setTBR: " + tbr.description) + return setCommand(MedtronicCommandType.SetTemporaryBasal, tbr.asRawData) + } + + fun setPumpTime(): Boolean { + val gc = GregorianCalendar() + gc.add(Calendar.SECOND, 5) + aapsLogger.info(LTag.PUMPCOMM, "setPumpTime: " + DateTimeUtil.toString(gc)) + val i = 1 + val data = ByteArray(8) + data[0] = 7 + data[i] = gc[Calendar.HOUR_OF_DAY].toByte() + data[i + 1] = gc[Calendar.MINUTE].toByte() + data[i + 2] = gc[Calendar.SECOND].toByte() + val yearByte = getByteArrayFromUnsignedShort(gc[Calendar.YEAR], true) + data[i + 3] = yearByte[0] + data[i + 4] = yearByte[1] + data[i + 5] = (gc[Calendar.MONTH] + 1).toByte() + data[i + 6] = gc[Calendar.DAY_OF_MONTH].toByte() + + //aapsLogger.info(LTag.PUMPCOMM,"setPumpTime: Body: " + ByteUtil.getHex(data)); + return setCommand(MedtronicCommandType.SetRealTimeClock, data) + } + + private fun setCommand(commandType: MedtronicCommandType, body: ByteArray): Boolean { + for (retries in 0..MAX_COMMAND_TRIES) { + try { + if (doWakeUpBeforeCommand) wakeUp(false) + if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: Body - %s", commandType.commandDescription, + ByteUtil.getHex(body))) + val msg = makePumpMessage(commandType, CarelinkLongMessageBody(body)) + val pumpMessage = runCommandWithArgs(msg) + if (debugSetCommands) aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: %s", commandType.commandDescription, pumpMessage.responseContent)) + if (pumpMessage.commandType === MedtronicCommandType.CommandACK) { + return true + } else { + aapsLogger.warn(LTag.PUMPCOMM, "We received non-ACK response from pump: " + pumpMessage.responseContent) + } + } catch (e: RileyLinkCommunicationException) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.message, retries + 1)) + } + } + return false + } + + fun cancelTBR(): Boolean { + return setTemporaryBasal(TempBasalPair(0.0, false, 0)) + } + + fun getRemainingBattery(): BatteryStatusDTO? { + val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus) + return if (responseObject == null) null else responseObject as BatteryStatusDTO? + } + + fun setBasalProfile(basalProfile: BasalProfile): Boolean { + val basalProfileFrames = medtronicUtil.getBasalProfileFrames(basalProfile.rawData) + for (retries in 0..MAX_COMMAND_TRIES) { + var responseMessage: PumpMessage? = null + try { + responseMessage = runCommandWithFrames(MedtronicCommandType.SetBasalProfileSTD, + basalProfileFrames) + if (responseMessage!!.commandType === MedtronicCommandType.CommandACK) return true + } catch (e: RileyLinkCommunicationException) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.message, retries + 1)) + } + if (responseMessage != null) aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Set Basal Profile: Invalid response: commandType=%s,rawData=%s", responseMessage.commandType, ByteUtil.shortHexString(responseMessage.rawContent))) else aapsLogger.warn(LTag.PUMPCOMM, "Set Basal Profile: Null response.") + } + return false + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 57bc0eab11..0a4db88ede 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -51,7 +51,7 @@ abstract class MedtronicHistoryDecoder : MedtronicHi } } - fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): List? { + fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): List { return processPageAndCreateRecords(rawHistoryPage, false) } @@ -120,7 +120,7 @@ abstract class MedtronicHistoryDecoder : MedtronicHi private fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage, partial: Boolean): List { val dataClear = checkPage(rawHistoryPage, partial) val records: List = createRecords(dataClear) - for (record in records!!) { + for (record in records) { decodeRecord(record) } runPostDecodeTasks() diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index 77f1ee32c1..83a20262cc 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -25,14 +25,14 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() override fun decodeRecord(record: CGMSHistoryEntry): RecordDecodeStatus? { return try { - decodeRecord(record, false) + decodeRecordInternal(record) } catch (ex: Exception) { LOG.error(" Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) RecordDecodeStatus.Error } } - fun decodeRecord(entry: CGMSHistoryEntry, ignore: Boolean): RecordDecodeStatus { + fun decodeRecordInternal(entry: CGMSHistoryEntry): RecordDecodeStatus { if (entry.dateTimeLength > 0) { parseDate(entry) } @@ -62,6 +62,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() } override fun postProcess() {} + override fun createRecords(dataClearInput: List): List { val dataClear = reverseList(dataClearInput, Byte::class.java) prepareStatistics() diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index 0a2da5b5be..e9131694d2 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -79,7 +79,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( listRawData.add(opCode.toByte()) if (entryType === PumpHistoryEntryType.UnabsorbedInsulin || entryType === PumpHistoryEntryType.UnabsorbedInsulin512) { - val elements: Int = dataClear[counter]!!.toInt() + val elements: Int = dataClear[counter].toInt() listRawData.add(elements.toByte()) counter++ val els = getUnsignedInt(elements) @@ -106,12 +106,12 @@ class MedtronicPumpHistoryDecoder @Inject constructor( if (incompletePacket) break } if (entryType === PumpHistoryEntryType.None) { - aapsLogger!!.error(LTag.PUMPBTCOMM, "Error in code. We should have not come into this branch.") + aapsLogger.error(LTag.PUMPBTCOMM, "Error in code. We should have not come into this branch.") } else { if (pe.entryType === PumpHistoryEntryType.UnknownBasePacket) { 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, special) val decoded = decodeRecord(pe) if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { @@ -132,7 +132,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( override fun decodeRecord(record: PumpHistoryEntry): RecordDecodeStatus? { return try { - decodeRecord(record, false) + decodeRecordInternal(record) } catch (ex: Exception) { aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.entryType!!.name, ex.message, ex)) //ex.printStackTrace() @@ -140,7 +140,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } } - private fun decodeRecord(entry: PumpHistoryEntry, x: Boolean): RecordDecodeStatus { + private fun decodeRecordInternal(entry: PumpHistoryEntry): RecordDecodeStatus { if (entry.dateTimeLength > 0) { decodeDateTime(entry) } @@ -169,6 +169,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( PumpHistoryEntryType.TempBasalDuration -> // decodeTempBasal(entry); RecordDecodeStatus.OK + PumpHistoryEntryType.TempBasalRate -> // decodeTempBasal(entry); RecordDecodeStatus.OK @@ -254,7 +255,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val body = entry.body!! val dto = BolusWizardDTO() 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 bolusStrokes = 40.0f dto.carbs = ((body[1] and 0x0c.toByte()).toInt() shl 6) + body[0] diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index 7cb40c46e6..a5a7cbfaa8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -69,10 +69,10 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { override val dateLength: Int get() = entryType!!.dateLength - override fun equals(o: Any?): Boolean { - if (this === o) return true - if (o !is PumpHistoryEntry) return false - val that = o + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is PumpHistoryEntry) return false + val that = other return entryType == that.entryType && // atechDateTime === that.atechDateTime // && // // Objects.equals(this.decodedData, that.decodedData); diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt index b772119de8..09d694f061 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt @@ -81,8 +81,8 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis } override fun toString(): String { - return "PumpHistoryResult [unprocessed=" + (if (unprocessedEntries != null) "" + unprocessedEntries!!.size else "0") + // - ", valid=" + (if (validEntries != null) "" + validEntries!!.size else "0") + // + return "PumpHistoryResult [unprocessed=" + unprocessedEntries.size + // + ", valid=" + validEntries.size + // ", searchEntry=" + searchEntry + // ", searchDate=" + searchDate + // ", searchType=" + searchType + // diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt index 815ca14549..addcd5d2c3 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt @@ -53,19 +53,19 @@ class MedtronicUITask { aapsLogger.debug(LTag.PUMP, "MedtronicUITask: @@@ In execute. $commandType") when (commandType) { MedtronicCommandType.PumpModel -> { - result = communicationManager.pumpModel + result = communicationManager.getPumpModel() } MedtronicCommandType.GetBasalProfileSTD -> { - result = communicationManager.basalProfile + result = communicationManager.getBasalProfile() } MedtronicCommandType.GetRemainingInsulin -> { - result = communicationManager.remainingInsulin + result = communicationManager.getRemainingInsulin() } MedtronicCommandType.GetRealTimeClock -> { - result = communicationManager.pumpTime + result = communicationManager.getPumpTime() medtronicUtil.pumpTime = null } @@ -74,22 +74,22 @@ class MedtronicUITask { } MedtronicCommandType.GetBatteryStatus -> { - result = communicationManager.remainingBattery + result = communicationManager.getRemainingBattery() } MedtronicCommandType.SetTemporaryBasal -> { - val tbr = tBRSettings + val tbr = getTbrSettings() if (tbr != null) { - result = communicationManager.setTBR(tbr) + result = communicationManager.setTemporaryBasal(tbr) } } MedtronicCommandType.ReadTemporaryBasal -> { - result = communicationManager.temporaryBasal + result = communicationManager.getTemporaryBasal() } MedtronicCommandType.Settings, MedtronicCommandType.Settings_512 -> { - result = communicationManager.pumpSettings + result = communicationManager.getPumpSettings() } MedtronicCommandType.SetBolus -> { @@ -127,12 +127,11 @@ class MedtronicUITask { } } - // - // - private val tBRSettings: TempBasalPair - private get() = TempBasalPair(getDoubleFromParameters(0), // + private fun getTbrSettings(): TempBasalPair? { + return TempBasalPair(getDoubleFromParameters(0), // false, // getIntegerFromParameters(1)) + } private fun getFloatFromParameters(index: Int): Float { return parameters!![index] as Float diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt index 92720b72f2..b1af19654a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -96,7 +96,7 @@ class BasalProfile { fun dumpBasalProfile() { aapsLogger.debug(LTag.PUMPCOMM, "Basal Profile entries:") - val entries = entries + val entries = getEntries() for (i in entries.indices) { val entry = entries[i] val startString = entry.startTime!!.toString("HH:mm") @@ -109,7 +109,7 @@ class BasalProfile { val basalProfileAsString: String get() { val sb = StringBuffer("Basal Profile entries:\n") - val entries = entries + val entries = getEntries() for (i in entries.indices) { val entry = entries[i] val startString = entry.startTime!!.toString("HH:mm") @@ -124,7 +124,7 @@ class BasalProfile { fun basalProfileToString(): String { val sb = StringBuffer("Basal Profile [") - val entries = entries + val entries = getEntries() for (i in entries.indices) { val entry = entries[i] val startString = entry.startTime!!.toString("HH:mm") @@ -138,7 +138,7 @@ class BasalProfile { // and changes to the profiles themselves. fun getEntryForTime(`when`: Instant): BasalProfileEntry { var rval = BasalProfileEntry() - val entries = entries + val entries = getEntries() if (entries.size == 0) { aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getEntryForTime(%s): table is empty", `when`.toDateTime().toLocalTime().toString("HH:mm"))) @@ -181,31 +181,30 @@ class BasalProfile { }// readUnsignedByte(mRawData[i]); // an empty list - val entries: List - get() { - val entries: MutableList = ArrayList() - if (rawData == null || rawData!![2] == 0x3f.toByte()) { - aapsLogger.warn(LTag.PUMPCOMM, "Raw Data is empty.") - return entries // an empty list - } - var r: Int - var st: Int - var i = 0 - while (i < rawData!!.size - 2) { - if (rawData!![i] == 0.toByte() && rawData!![i + 1] == 0.toByte() && rawData!![i + 2] == 0.toByte()) break - if (rawData!![i] == 0.toByte() && rawData!![i + 1] == 0.toByte() && rawData!![i + 2] == 0x3f.toByte()) break - r = MedtronicUtil.makeUnsignedShort(rawData!![i + 1].toInt(), rawData!![i].toInt()) // readUnsignedByte(mRawData[i]); - st = readUnsignedByte(rawData!![i + 2]) - try { - entries.add(BasalProfileEntry(aapsLogger, r, st)) - } catch (ex: Exception) { - aapsLogger.error(LTag.PUMPCOMM, "Error decoding basal profile from bytes: " + ByteUtil.shortHexString(rawData)) - throw ex - } - i += 3 - } - return entries + fun getEntries(): List { + val entries: MutableList = ArrayList() + if (rawData[2] == 0x3f.toByte()) { + aapsLogger.warn(LTag.PUMPCOMM, "Raw Data is empty.") + return entries // an empty list } + var r: Int + var st: Int + var i = 0 + while (i < rawData.size - 2) { + if (rawData[i] == 0.toByte() && rawData[i + 1] == 0.toByte() && rawData[i + 2] == 0.toByte()) break + if (rawData[i] == 0.toByte() && rawData[i + 1] == 0.toByte() && rawData[i + 2] == 0x3f.toByte()) break + r = MedtronicUtil.makeUnsignedShort(rawData[i + 1].toInt(), rawData[i].toInt()) // readUnsignedByte(mRawData[i]); + st = readUnsignedByte(rawData[i + 2]) + try { + entries.add(BasalProfileEntry(aapsLogger, r, st)) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMPCOMM, "Error decoding basal profile from bytes: " + ByteUtil.shortHexString(rawData)) + throw ex + } + i += 3 + } + return entries + } /** * This is used to prepare new profile @@ -233,7 +232,7 @@ class BasalProfile { fun getProfilesByHour(pumpType: PumpType): Array { var entriesCopy: List? = null try { - entriesCopy = entries + entriesCopy = getEntries() } catch (ex: Exception) { aapsLogger.error(LTag.PUMPCOMM, "=============================================================================") aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: $ex", ex) @@ -280,7 +279,7 @@ class BasalProfile { fun verify(pumpType: PumpType): Boolean { try { - entries + getEntries() } catch (ex: Exception) { return false } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt index e5a047ab97..c1e08c7f18 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt @@ -38,14 +38,14 @@ class MedtronicHistoryActivity : DaggerActivity() { var manualChange = false var typeListFull: List? = null - private var _binding: MedtronicHistoryActivityBinding? = null + //private var _binding: MedtronicHistoryActivityBinding? = null //@Inject //var fragmentInjector: DispatchingAndroidInjector? = null // This property is only valid between onCreateView and // onDestroyView. - private val binding get() = _binding!! + //private val binding get() = _binding!! private fun filterHistory(group: PumpHistoryEntryGroup) { filteredHistoryList.clear() @@ -93,20 +93,17 @@ class MedtronicHistoryActivity : DaggerActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - //setContentView(R.layout.medtronic_history_activity) - - _binding = MedtronicHistoryActivityBinding.inflate(getLayoutInflater()) //(inflater, container, false) - - historyTypeSpinner = binding.medtronicHistorytype //findViewById(R.id.medtronic_historytype) - statusView = binding.medtronicHistorystatus //findViewById(R.id.medtronic_historystatus) - recyclerView = binding.medtronicHistoryRecyclerview //findViewById(R.id.medtronic_history_recyclerview) + setContentView(R.layout.medtronic_history_activity) + historyTypeSpinner = findViewById(R.id.medtronic_historytype) + statusView = findViewById(R.id.medtronic_historystatus) + recyclerView = findViewById(R.id.medtronic_history_recyclerview) recyclerView.setHasFixedSize(true) llm = LinearLayoutManager(this) recyclerView.setLayoutManager(llm) recyclerViewAdapter = RecyclerViewAdapter(filteredHistoryList) recyclerView.setAdapter(recyclerViewAdapter) statusView.setVisibility(View.GONE) - typeListFull = getTypeList(getTranslatedList(resourceHelper!!)) + typeListFull = getTypeList(PumpHistoryEntryGroup.getTranslatedList(resourceHelper)) val spinnerAdapter = ArrayAdapter(this, R.layout.spinner_centered, typeListFull) historyTypeSpinner.setAdapter(spinnerAdapter) historyTypeSpinner.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener { @@ -163,11 +160,11 @@ class MedtronicHistoryActivity : DaggerActivity() { override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) { val record = historyList[position] - if (record != null) { + //if (record != null) { holder.timeView.text = record.dateTimeString holder.typeView.text = record.entryType!!.description holder.valueView.text = record.displayableValue - } + //} } override fun getItemCount(): Int { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt index b753ac5795..3fe1eb4d8e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt @@ -108,8 +108,8 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { return i.toLong() } - override fun getView(i: Int, view: View, viewGroup: ViewGroup): View { - var view = view + override fun getView(i: Int, viewIn: View, viewGroup: ViewGroup): View { + var view = viewIn val viewHolder: ViewHolder // General ListView optimization code. if (view == null) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt index 205742a336..d8fb29c42a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -164,6 +164,7 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi } else { val pumpType = medtronicPumpStatus.medtronicPumpMap[pumpTypePart] medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.medtronicDeviceTypeMap[pumpTypePart] + medtronicPumpStatus.pumpType = pumpType!! medtronicPumpPlugin.pumpType = pumpType if (pumpTypePart.startsWith("7")) medtronicPumpStatus.reservoirFullUnits = 300 else medtronicPumpStatus.reservoirFullUnits = 176 } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt index ac690be476..72574a99b0 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt @@ -291,10 +291,10 @@ class MedtronicUtil @Inject constructor( } fun getStrokesInt(amount: Double, strokesPerUnit: Int): Int { - var length = 1 + //var length = 1 var scrollRate = 1 if (strokesPerUnit >= 40) { - length = 2 + // length = 2 // 40-stroke pumps scroll faster for higher unit values if (amount > 10) scrollRate = 4 else if (amount > 1) scrollRate = 2 From 28c0f1b8940ecdb877b8c0d28eecd37d3af7daec Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 24 Apr 2021 19:11:01 +0100 Subject: [PATCH 08/39] - all files kotlinized - started some refactoring - added adrians refactoring of MedtronicCommunicationManager --- .../nightscout/androidaps/db/DbObjectBase.kt | 4 +- medtronic/build.gradle | 3 - .../pump/medtronic/MedtronicPumpPlugin.kt | 55 +- .../comm/MedtronicCommunicationManager.kt | 101 +- .../pump/medtronic/comm/MedtronicConverter.kt | 112 +- .../comm/history/MedtronicHistoryDecoder.kt | 16 +- .../MedtronicHistoryDecoderInterface.kt | 2 +- .../cgms/MedtronicCGMSHistoryDecoder.kt | 26 +- .../pump/MedtronicPumpHistoryDecoder.kt | 4 +- .../pump/medtronic/comm/ui/MedtronicUIComm.kt | 15 +- .../medtronic/data/MedtronicHistoryData.java | 1590 ----------------- .../medtronic/data/MedtronicHistoryData.kt | 1152 ++++++++++++ .../pump/medtronic/data/dto/BasalProfile.kt | 29 +- .../medtronic/defs/MedtronicCommandType.kt | 86 +- .../medtronic/defs/MedtronicDeviceType.kt | 39 +- .../pump/medtronic/di/MedtronicModule.kt | 3 + .../service/RileyLinkMedtronicService.kt | 7 +- 17 files changed, 1409 insertions(+), 1835 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java create mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt diff --git a/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt b/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt index 76228abe9b..e8e4be360f 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt +++ b/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt @@ -2,6 +2,6 @@ package info.nightscout.androidaps.db interface DbObjectBase { - val date: Long - val pumpId: Long + fun getDate(): Long + fun getPumpId(): Long } \ No newline at end of file diff --git a/medtronic/build.gradle b/medtronic/build.gradle index 0488efd078..a3cb9f789e 100644 --- a/medtronic/build.gradle +++ b/medtronic/build.gradle @@ -12,9 +12,6 @@ android { versionCode 1 versionName "1.0" } - dataBinding { - enabled = true - } } dependencies { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 64bb650744..a32a8937e2 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -364,13 +364,13 @@ class MedtronicPumpPlugin @Inject constructor( } MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.RemainingInsulin -> { - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) refreshTypesNeededToReschedule.add(key) resetTime = true } MedtronicStatusRefreshType.Configuration -> { - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) resetTime = true } } @@ -415,7 +415,7 @@ class MedtronicPumpPlugin @Inject constructor( // model (once) if (medtronicUtil.medtronicPumpModel == null) { - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.PumpModel) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel) } else { if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) { aapsLogger.warn(LTag.PUMP, logPrefix + "Configured pump is not the same as one detected.") @@ -429,19 +429,19 @@ class MedtronicPumpPlugin @Inject constructor( readPumpHistory() // remaining insulin (>50 = 4h; 50-20 = 1h; 15m) - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetRemainingInsulin) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin) scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10) // remaining power (1h) - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetBatteryStatus) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus) scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20) // configuration (once and then if history shows config changes) - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) // read profile (once, later its controlled by isThisProfileSet method) basalProfiles - val errorCount = rileyLinkMedtronicService!!.medtronicUIComm!!.invalidResponsesCount + val errorCount = rileyLinkMedtronicService!!.medtronicUIComm.invalidResponsesCount if (errorCount >= 5) { aapsLogger.error("Number of error counts was 5 or more. Starting tunning.") setRefreshButtonEnabled(true) @@ -461,9 +461,9 @@ class MedtronicPumpPlugin @Inject constructor( private val basalProfiles: Unit private get() { - val medtronicUITask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + val medtronicUITask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) if (medtronicUITask.responseType === MedtronicUIResponseType.Error) { - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) } } @@ -492,7 +492,7 @@ class MedtronicPumpPlugin @Inject constructor( for (basalValue in profile.basalValues) { val basalValueValue = pumpDescription.pumpType.determineCorrectBasalSize(basalValue.value) val hour = basalValue.timeAsSeconds / (60 * 60) - if (!isSame(basalsByHour[hour]!!, basalValueValue)) { + if (!isSame(basalsByHour[hour], basalValueValue)) { invalid = true } stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) @@ -551,10 +551,10 @@ class MedtronicPumpPlugin @Inject constructor( return } medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetRealTimeClock) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) var clock = medtronicUtil.pumpTime if (clock == null) { // retry - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetRealTimeClock) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) clock = medtronicUtil.pumpTime } if (clock == null) return @@ -562,7 +562,7 @@ class MedtronicPumpPlugin @Inject constructor( if (timeDiff > 20) { if (clock.localDeviceTime!!.year <= 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)) - rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetRealTimeClock) + rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock) if (clock.timeDifference == 0) { val notification = Notification(Notification.INSIGHT_DATE_TIME_UPDATED, resourceHelper.gs(R.string.pump_time_updated), Notification.INFO, 60) rxBus.send(EventNewNotification(notification)) @@ -611,8 +611,8 @@ class MedtronicPumpPlugin @Inject constructor( bolusDeliveryType = BolusDeliveryType.Delivering // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetBolus, - Arrays.asList(detailedBolusInfo.insulin)) + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, + arrayListOf(detailedBolusInfo.insulin)) val response = responseTask.result as Boolean? setRefreshButtonEnabled(true) @@ -621,12 +621,7 @@ class MedtronicPumpPlugin @Inject constructor( if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled after Bolus started."); Thread(Runnable { - - // Looper.prepare(); - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog - before"); SystemClock.sleep(2000) - // LOG.debug("MedtronicPumpPlugin::deliverBolus - Show dialog. Context: " - // + MainApp.instance().getApplicationContext()); runAlarm(context, resourceHelper.gs(R.string.medtronic_cmd_cancel_bolus_not_supported), resourceHelper.gs(R.string.medtronic_warning), R.raw.boluserror) }).start() } @@ -743,7 +738,7 @@ class MedtronicPumpPlugin @Inject constructor( aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - TBR running - so canceling it.") // CANCEL - val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.CancelTBR) + val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) val response = responseTask2.result as Boolean? if (response!!) { aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") @@ -756,8 +751,8 @@ class MedtronicPumpPlugin @Inject constructor( } // now start new TBR - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetTemporaryBasal, - Arrays.asList(absoluteRate, durationInMinutes)) + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal, + arrayListOf(absoluteRate, durationInMinutes)) val response = responseTask.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - setTBR. Response: " + response) return if (response!!) { @@ -853,7 +848,7 @@ class MedtronicPumpPlugin @Inject constructor( } else { // LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime); if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: " + lastPumpHistoryEntryTime + " - targetDate: " + targetDate) - medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntryTime) + //medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntryTime) var lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime) lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12) // we get last 12 hours of history to // determine pump state @@ -873,8 +868,8 @@ class MedtronicPumpPlugin @Inject constructor( } //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); - val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.GetHistoryData, - Arrays.asList(lastPumpHistoryEntry, targetDate) as List?) + val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData, + arrayListOf(lastPumpHistoryEntry, targetDate) as ArrayList?) if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task") val historyResult = responseTask2.result as PumpHistoryResult? if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString()) @@ -971,7 +966,7 @@ class MedtronicPumpPlugin @Inject constructor( } private fun readTBR(): TempBasalPair? { - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.ReadTemporaryBasal) + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal) return if (responseTask.hasData()) { val tbr = responseTask.result as TempBasalPair? @@ -1009,7 +1004,7 @@ class MedtronicPumpPlugin @Inject constructor( return PumpEnactResult(injector).success(false).enacted(false) .comment(R.string.medtronic_cmd_cant_read_tbr) } - val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.CancelTBR) + val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) val response = responseTask2.result as Boolean? finishAction("TBR") return if (response!!) { @@ -1070,8 +1065,8 @@ class MedtronicPumpPlugin @Inject constructor( .enacted(false) // .comment(resourceHelper.gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid)) } - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm!!.executeCommand(MedtronicCommandType.SetBasalProfileSTD, - Arrays.asList(basalProfile)) + val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetBasalProfileSTD, + arrayListOf(basalProfile)) val response = responseTask.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "Basal Profile was set: " + response) return if (response!!) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index e913ff52f7..531e6f3422 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm import android.os.SystemClock 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.RileyLinkCommunicationManager import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkCommunicationException @@ -64,7 +65,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth private var doWakeUpBeforeCommand = true @Inject - open fun onInit(): Unit { + fun onInit(): Unit { // we can't do this in the constructor, as sp only gets injected after the constructor has returned medtronicPumpStatus.previousConnection = sp.getLong( RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L) @@ -133,8 +134,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } else { // radioResponse.rssi; - val dataResponse = medtronicConverter!!.convertResponse(medtronicPumpStatus.pumpType, MedtronicCommandType.PumpModel, - pumpResponse.rawContent) + val dataResponse = medtronicConverter.decodeModel(pumpResponse.rawContent) val pumpModel = dataResponse as MedtronicDeviceType? val valid = pumpModel !== MedtronicDeviceType.Unknown_Device if (medtronicUtil.medtronicPumpModel == null && valid) { @@ -350,11 +350,11 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth return when (type) { RLMessageType.PowerOn -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.RFPowerOn, byteArrayOf(2, 1, receiverDeviceAwakeForMinutes.toByte())) // maybe this is better FIXME RLMessageType.ReadSimpleData -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.PumpModel, null) + else -> ByteArray(0) } - return ByteArray(0) } - private fun makePumpMessage(messageType: MedtronicCommandType, body: ByteArray? = null as ByteArray?): PumpMessage { + private fun makePumpMessage(messageType: MedtronicCommandType, body: ByteArray? = null): PumpMessage { return makePumpMessage(messageType, body?.let { CarelinkShortMessageBody(it) } ?: CarelinkShortMessageBody()) } @@ -400,14 +400,21 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth return super.sendAndListen(msg, timeout_ms)!! } - private fun sendAndGetResponseWithCheck(commandType: MedtronicCommandType, bodyData: ByteArray? = null): Any? { + private inline fun sendAndGetResponseWithCheck( + commandType: MedtronicCommandType, + bodyData: ByteArray? = null, + decode: (pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray?) -> T + ): T? { aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") for (retries in 0 until MAX_COMMAND_TRIES) { try { val response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * retries) val check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength) if (check == null) { - val dataResponse = medtronicConverter.convertResponse(medtronicPumpStatus.pumpType, commandType, response.rawContent) + + checkResponseRawContent(response.rawContent, commandType) { return@sendAndGetResponseWithCheck null } + + val dataResponse = decode(medtronicPumpStatus.pumpType, commandType, response.rawContent) if (dataResponse != null) { errorResponse = null aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, dataResponse)) @@ -426,6 +433,16 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth return null } + private inline fun checkResponseRawContent(rawContent: ByteArray?, commandType: MedtronicCommandType, errorCase: () -> Unit) { + if (rawContent?.isEmpty() != false && commandType != MedtronicCommandType.PumpModel) { + aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Content is empty or too short, no data to convert (type=%s,isNull=%b,length=%s)", + commandType.name, rawContent == null, rawContent?.size ?: "-")) + errorCase.invoke() + } else { + aapsLogger.debug(LTag.PUMPCOMM, "Raw response before convert: " + ByteUtil.shortHexString(rawContent)) + } + } + // private fun sendAndGetResponseWithCheck(commandType: MedtronicCommandType, bodyData: ByteArray, clazz: Class): T? { // aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") // for (retries in 0 until MAX_COMMAND_TRIES) { @@ -479,13 +496,15 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth // PUMP SPECIFIC COMMANDS fun getRemainingInsulin(): Double? { - val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin) - return if (responseObject == null) null else responseObject as Double? + return sendAndGetResponseWithCheck(MedtronicCommandType.GetRemainingInsulin) { _, _, rawContent -> + medtronicConverter.decodeRemainingInsulin(rawContent) + } } fun getPumpModel(): MedtronicDeviceType? { - val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel) - return if (responseObject == null) null else responseObject as MedtronicDeviceType? + return sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel) { _, _, rawContent -> + medtronicConverter.decodeModel(rawContent) + } } @@ -531,7 +550,12 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } else { errorResponse = check } - val basalProfile = medtronicConverter.convertResponse(medtronicPumpPlugin.pumpType, commandType, data) as BasalProfile? + + var basalProfile: BasalProfile? = null + checkResponseRawContent(data, commandType) { + basalProfile = medtronicConverter.decodeBasalProfile(medtronicPumpPlugin.pumpDescription.pumpType, data) + } + if (basalProfile != null) { aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, basalProfile)) medtronicUtil.setCurrentCommand(null) @@ -568,22 +592,24 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth fun getPumpTime(): ClockDTO? { val clockDTO = ClockDTO() clockDTO.localDeviceTime = LocalDateTime() - val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock) + val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock) { _, _, rawContent -> + medtronicConverter.decodeTime(rawContent) + } if (responseObject != null) { - clockDTO.pumpTime = responseObject as LocalDateTime? + clockDTO.pumpTime = responseObject return clockDTO } return null } fun getTemporaryBasal(): TempBasalPair? { - val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal) - return if (responseObject == null) null else responseObject as TempBasalPair? + return sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal) { _, _, rawContent -> + TempBasalPair(aapsLogger, rawContent!!) } } fun getPumpSettings(): Map? { - val responseObject = sendAndGetResponseWithCheck(getSettings(medtronicUtil.medtronicPumpModel)) - return if (responseObject == null) null else responseObject as Map? + return sendAndGetResponseWithCheck(getSettings(medtronicUtil.medtronicPumpModel)) { _, _, rawContent -> + medtronicConverter.decodeSettingsLoop(rawContent) } } fun setBolus(units: Double): Boolean { @@ -600,20 +626,32 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth val gc = GregorianCalendar() gc.add(Calendar.SECOND, 5) aapsLogger.info(LTag.PUMPCOMM, "setPumpTime: " + DateTimeUtil.toString(gc)) - val i = 1 - val data = ByteArray(8) - data[0] = 7 - data[i] = gc[Calendar.HOUR_OF_DAY].toByte() - data[i + 1] = gc[Calendar.MINUTE].toByte() - data[i + 2] = gc[Calendar.SECOND].toByte() val yearByte = getByteArrayFromUnsignedShort(gc[Calendar.YEAR], true) - data[i + 3] = yearByte[0] - data[i + 4] = yearByte[1] - data[i + 5] = (gc[Calendar.MONTH] + 1).toByte() - data[i + 6] = gc[Calendar.DAY_OF_MONTH].toByte() + // val i = 1 + // val data = ByteArray(8) + // data[0] = 7 + // data[i] = gc[Calendar.HOUR_OF_DAY].toByte() + // data[i + 1] = gc[Calendar.MINUTE].toByte() + // data[i + 2] = gc[Calendar.SECOND].toByte() + // val yearByte = getByteArrayFromUnsignedShort(gc[Calendar.YEAR], true) + // data[i + 3] = yearByte[0] + // data[i + 4] = yearByte[1] + // data[i + 5] = (gc[Calendar.MONTH] + 1).toByte() + // data[i + 6] = gc[Calendar.DAY_OF_MONTH].toByte() + + val timeData = byteArrayOf( + 7, + gc[Calendar.HOUR_OF_DAY].toByte(), + gc[Calendar.MINUTE].toByte(), + gc[Calendar.SECOND].toByte(), + yearByte[0], + yearByte[1], + (gc[Calendar.MONTH] + 1).toByte(), + gc[Calendar.DAY_OF_MONTH].toByte() + ) //aapsLogger.info(LTag.PUMPCOMM,"setPumpTime: Body: " + ByteUtil.getHex(data)); - return setCommand(MedtronicCommandType.SetRealTimeClock, data) + return setCommand(MedtronicCommandType.SetRealTimeClock, timeData) } private fun setCommand(commandType: MedtronicCommandType, body: ByteArray): Boolean { @@ -642,8 +680,9 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } fun getRemainingBattery(): BatteryStatusDTO? { - val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus) - return if (responseObject == null) null else responseObject as BatteryStatusDTO? + return sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus) { _, _, rawContent -> + medtronicConverter.decodeBatteryStatus(rawContent) + } } fun setBasalProfile(basalProfile: BasalProfile): Boolean { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt index a15fb131b7..49416f66c8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt @@ -29,62 +29,62 @@ class MedtronicConverter @Inject constructor( private val medtronicUtil: MedtronicUtil ) { - fun convertResponse(pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray?): Any? { - if ((rawContent == null || rawContent.size < 1) && commandType != MedtronicCommandType.PumpModel) { - aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Content is empty or too short, no data to convert (type=%s,isNull=%b,length=%s)", - commandType.name, rawContent == null, rawContent?.size ?: "-")) - return null - } - aapsLogger.debug(LTag.PUMPCOMM, "Raw response before convert: " + ByteUtil.shortHexString(rawContent)) - return when (commandType) { - MedtronicCommandType.PumpModel -> { - decodeModel(rawContent) - } + // fun convertResponse(pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray?): Any? { + // if ((rawContent == null || rawContent.size < 1) && commandType != MedtronicCommandType.PumpModel) { + // aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Content is empty or too short, no data to convert (type=%s,isNull=%b,length=%s)", + // commandType.name, rawContent == null, rawContent?.size ?: "-")) + // return null + // } + // aapsLogger.debug(LTag.PUMPCOMM, "Raw response before convert: " + ByteUtil.shortHexString(rawContent)) + // return when (commandType) { + // MedtronicCommandType.PumpModel -> { + // decodeModel(rawContent) + // } + // + // MedtronicCommandType.GetRealTimeClock -> { + // decodeTime(rawContent) + // } + // + // MedtronicCommandType.GetRemainingInsulin -> { + // decodeRemainingInsulin(rawContent) + // } + // + // MedtronicCommandType.GetBatteryStatus -> { + // decodeBatteryStatus(rawContent) // 1 + // } + // + // MedtronicCommandType.GetBasalProfileSTD, MedtronicCommandType.GetBasalProfileA, MedtronicCommandType.GetBasalProfileB -> { + // decodeBasalProfile(pumpType, rawContent) + // } + // + // MedtronicCommandType.ReadTemporaryBasal -> { + // TempBasalPair(aapsLogger, rawContent!!) // 5 + // } + // + // MedtronicCommandType.Settings_512 -> { + // decodeSettingsLoop(rawContent) + // } + // + // MedtronicCommandType.Settings -> { + // decodeSettingsLoop(rawContent) + // } + // + // MedtronicCommandType.SetBolus -> { + // rawContent // 1 + // } + // + // else -> { + // throw RuntimeException("Unsupported command Type: $commandType") + // } + // } + // } - MedtronicCommandType.GetRealTimeClock -> { - decodeTime(rawContent) - } - - MedtronicCommandType.GetRemainingInsulin -> { - decodeRemainingInsulin(rawContent) - } - - MedtronicCommandType.GetBatteryStatus -> { - decodeBatteryStatus(rawContent) // 1 - } - - MedtronicCommandType.GetBasalProfileSTD, MedtronicCommandType.GetBasalProfileA, MedtronicCommandType.GetBasalProfileB -> { - decodeBasalProfile(pumpType, rawContent) - } - - MedtronicCommandType.ReadTemporaryBasal -> { - TempBasalPair(aapsLogger, rawContent!!) // 5 - } - - MedtronicCommandType.Settings_512 -> { - decodeSettingsLoop(rawContent) - } - - MedtronicCommandType.Settings -> { - decodeSettingsLoop(rawContent) - } - - MedtronicCommandType.SetBolus -> { - rawContent // 1 - } - - else -> { - throw RuntimeException("Unsupported command Type: $commandType") - } - } - } - - private fun decodeBasalProfile(pumpType: PumpType, rawContent: ByteArray?): BasalProfile? { + fun decodeBasalProfile(pumpType: PumpType, rawContent: ByteArray?): BasalProfile? { val basalProfile = BasalProfile(aapsLogger, rawContent!!) return if (basalProfile.verify(pumpType)) basalProfile else null } - private fun decodeModel(rawContent: ByteArray?): MedtronicDeviceType { + fun decodeModel(rawContent: ByteArray?): MedtronicDeviceType { if (rawContent == null || rawContent.size < 4) { aapsLogger.warn(LTag.PUMPCOMM, "Error reading PumpModel, returning Unknown_Device") return MedtronicDeviceType.Unknown_Device @@ -100,7 +100,7 @@ class MedtronicConverter @Inject constructor( return pumpModel } - private fun decodeBatteryStatus(rawData: ByteArray?): BatteryStatusDTO { + fun decodeBatteryStatus(rawData: ByteArray?): BatteryStatusDTO { // 00 7C 00 00 val batteryStatus = BatteryStatusDTO() val status = rawData!![0].toInt() @@ -126,7 +126,7 @@ class MedtronicConverter @Inject constructor( return batteryStatus } - private fun decodeRemainingInsulin(rawData: ByteArray?): Double { + public fun decodeRemainingInsulin(rawData: ByteArray?): Double { var startIdx = 0 val pumpModel = medtronicUtil.medtronicPumpModel val strokes = pumpModel?.bolusStrokes ?: 10 @@ -134,7 +134,7 @@ class MedtronicConverter @Inject constructor( startIdx = 2 } val reqLength = startIdx + 1 - var value = 0.0 + val value : Double value = if (reqLength >= rawData!!.size) { rawData[startIdx] / (1.0 * strokes) } else { @@ -144,7 +144,7 @@ class MedtronicConverter @Inject constructor( return value } - private fun decodeTime(rawContent: ByteArray?): LocalDateTime? { + public fun decodeTime(rawContent: ByteArray?): LocalDateTime? { val hours = ByteUtil.asUINT8(rawContent!![0]) val minutes = ByteUtil.asUINT8(rawContent[1]) val seconds = ByteUtil.asUINT8(rawContent[2]) @@ -160,7 +160,7 @@ class MedtronicConverter @Inject constructor( } } - private fun decodeSettingsLoop(rd: ByteArray?): Map { + public fun decodeSettingsLoop(rd: ByteArray?): Map { val map: MutableMap = HashMap() addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map) addSettingToMap( diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 0a4db88ede..91d64f3efc 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -35,19 +35,19 @@ abstract class MedtronicHistoryDecoder : MedtronicHi // TODO_ extend this to also use bigger pages (for now we support only 1024 pages) @Throws(RuntimeException::class) - private fun checkPage(page: RawHistoryPage, partial: Boolean): List { - val byteList: List = ArrayList() + private fun checkPage(page: RawHistoryPage, partial: Boolean): MutableList { + //val byteList: MutableList = mutableListOf() if (medtronicUtil.medtronicPumpModel == null) { aapsLogger.error(LTag.PUMPCOMM, "Device Type is not defined.") - return byteList + return mutableListOf() } return if (page.data.size != 1024) { - ByteUtil.getListFromByteArray(page.data) + page.data.toMutableList() } else if (page.isChecksumOK) { - ByteUtil.getListFromByteArray(page.onlyData) + page.onlyData.toMutableList() } else { - byteList + mutableListOf() } } @@ -117,9 +117,9 @@ abstract class MedtronicHistoryDecoder : MedtronicHi return StringUtil.getFormatedValueUS(value, decimals) } - private fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage, partial: Boolean): List { + private fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage, partial: Boolean): MutableList { val dataClear = checkPage(rawHistoryPage, partial) - val records: List = createRecords(dataClear) + val records: MutableList = createRecords(dataClear) for (record in records) { decodeRecord(record) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt index 1137371843..8b2ee5d2b0 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt @@ -6,5 +6,5 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history interface MedtronicHistoryDecoderInterface { fun decodeRecord(record: T): RecordDecodeStatus? - fun createRecords(dataClear: List): List + fun createRecords(dataClear: MutableList): MutableList } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index 83a20262cc..7ce380ca4b 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -63,11 +63,12 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() override fun postProcess() {} - override fun createRecords(dataClearInput: List): List { - val dataClear = reverseList(dataClearInput, Byte::class.java) + override fun createRecords(dataClearInput: MutableList): MutableList { + dataClearInput.reverse() + val dataClear = dataClearInput //reverseList(dataClearInput, Byte::class.java) prepareStatistics() var counter = 0 - val outList: MutableList = ArrayList() + val outList: MutableList = mutableListOf() // create CGMS entries (without dates) do { @@ -109,7 +110,8 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() outList.add(pe) } } while (counter < dataClear.size) - val reversedOutList = reverseList(outList, CGMSHistoryEntry::class.java) + outList.reverse() + val reversedOutList = outList // reverseList(outList, CGMSHistoryEntry::class.java) var timeStamp: Long? = null var dateTime: LocalDateTime? = null var getIndex = 0 @@ -119,7 +121,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() timeStamp = entry.atechDateTime dateTime = DateTimeUtil.toLocalDateTime(timeStamp!!) getIndex = 0 - } else if (entry.entryType === CGMSHistoryEntryType.GlucoseSensorData) { + } else if (entry.entryType == CGMSHistoryEntryType.GlucoseSensorData) { getIndex++ if (dateTime != null) entry.setDateTime(dateTime, getIndex) } else { @@ -130,13 +132,13 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() return reversedOutList } - private fun reverseList(dataClearInput: List, clazz: Class): List { - val outList: MutableList = ArrayList() - for (i in dataClearInput.size - 1 downTo 1) { - outList.add(dataClearInput[i]) - } - return outList - } + // private fun reverseList(dataClearInput: List, clazz: Class): List { + // val outList: MutableList = ArrayList() + // for (i in dataClearInput.size - 1 downTo 1) { + // outList.add(dataClearInput[i]) + // } + // return outList + // } private fun parseMinutes(one: Int): Int { return one and "0111111".toInt(2) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index e9131694d2..452faa705d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -37,12 +37,12 @@ class MedtronicPumpHistoryDecoder @Inject constructor( private var tbrPreviousRecord: PumpHistoryEntry? = null private var changeTimeRecord: PumpHistoryEntry? = null - override fun createRecords(dataClear: List): List { + override fun createRecords(dataClear: MutableList): MutableList { prepareStatistics() var counter = 0 var record = 0 var incompletePacket: Boolean - val outList: MutableList = ArrayList() + val outList: MutableList = mutableListOf() var skipped: String? = null if (dataClear.size == 0) { aapsLogger.error(LTag.PUMPBTCOMM, "Empty page.") diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt index 4cdb5766ec..3bff5105ee 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIComm.kt @@ -6,16 +6,17 @@ 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 +import javax.inject.Inject /** * 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 +class MedtronicUIComm @Inject constructor( + 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 { @@ -23,7 +24,7 @@ class MedtronicUIComm( } @Synchronized - fun executeCommand(commandType: MedtronicCommandType, parameters: List?): MedtronicUITask { + fun executeCommand(commandType: MedtronicCommandType, parameters: ArrayList?): MedtronicUITask { aapsLogger.info(LTag.PUMP, "Execute Command: " + commandType.name) val task = MedtronicUITask(injector, commandType, parameters) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java deleted file mode 100644 index 070bfb1a38..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.java +++ /dev/null @@ -1,1590 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.data; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.LocalDateTime; -import org.joda.time.Minutes; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.db.DbObjectBase; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TDD; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.interfaces.ActivePlugin; -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; -import info.nightscout.androidaps.interfaces.PumpSync; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; -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.MedtronicPumpHistoryDecoder; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusWizardDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.ClockDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.DailyTotalsDTO; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair; -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalProcessDTO; -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; -import info.nightscout.androidaps.plugins.treatments.TreatmentUpdateReturn; -import info.nightscout.androidaps.utils.Round; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - - -/** - * Created by andy on 10/12/18. - */ - -// TODO: After release we need to refactor how data is retrieved from pump, each entry in history needs to be marked, and sorting -// needs to happen according those markings, not on time stamp (since AAPS can change time anytime it drifts away). This -// needs to include not returning any records if TZ goes into -x area. To fully support this AAPS would need to take note of -// all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can -// handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) - -// All things marked with "TODO: Fix db code" needs to be updated in new 2.5 database code - -@Singleton -public class MedtronicHistoryData { - - private final HasAndroidInjector injector; - private final AAPSLogger aapsLogger; - private final SP sp; - private final ActivePlugin activePlugin; - private final MedtronicUtil medtronicUtil; - private final MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder; - private final MedtronicPumpStatus medtronicPumpStatus; - private final DatabaseHelperInterface databaseHelper; - private final PumpSync pumpSync; - - private final List allHistory; - private List newHistory = null; - - private boolean isInit = false; - - private Gson gson; // cannot be initialized in constructor because of injection - private Gson gsonCore; // cannot be initialized in constructor because of injection - - private ClockDTO pumpTime; - - private long lastIdUsed = 0; - - /** - * Double bolus debug. We seem to have small problem with double Boluses (or sometimes also missing boluses - * from history. This flag turns on debugging for that (default is off=false)... Debugging is pretty detailed, - * so log files will get bigger. - * Note: June 2020. Since this seems to be fixed, I am disabling this per default. I will leave code inside - * in case we need it again. Code that turns this on is commented out RileyLinkMedtronicService#verifyConfiguration() - */ - public static final boolean doubleBolusDebug = false; - - @Inject - public MedtronicHistoryData( - HasAndroidInjector injector, - AAPSLogger aapsLogger, - SP sp, - ActivePlugin activePlugin, - MedtronicUtil medtronicUtil, - MedtronicPumpHistoryDecoder medtronicPumpHistoryDecoder, - MedtronicPumpStatus medtronicPumpStatus, - DatabaseHelperInterface databaseHelperInterface, - PumpSync pumpSync - ) { - this.allHistory = new ArrayList<>(); - - this.injector = injector; - this.aapsLogger = aapsLogger; - this.sp = sp; - this.activePlugin = activePlugin; - this.medtronicUtil = medtronicUtil; - this.medtronicPumpHistoryDecoder = medtronicPumpHistoryDecoder; - this.medtronicPumpStatus = medtronicPumpStatus; - this.databaseHelper = databaseHelperInterface; - this.pumpSync = pumpSync; - } - - private Gson gson() { - if (gson == null) gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); - return gson; - } - - private Gson gsonCore() { - if (gsonCore == null) gsonCore = new GsonBuilder().create(); - return gsonCore; - } - - /** - * Add New History entries - * - * @param result PumpHistoryResult instance - */ - public void addNewHistory(PumpHistoryResult result) { - - List validEntries = result.getValidEntries(); - - List newEntries = new ArrayList<>(); - - for (PumpHistoryEntry validEntry : validEntries) { - - if (!this.allHistory.contains(validEntry)) { - newEntries.add(validEntry); - } - } - - this.newHistory = newEntries; - - showLogs("List of history (before filtering): [" + this.newHistory.size() + "]", gson().toJson(this.newHistory)); - } - - - private void showLogs(String header, String data) { - if (header != null) { - aapsLogger.debug(LTag.PUMP, header); - } - - if (StringUtils.isNotBlank(data)) { - for (final String token : StringUtil.splitString(data, 3500)) { - aapsLogger.debug(LTag.PUMP, token); - } - } else { - aapsLogger.debug(LTag.PUMP, "No data."); - } - } - - - public List getAllHistory() { - return this.allHistory; - } - - - public void filterNewEntries() { - - List newHistory2 = new ArrayList<>(); - List TBRs = new ArrayList<>(); - List bolusEstimates = new ArrayList<>(); - long atechDate = DateTimeUtil.toATechDate(new GregorianCalendar()); - - //aapsLogger.debug(LTag.PUMP, "Filter new entries: Before {}", newHistory); - - if (!isCollectionEmpty(newHistory)) { - - for (PumpHistoryEntry pumpHistoryEntry : newHistory) { - - if (!this.allHistory.contains(pumpHistoryEntry)) { - - PumpHistoryEntryType type = pumpHistoryEntry.getEntryType(); - - if (type == PumpHistoryEntryType.TempBasalRate || type == PumpHistoryEntryType.TempBasalDuration) { - TBRs.add(pumpHistoryEntry); - } else if (type == PumpHistoryEntryType.BolusWizard || type == PumpHistoryEntryType.BolusWizard512) { - bolusEstimates.add(pumpHistoryEntry); - newHistory2.add(pumpHistoryEntry); - } else { - - if (type == PumpHistoryEntryType.EndResultTotals) { - if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.getAtechDateTime())) { - newHistory2.add(pumpHistoryEntry); - } - } else { - newHistory2.add(pumpHistoryEntry); - } - } - } - } - - TBRs = preProcessTBRs(TBRs); - - if (bolusEstimates.size() > 0) { - extendBolusRecords(bolusEstimates, newHistory2); - } - - newHistory2.addAll(TBRs); - - this.newHistory = newHistory2; - - sort(this.newHistory); - } - - aapsLogger.debug(LTag.PUMP, "New History entries found: " + this.newHistory.size()); - - showLogs("List of history (after filtering): [" + this.newHistory.size() + "]", gson().toJson(this.newHistory)); - - } - - private void extendBolusRecords(List bolusEstimates, List newHistory2) { - - List boluses = getFilteredItems(newHistory2, PumpHistoryEntryType.Bolus); - - for (PumpHistoryEntry bolusEstimate : bolusEstimates) { - for (PumpHistoryEntry bolus : boluses) { - if (bolusEstimate.getAtechDateTime().equals(bolus.getAtechDateTime())) { - bolus.addDecodedData("Estimate", bolusEstimate.getDecodedData().get("Object")); - } - } - } - } - - - public void finalizeNewHistoryRecords() { - - if ((newHistory == null) || (newHistory.size() == 0)) - return; - - PumpHistoryEntry pheLast = newHistory.get(0); - - // find last entry - for (PumpHistoryEntry pumpHistoryEntry : newHistory) { - if (pumpHistoryEntry.getAtechDateTime() != null && pumpHistoryEntry.isAfter(pheLast.getAtechDateTime())) { - pheLast = pumpHistoryEntry; - } - } - - // add new entries - Collections.reverse(newHistory); - - for (PumpHistoryEntry pumpHistoryEntry : newHistory) { - - if (!this.allHistory.contains(pumpHistoryEntry)) { - lastIdUsed++; - pumpHistoryEntry.setId(lastIdUsed); - this.allHistory.add(pumpHistoryEntry); - } - - } - - - if (pheLast == null) // if we don't have any valid record we don't do the filtering and setting - return; - - this.setLastHistoryRecordTime(pheLast.getAtechDateTime()); - sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.getAtechDateTime()); - - LocalDateTime dt = null; - - try { - dt = DateTimeUtil.toLocalDateTime(pheLast.getAtechDateTime()); - } catch (Exception ex) { - aapsLogger.error("Problem decoding date from last record: " + pheLast); - } - - if (dt != null) { - - dt = dt.minusDays(1); // we keep 24 hours - - long dtRemove = DateTimeUtil.toATechDate(dt); - - List removeList = new ArrayList<>(); - - for (PumpHistoryEntry pumpHistoryEntry : allHistory) { - - if (!pumpHistoryEntry.isAfter(dtRemove)) { - removeList.add(pumpHistoryEntry); - } - } - - this.allHistory.removeAll(removeList); - - this.sort(this.allHistory); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "All History records [afterFilterCount=%d, removedItemsCount=%d, newItemsCount=%d]", - allHistory.size(), removeList.size(), newHistory.size())); - } else { - aapsLogger.error("Since we couldn't determine date, we don't clean full history. This is just workaround."); - } - - this.newHistory.clear(); - } - - - public boolean hasRelevantConfigurationChanged() { - return getStateFromFilteredList( // - PumpHistoryEntryType.ChangeBasalPattern, // - PumpHistoryEntryType.ClearSettings, // - PumpHistoryEntryType.SaveSettings, // - PumpHistoryEntryType.ChangeMaxBolus, // - PumpHistoryEntryType.ChangeMaxBasal, // - PumpHistoryEntryType.ChangeTempBasalType); - } - - - private boolean isCollectionEmpty(List col) { - return (col == null || col.isEmpty()); - } - - private boolean isCollectionNotEmpty(List col) { - return (col != null && !col.isEmpty()); - } - - - public boolean isPumpSuspended() { - - List items = getDataForPumpSuspends(); - - showLogs("isPumpSuspended: ", gson().toJson(items)); - - if (isCollectionNotEmpty(items)) { - - PumpHistoryEntryType pumpHistoryEntryType = items.get(0).getEntryType(); - - boolean isSuspended = !(pumpHistoryEntryType == PumpHistoryEntryType.TempBasalCombined || // - pumpHistoryEntryType == PumpHistoryEntryType.BasalProfileStart || // - pumpHistoryEntryType == PumpHistoryEntryType.Bolus || // - pumpHistoryEntryType == PumpHistoryEntryType.ResumePump || // - pumpHistoryEntryType == PumpHistoryEntryType.BatteryChange || // - pumpHistoryEntryType == PumpHistoryEntryType.Prime); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "isPumpSuspended. Last entry type=%s, isSuspended=%b", pumpHistoryEntryType, isSuspended)); - - return isSuspended; - } else - return false; - - } - - - private List getDataForPumpSuspends() { - - List newAndAll = new ArrayList<>(); - - if (isCollectionNotEmpty(this.allHistory)) { - newAndAll.addAll(this.allHistory); - } - - if (isCollectionNotEmpty(this.newHistory)) { - - for (PumpHistoryEntry pumpHistoryEntry : newHistory) { - if (!newAndAll.contains(pumpHistoryEntry)) { - newAndAll.add(pumpHistoryEntry); - } - } - } - - if (newAndAll.isEmpty()) - return newAndAll; - - this.sort(newAndAll); - - List newAndAll2 = getFilteredItems(newAndAll, // - PumpHistoryEntryType.Bolus, // - PumpHistoryEntryType.TempBasalCombined, // - PumpHistoryEntryType.Prime, // - PumpHistoryEntryType.SuspendPump, // - PumpHistoryEntryType.ResumePump, // - PumpHistoryEntryType.Rewind, // - PumpHistoryEntryType.NoDeliveryAlarm, // - PumpHistoryEntryType.BatteryChange, // - PumpHistoryEntryType.BasalProfileStart); - - newAndAll2 = filterPumpSuspend(newAndAll2, 10); - - return newAndAll2; - } - - - private List filterPumpSuspend(List newAndAll, int filterCount) { - - if (newAndAll.size() <= filterCount) { - return newAndAll; - } - - List newAndAllOut = new ArrayList<>(); - - for (int i = 0; i < filterCount; i++) { - newAndAllOut.add(newAndAll.get(i)); - } - - return newAndAllOut; - } - - - /** - * Process History Data: Boluses(Treatments), TDD, TBRs, Suspend-Resume (or other pump stops: battery, prime) - */ - public void processNewHistoryData() { - - // TODO: Fix db code - // Prime (for reseting autosense) - List primeRecords = getFilteredItems(PumpHistoryEntryType.Prime); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Prime [count=%d, items=%s]", primeRecords.size(), gson().toJson(primeRecords))); - - if (isCollectionNotEmpty(primeRecords)) { - try { - processPrime(primeRecords); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Prime entries: " + ex.getMessage(), ex); - throw ex; - } - } - - // Rewind (for marking insulin change) - List rewindRecords = getFilteredItems(PumpHistoryEntryType.Rewind); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Rewind [count=%d, items=%s]", rewindRecords.size(), gson().toJson(rewindRecords))); - - if (isCollectionNotEmpty(rewindRecords)) { - try { - processRewind(rewindRecords); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Rewind entries: " + ex.getMessage(), ex); - throw ex; - } - } - - // TDD - List tdds = getFilteredItems(PumpHistoryEntryType.EndResultTotals, getTDDType()); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TDD [count=%d, items=%s]", tdds.size(), gson().toJson(tdds))); - - if (isCollectionNotEmpty(tdds)) { - try { - processTDDs(tdds); - } catch (Exception ex) { - aapsLogger.error("ProcessHistoryData: Error processing TDD entries: " + ex.getMessage(), ex); - throw ex; - } - } - - pumpTime = medtronicUtil.getPumpTime(); - - // Bolus - List treatments = getFilteredItems(PumpHistoryEntryType.Bolus); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Bolus [count=%d, items=%s]", treatments.size(), gson().toJson(treatments))); - - if (treatments.size() > 0) { - try { - processBolusEntries(treatments); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Bolus entries: " + ex.getMessage(), ex); - throw ex; - } - } - - // TBR - List tbrs = getFilteredItems(PumpHistoryEntryType.TempBasalCombined); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TBRs Processed [count=%d, items=%s]", tbrs.size(), gson().toJson(tbrs))); - - if (tbrs.size() > 0) { - try { - processTBREntries(tbrs); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing TBR entries: " + ex.getMessage(), ex); - throw ex; - } - } - - // 'Delivery Suspend' - List suspends; - - try { - suspends = getSuspends(); - } catch (Exception ex) { - aapsLogger.error("ProcessHistoryData: Error getting Suspend entries: " + ex.getMessage(), ex); - throw ex; - } - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: 'Delivery Suspend' Processed [count=%d, items=%s]", suspends.size(), - gson().toJson(suspends))); - - if (isCollectionNotEmpty(suspends)) { - try { - processSuspends(suspends); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Suspends entries: " + ex.getMessage(), ex); - throw ex; - } - } - } - - - private void processPrime(List primeRecords) { - - long maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(new GregorianCalendar(), -30); - - long lastPrimeRecord = 0L; - - for (PumpHistoryEntry primeRecord : primeRecords) { - Object fixedAmount = primeRecord.getDecodedDataEntry("FixedAmount"); - - if (fixedAmount != null && ((float) fixedAmount) == 0.0f) { - // non-fixed primes are used to prime the tubing - // fixed primes are used to prime the cannula - // so skip the prime entry if it was not a fixed prime - continue; - } - - if (primeRecord.getAtechDateTime() > maxAllowedTimeInPast) { - if (lastPrimeRecord < primeRecord.getAtechDateTime()) { - lastPrimeRecord = primeRecord.getAtechDateTime(); - } - } - } - - if (lastPrimeRecord != 0L) { - long lastPrimeFromAAPS = sp.getLong(MedtronicConst.Statistics.LastPrime, 0L); - - if (lastPrimeRecord != lastPrimeFromAAPS) { - uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastPrimeRecord), DetailedBolusInfo.EventType.CANNULA_CHANGE); - - sp.putLong(MedtronicConst.Statistics.LastPrime, lastPrimeRecord); - } - } - } - - private void processRewind(List rewindRecords) { - long maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(new GregorianCalendar(), -30); - long lastRewindRecord = 0L; - - for (PumpHistoryEntry rewindRecord : rewindRecords) { - if (rewindRecord.getAtechDateTime() > maxAllowedTimeInPast) { - if (lastRewindRecord < rewindRecord.getAtechDateTime()) { - lastRewindRecord = rewindRecord.getAtechDateTime(); - } - } - } - - if (lastRewindRecord != 0L) { - long lastRewindFromAAPS = sp.getLong(MedtronicConst.Statistics.LastRewind, 0L); - - if (lastRewindRecord != lastRewindFromAAPS) { - uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastRewindRecord), DetailedBolusInfo.EventType.INSULIN_CHANGE); - - sp.putLong(MedtronicConst.Statistics.LastRewind, lastRewindRecord); - } - } - } - - - private void uploadCareportalEvent(long date, DetailedBolusInfo.EventType event) { - pumpSync.insertTherapyEventIfNewWithTimestamp(date, event, null, null, - medtronicPumpStatus.getPumpType(), medtronicPumpStatus.getSerialNumber()); - } - - private void processTDDs(List tddsIn) { - - List tdds = filterTDDs(tddsIn); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, getLogPrefix() + "TDDs found: %d.\n%s", tdds.size(), gson().toJson(tdds))); - - List tddsDb = databaseHelper.getTDDsForLastXDays(3); - - for (PumpHistoryEntry tdd : tdds) { - - TDD tddDbEntry = findTDD(tdd.getAtechDateTime(), tddsDb); - - DailyTotalsDTO totalsDTO = (DailyTotalsDTO) tdd.getDecodedData().get("Object"); - - //aapsLogger.debug(LTag.PUMP, "DailyTotals: {}", totalsDTO); - - if (tddDbEntry == null) { - TDD tddNew = new TDD(); - totalsDTO.setTDD(tddNew); - - aapsLogger.debug(LTag.PUMP, "TDD Add: " + tddNew); - - databaseHelper.createOrUpdateTDD(tddNew); - - } else { - - if (!totalsDTO.doesEqual(tddDbEntry)) { - totalsDTO.setTDD(tddDbEntry); - - aapsLogger.debug(LTag.PUMP, "TDD Edit: " + tddDbEntry); - - databaseHelper.createOrUpdateTDD(tddDbEntry); - } - } - } - } - - - private enum ProcessHistoryRecord { - Bolus("Bolus"), - TBR("TBR"), - Suspend("Suspend"); - - private final String description; - - ProcessHistoryRecord(String desc) { - this.description = desc; - } - - public String getDescription() { - return this.description; - } - - } - - - private void processBolusEntries(List entryList) { - - long oldestTimestamp = getOldestTimestamp(entryList); - - List entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.Bolus); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (before filter): %s, FromDb=%s", gson().toJson(entryList), - gsonCore().toJson(entriesFromHistory))); - - filterOutAlreadyAddedEntries(entryList, entriesFromHistory); - - if (entryList.isEmpty()) { - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: EntryList was filtered out."); - return; - } - - filterOutNonInsulinEntries(entriesFromHistory); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (after filter): %s, FromDb=%s", gson().toJson(entryList), - gsonCore().toJson(entriesFromHistory))); - - if (isCollectionEmpty(entriesFromHistory)) { - for (PumpHistoryEntry treatment : entryList) { - aapsLogger.debug(LTag.PUMP, "Add Bolus (no db entry): " + treatment); - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: Add Bolus: FromDb=null, Treatment=" + treatment); - - addBolus(treatment, null); - } - } else { - for (PumpHistoryEntry treatment : entryList) { - DbObjectBase treatmentDb = findDbEntry(treatment, entriesFromHistory); - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add Bolus %s - (entryFromDb=%s) ", treatment, treatmentDb)); - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: Add Bolus: FromDb=%s, Treatment=%s", treatmentDb, treatment)); - - addBolus(treatment, (Treatment) treatmentDb); - } - } - } - - - private void filterOutNonInsulinEntries(List entriesFromHistory) { - // when we try to pair PumpHistory with AAPS treatments, we need to ignore all non-insulin entries - List removeList = new ArrayList<>(); - - for (DbObjectBase dbObjectBase : entriesFromHistory) { - - Treatment treatment = (Treatment) dbObjectBase; - - if (Round.isSame(treatment.insulin, 0d)) { - removeList.add(dbObjectBase); - } - } - - entriesFromHistory.removeAll(removeList); - } - - - private void processTBREntries(List entryList) { - - Collections.reverse(entryList); - - TempBasalPair tbr = (TempBasalPair) entryList.get(0).getDecodedDataEntry("Object"); - - boolean readOldItem = false; - - if (tbr.isCancelTBR()) { - PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined); - - if (oneMoreEntryFromHistory != null) { - entryList.add(0, oneMoreEntryFromHistory); - readOldItem = true; - } else { - entryList.remove(0); - } - } - - long oldestTimestamp = getOldestTimestamp(entryList); - - List entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.TBR); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.getDescription() + " List (before filter): %s, FromDb=%s", gson().toJson(entryList), - gson().toJson(entriesFromHistory))); - - - TempBasalProcessDTO processDTO = null; - List processList = new ArrayList<>(); - - for (PumpHistoryEntry treatment : entryList) { - - TempBasalPair tbr2 = (TempBasalPair) treatment.getDecodedDataEntry("Object"); - - if (tbr2.isCancelTBR()) { - - if (processDTO != null) { - processDTO.itemTwo = treatment; - - if (readOldItem) { - processDTO.processOperation = TempBasalProcessDTO.Operation.Edit; - readOldItem = false; - } - } else { - aapsLogger.error("processDTO was null - shouldn't happen. ItemTwo=" + treatment); - } - } else { - if (processDTO != null) { - processList.add(processDTO); - } - - processDTO = new TempBasalProcessDTO(); - processDTO.itemOne = treatment; - processDTO.processOperation = TempBasalProcessDTO.Operation.Add; - } - } - - if (processDTO != null) { - processList.add(processDTO); - } - - - if (isCollectionNotEmpty(processList)) { - - for (TempBasalProcessDTO tempBasalProcessDTO : processList) { - - if (tempBasalProcessDTO.processOperation == TempBasalProcessDTO.Operation.Edit) { - // edit - TemporaryBasal tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne.getPumpId(), entriesFromHistory); - - if (tempBasal != null) { - - tempBasal.durationInMinutes = tempBasalProcessDTO.getDuration(); - - databaseHelper.createOrUpdate(tempBasal); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Edit " + ProcessHistoryRecord.TBR.getDescription() + " - (entryFromDb=%s) ", tempBasal)); - } else { - aapsLogger.error(LTag.PUMP, "TempBasal not found. Item: " + tempBasalProcessDTO.itemOne); - } - - } else { - // add - - PumpHistoryEntry treatment = tempBasalProcessDTO.itemOne; - - TempBasalPair tbr2 = (TempBasalPair) treatment.getDecodedData().get("Object"); - tbr2.setDurationMinutes(tempBasalProcessDTO.getDuration()); - - TemporaryBasal tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne.getPumpId(), entriesFromHistory); - - if (tempBasal == null) { - DbObjectBase treatmentDb = findDbEntry(treatment, entriesFromHistory); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add " + ProcessHistoryRecord.TBR.getDescription() + " %s - (entryFromDb=%s) ", treatment, treatmentDb)); - - addTBR(treatment, (TemporaryBasal) treatmentDb); - } else { - // this shouldn't happen - if (tempBasal.durationInMinutes != tempBasalProcessDTO.getDuration()) { - aapsLogger.debug(LTag.PUMP, "Found entry with wrong duration (shouldn't happen)... updating"); - tempBasal.durationInMinutes = tempBasalProcessDTO.getDuration(); - } - - } - } // if - } // for - - } // collection - } - - - private TemporaryBasal findTempBasalWithPumpId(long pumpId, List entriesFromHistory) { - - for (DbObjectBase dbObjectBase : entriesFromHistory) { - TemporaryBasal tbr = (TemporaryBasal) dbObjectBase; - - if (tbr.pumpId == pumpId) { - return tbr; - } - } - - TemporaryBasal tempBasal = databaseHelper.findTempBasalByPumpId(pumpId); - return tempBasal; - } - - - /** - * findDbEntry - finds Db entries in database, while theoretically this should have same dateTime they - * don't. Entry on pump is few seconds before treatment in AAPS, and on manual boluses on pump there - * is no treatment at all. For now we look fro tratment that was from 0s - 1m59s within pump entry. - * - * @param treatment Pump Entry - * @param entriesFromHistory entries from history - * @return DbObject from AAPS (if found) - */ - private DbObjectBase findDbEntry(PumpHistoryEntry treatment, List entriesFromHistory) { - - long proposedTime = DateTimeUtil.toMillisFromATD(treatment.getAtechDateTime()); - - //proposedTime += (this.pumpTime.timeDifference * 1000); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s", treatment, gson().toJson(entriesFromHistory))); - - if (entriesFromHistory.size() == 0) { - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=null", treatment)); - return null; - } else if (entriesFromHistory.size() == 1) { - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s. Type=SingleEntry", treatment, entriesFromHistory.get(0))); - - // TODO: Fix db code - // if difference is bigger than 2 minutes we discard entry - long maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.getAtechDateTime(), 2); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry maxMillisAllowed=%d, AtechDateTime=%d (add 2 minutes). ", maxMillisAllowed, treatment.getAtechDateTime())); - - if (entriesFromHistory.get(0).getDate() > maxMillisAllowed) { - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: findDbEntry entry filtered out, returning null. "); - return null; - } - - return entriesFromHistory.get(0); - } - - for (int min = 0; min < 2; min += 1) { - - for (int sec = 0; sec <= 50; sec += 10) { - - if (min == 1 && sec == 50) { - sec = 59; - } - - int diff = (sec * 1000); - - List outList = new ArrayList<>(); - - for (DbObjectBase treatment1 : entriesFromHistory) { - - if ((treatment1.getDate() > proposedTime - diff) && (treatment1.getDate() < proposedTime + diff)) { - outList.add(treatment1); - } - } - - if (outList.size() == 1) { - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}. Type=EntrySelected, AtTimeMin={}, AtTimeSec={}", treatment, entriesFromHistory.get(0), min, sec)); - - return outList.get(0); - } - - if (min == 0 && sec == 10 && outList.size() > 1) { - aapsLogger.error(String.format(Locale.ENGLISH, "Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", - min, sec, outList.size(), gson().toJson(outList))); - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Error - Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", - min, sec, outList.size(), gson().toJson(outList))); - } - } - } - - return null; - } - - - private List getDatabaseEntriesByLastTimestamp(long startTimestamp, ProcessHistoryRecord processHistoryRecord) { - if (processHistoryRecord == ProcessHistoryRecord.Bolus) { - return activePlugin.getActiveTreatments().getTreatmentsFromHistoryAfterTimestamp(startTimestamp); - } else { - return databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true); - } - } - - - private void filterOutAlreadyAddedEntries(List entryList, List treatmentsFromHistory) { - - if (isCollectionEmpty(treatmentsFromHistory)) - return; - - List removeTreatmentsFromHistory = new ArrayList<>(); - List removeTreatmentsFromPH = new ArrayList<>(); - - for (DbObjectBase treatment : treatmentsFromHistory) { - - if (treatment.getPumpId() != 0) { - - PumpHistoryEntry selectedBolus = null; - - for (PumpHistoryEntry bolus : entryList) { - if (bolus.getPumpId() == treatment.getPumpId()) { - selectedBolus = bolus; - break; - } - } - - if (selectedBolus != null) { - entryList.remove(selectedBolus); - - removeTreatmentsFromPH.add(selectedBolus); - removeTreatmentsFromHistory.add(treatment); - } - } - } - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: filterOutAlreadyAddedEntries: PumpHistory=%s, Treatments=%s", - gson().toJson(removeTreatmentsFromPH), - gsonCore().toJson(removeTreatmentsFromHistory))); - - treatmentsFromHistory.removeAll(removeTreatmentsFromHistory); - } - - - private void addBolus(PumpHistoryEntry bolus, Treatment treatment) { - - BolusDTO bolusDTO = (BolusDTO) bolus.getDecodedData().get("Object"); - - if (treatment == null) { - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): Bolus=" + bolusDTO); - - switch (bolusDTO.getBolusType()) { - case Normal: { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - - detailedBolusInfo.setBolusTimestamp(tryToGetByLocalTime(bolus.getAtechDateTime())); - detailedBolusInfo.setPumpType(PumpType.MEDTRONIC_512_712); // TODO grab real model - detailedBolusInfo.setPumpSerial(medtronicPumpStatus.getSerialNumber()); - detailedBolusInfo.setBolusPumpId(bolus.getPumpId()); - detailedBolusInfo.insulin = bolusDTO.getDeliveredAmount(); - - addCarbsFromEstimate(detailedBolusInfo, bolus); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): DetailedBolusInfo=" + detailedBolusInfo); - - boolean newRecord = activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, false); - - bolus.setLinkedObject(detailedBolusInfo); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.timestamp, - detailedBolusInfo.getBolusPumpId(), detailedBolusInfo.insulin, newRecord)); - } - break; - - case Audio: - case Extended: { - ExtendedBolus extendedBolus = new ExtendedBolus(injector); - extendedBolus.date = tryToGetByLocalTime(bolus.getAtechDateTime()); - extendedBolus.source = Source.PUMP; - extendedBolus.insulin = bolusDTO.getDeliveredAmount(); - extendedBolus.pumpId = bolus.getPumpId(); - extendedBolus.isValid = true; - extendedBolus.durationInMinutes = bolusDTO.getDuration(); - - bolus.setLinkedObject(extendedBolus); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): ExtendedBolus=" + extendedBolus); - - activePlugin.getActiveTreatments().addToHistoryExtendedBolus(extendedBolus); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - Extended [date=%d,pumpId=%d, insulin=%.3f, duration=%d]", extendedBolus.date, - extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes)); - - } - break; - } - - } else { - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(OldTreatment=%s): Bolus=%s", treatment, bolusDTO)); - - treatment.source = Source.PUMP; - treatment.pumpId = bolus.getPumpId(); - treatment.insulin = bolusDTO.getDeliveredAmount(); - - TreatmentUpdateReturn updateReturn = activePlugin.getActiveTreatments().createOrUpdateMedtronic(treatment, false); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(tretament!=null): NewTreatment=%s, UpdateReturn=%s", treatment, updateReturn)); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "editBolus - [date=%d,pumpId=%d, insulin=%.3f, newRecord=%s]", treatment.date, - treatment.pumpId, treatment.insulin, updateReturn.toString())); - - bolus.setLinkedObject(treatment); - - } - } - - - private void addCarbsFromEstimate(DetailedBolusInfo detailedBolusInfo, PumpHistoryEntry bolus) { - - if (bolus.containsDecodedData("Estimate")) { - - BolusWizardDTO bolusWizard = (BolusWizardDTO) bolus.getDecodedData().get("Estimate"); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard)); - - detailedBolusInfo.carbs = bolusWizard.getCarbs(); - } - } - - - private void addTBR(PumpHistoryEntry treatment, TemporaryBasal temporaryBasalDbInput) { - - TempBasalPair tbr = (TempBasalPair) treatment.getDecodedData().get("Object"); - - TemporaryBasal temporaryBasalDb = temporaryBasalDbInput; - String operation = "editTBR"; - - if (temporaryBasalDb == null) { - temporaryBasalDb = new TemporaryBasal(injector); - temporaryBasalDb.date = tryToGetByLocalTime(treatment.getAtechDateTime()); - - operation = "addTBR"; - } - - temporaryBasalDb.source = Source.PUMP; - temporaryBasalDb.pumpId = treatment.getPumpId(); - temporaryBasalDb.durationInMinutes = tbr.getDurationMinutes(); - temporaryBasalDb.absoluteRate = tbr.getInsulinRate(); - temporaryBasalDb.isAbsolute = !tbr.isPercent(); - - treatment.setLinkedObject(temporaryBasalDb); - - databaseHelper.createOrUpdate(temporaryBasalDb); - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, operation + " - [date=%d,pumpId=%d, rate=%s %s, duration=%d]", // - temporaryBasalDb.date, // - temporaryBasalDb.pumpId, // - temporaryBasalDb.isAbsolute ? String.format(Locale.ENGLISH, "%.2f", temporaryBasalDb.absoluteRate) : - String.format(Locale.ENGLISH, "%d", temporaryBasalDb.percentRate), // - temporaryBasalDb.isAbsolute ? "U/h" : "%", // - temporaryBasalDb.durationInMinutes)); - } - - - private void processSuspends(List tempBasalProcessList) { - - for (TempBasalProcessDTO tempBasalProcess : tempBasalProcessList) { - - TemporaryBasal tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne.getPumpId()); - - if (tempBasal == null) { - // add - tempBasal = new TemporaryBasal(injector); - tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne.getAtechDateTime()); - - tempBasal.source = Source.PUMP; - tempBasal.pumpId = tempBasalProcess.itemOne.getPumpId(); - tempBasal.durationInMinutes = tempBasalProcess.getDuration(); - tempBasal.absoluteRate = 0.0d; - tempBasal.isAbsolute = true; - - tempBasalProcess.itemOne.setLinkedObject(tempBasal); - tempBasalProcess.itemTwo.setLinkedObject(tempBasal); - - databaseHelper.createOrUpdate(tempBasal); - - } - } - - } - - - private List getSuspends() { - - List outList = new ArrayList<>(); - - // suspend/resume - outList.addAll(getSuspendResumeRecords()); - // no_delivery/prime & rewind/prime - outList.addAll(getNoDeliveryRewindPrimeRecords()); - - return outList; - } - - private List getSuspendResumeRecords() { - List filteredItems = getFilteredItems(this.newHistory, // - PumpHistoryEntryType.SuspendPump, // - PumpHistoryEntryType.ResumePump); - - List outList = new ArrayList<>(); - - if (filteredItems.size() > 0) { - - List filtered2Items = new ArrayList<>(); - - if ((filteredItems.size() % 2 == 0) && (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.ResumePump)) { - // full resume suspends (S R S R) - filtered2Items.addAll(filteredItems); - } else if ((filteredItems.size() % 2 == 0) && (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.SuspendPump)) { - // not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS]) - filteredItems.remove(0); - - PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump); - if (oneMoreEntryFromHistory != null) { - filteredItems.add(oneMoreEntryFromHistory); - } else { - filteredItems.remove(filteredItems.size() - 1); // remove last (unpaired R) - } - - filtered2Items.addAll(filteredItems); - } else { - if (filteredItems.get(0).getEntryType() == PumpHistoryEntryType.ResumePump) { - // get one more from history (R S R) -> ([S] R S R) - - PumpHistoryEntry oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump); - if (oneMoreEntryFromHistory != null) { - filteredItems.add(oneMoreEntryFromHistory); - } else { - filteredItems.remove(filteredItems.size() - 1); // remove last (unpaired R) - } - - filtered2Items.addAll(filteredItems); - } else { - // remove last and have paired items - filteredItems.remove(0); - filtered2Items.addAll(filteredItems); - } - } - - if (filtered2Items.size() > 0) { - sort(filtered2Items); - Collections.reverse(filtered2Items); - - for (int i = 0; i < filtered2Items.size(); i += 2) { - TempBasalProcessDTO dto = new TempBasalProcessDTO(); - - dto.itemOne = filtered2Items.get(i); - dto.itemTwo = filtered2Items.get(i + 1); - - dto.processOperation = TempBasalProcessDTO.Operation.Add; - - outList.add(dto); - } - } - } - - return outList; - } - - - private List getNoDeliveryRewindPrimeRecords() { - List primeItems = getFilteredItems(this.newHistory, // - PumpHistoryEntryType.Prime); - - List outList = new ArrayList<>(); - - if (primeItems.size() == 0) - return outList; - - List filteredItems = getFilteredItems(this.newHistory, // - PumpHistoryEntryType.Prime, - PumpHistoryEntryType.Rewind, - PumpHistoryEntryType.NoDeliveryAlarm, - PumpHistoryEntryType.Bolus, - PumpHistoryEntryType.TempBasalCombined - ); - - List tempData = new ArrayList<>(); - boolean startedItems = false; - boolean finishedItems = false; - - for (PumpHistoryEntry filteredItem : filteredItems) { - if (filteredItem.getEntryType() == PumpHistoryEntryType.Prime) { - startedItems = true; - } - - if (startedItems) { - if (filteredItem.getEntryType() == PumpHistoryEntryType.Bolus || - filteredItem.getEntryType() == PumpHistoryEntryType.TempBasalCombined) { - finishedItems = true; - break; - } - - tempData.add(filteredItem); - } - } - - - if (!finishedItems) { - - List filteredItemsOld = getFilteredItems(this.allHistory, // - PumpHistoryEntryType.Rewind, - PumpHistoryEntryType.NoDeliveryAlarm, - PumpHistoryEntryType.Bolus, - PumpHistoryEntryType.TempBasalCombined - ); - - for (PumpHistoryEntry filteredItem : filteredItemsOld) { - - if (filteredItem.getEntryType() == PumpHistoryEntryType.Bolus || - filteredItem.getEntryType() == PumpHistoryEntryType.TempBasalCombined) { - finishedItems = true; - break; - } - - tempData.add(filteredItem); - } - } - - - if (!finishedItems) { - showLogs("NoDeliveryRewindPrimeRecords: Not finished Items: ", gson().toJson(tempData)); - return outList; - } - - showLogs("NoDeliveryRewindPrimeRecords: Records to evaluate: ", gson().toJson(tempData)); - - List items = getFilteredItems(tempData, // - PumpHistoryEntryType.Prime - ); - - - TempBasalProcessDTO processDTO = new TempBasalProcessDTO(); - - processDTO.itemTwo = items.get(0); - - items = getFilteredItems(tempData, // - PumpHistoryEntryType.NoDeliveryAlarm - ); - - if (items.size() > 0) { - - processDTO.itemOne = items.get(items.size() - 1); - processDTO.processOperation = TempBasalProcessDTO.Operation.Add; - - outList.add(processDTO); - return outList; - } - - - items = getFilteredItems(tempData, // - PumpHistoryEntryType.Rewind - ); - - if (items.size() > 0) { - - processDTO.itemOne = items.get(0); - processDTO.processOperation = TempBasalProcessDTO.Operation.Add; - - outList.add(processDTO); - return outList; - } - - return outList; - } - - - private PumpHistoryEntry getOneMoreEntryFromHistory(PumpHistoryEntryType entryType) { - List filteredItems = getFilteredItems(this.allHistory, entryType); - - return filteredItems.size() == 0 ? null : filteredItems.get(0); - } - - - private List filterTDDs(List tdds) { - List tddsOut = new ArrayList<>(); - - for (PumpHistoryEntry tdd : tdds) { - if (tdd.getEntryType() != PumpHistoryEntryType.EndResultTotals) { - tddsOut.add(tdd); - } - } - - return tddsOut.size() == 0 ? tdds : tddsOut; - } - - - private TDD findTDD(long atechDateTime, List tddsDb) { - - for (TDD tdd : tddsDb) { - - if (DateTimeUtil.isSameDayATDAndMillis(atechDateTime, tdd.date)) { - return tdd; - } - } - - return null; - } - - private long tryToGetByLocalTime(long atechDateTime) { - return DateTimeUtil.toMillisFromATD(atechDateTime); - } - - - private int getOldestDateDifference(List treatments) { - - long dt = Long.MAX_VALUE; - PumpHistoryEntry currentTreatment = null; - - if (isCollectionEmpty(treatments)) { - return 8; // default return of 6 (5 for diif on history reading + 2 for max allowed difference) minutes - } - - for (PumpHistoryEntry treatment : treatments) { - - if (treatment.getAtechDateTime() < dt) { - dt = treatment.getAtechDateTime(); - currentTreatment = treatment; - } - } - - LocalDateTime oldestEntryTime; - - try { - - oldestEntryTime = DateTimeUtil.toLocalDateTime(dt); - oldestEntryTime = oldestEntryTime.minusMinutes(3); - -// if (this.pumpTime.timeDifference < 0) { -// oldestEntryTime = oldestEntryTime.plusSeconds(this.pumpTime.timeDifference); -// } - } catch (Exception ex) { - aapsLogger.error("Problem decoding date from last record: " + currentTreatment); - return 8; // default return of 6 minutes - } - - LocalDateTime now = new LocalDateTime(); - - Minutes minutes = Minutes.minutesBetween(oldestEntryTime, now); - - // 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, - this.pumpTime.getTimeDifference(), oldestEntryTime, now, minutes.getMinutes())); - - return minutes.getMinutes(); - } - - - private long getOldestTimestamp(List treatments) { - - long dt = Long.MAX_VALUE; - PumpHistoryEntry currentTreatment = null; - - for (PumpHistoryEntry treatment : treatments) { - - if (treatment.getAtechDateTime() < dt) { - dt = treatment.getAtechDateTime(); - currentTreatment = treatment; - } - } - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. Oldest entry found: time=%d, object=%s", dt, currentTreatment)); - - try { - - GregorianCalendar oldestEntryTime = DateTimeUtil.toGregorianCalendar(dt); - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. oldestEntryTime: %s", DateTimeUtil.toString(oldestEntryTime))); - oldestEntryTime.add(Calendar.MINUTE, -2); - - if (doubleBolusDebug) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. oldestEntryTime (-2m): %s, timeInMillis=%d", DateTimeUtil.toString(oldestEntryTime), oldestEntryTime.getTimeInMillis())); - - return oldestEntryTime.getTimeInMillis(); - - } catch (Exception ex) { - aapsLogger.error("Problem decoding date from last record: " + currentTreatment); - return 8; // default return of 6 minutes - } - - } - - - private PumpHistoryEntryType getTDDType() { - - if (medtronicUtil.getMedtronicPumpModel() == null) { - return PumpHistoryEntryType.EndResultTotals; - } - - switch (medtronicUtil.getMedtronicPumpModel()) { - - case Medtronic_515: - case Medtronic_715: - return PumpHistoryEntryType.DailyTotals515; - - case Medtronic_522: - case Medtronic_722: - return PumpHistoryEntryType.DailyTotals522; - - case Medtronic_523_Revel: - case Medtronic_723_Revel: - case Medtronic_554_Veo: - case Medtronic_754_Veo: - return PumpHistoryEntryType.DailyTotals523; - - default: { - return PumpHistoryEntryType.EndResultTotals; - } - } - } - - - public boolean hasBasalProfileChanged() { - - List filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile); - - aapsLogger.debug(LTag.PUMP, "hasBasalProfileChanged. Items: " + gson().toJson(filteredItems)); - - return (filteredItems.size() > 0); - } - - - public void processLastBasalProfileChange(PumpType pumpType, MedtronicPumpStatus mdtPumpStatus) { - - List filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile); - - aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. Items: " + filteredItems); - - PumpHistoryEntry newProfile = null; - Long lastDate = null; - - if (filteredItems.size() == 1) { - newProfile = filteredItems.get(0); - } else if (filteredItems.size() > 1) { - - for (PumpHistoryEntry filteredItem : filteredItems) { - - if (lastDate == null || lastDate < filteredItem.getAtechDateTime()) { - newProfile = filteredItem; - lastDate = newProfile.getAtechDateTime(); - } - } - } - - if (newProfile != null) { - aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. item found, setting new basalProfileLocally: " + newProfile); - BasalProfile basalProfile = (BasalProfile) newProfile.getDecodedData().get("Object"); - - mdtPumpStatus.setBasalsByHour( basalProfile.getProfilesByHour(pumpType)); - } - } - - - public boolean hasPumpTimeChanged() { - return getStateFromFilteredList(PumpHistoryEntryType.NewTimeSet, // - PumpHistoryEntryType.ChangeTime); - } - - - public void setLastHistoryRecordTime(Long lastHistoryRecordTime) { - - // this.previousLastHistoryRecordTime = this.lastHistoryRecordTime; - } - - - public void setIsInInit(boolean init) { - this.isInit = init; - } - - - // HELPER METHODS - - private void sort(List list) { - if (list != null && !list.isEmpty()) { - Collections.sort(list, new PumpHistoryEntry.Comparator()); - } - } - - - private List preProcessTBRs(List TBRs_Input) { - List TBRs = new ArrayList<>(); - - Map map = new HashMap<>(); - - for (PumpHistoryEntry pumpHistoryEntry : TBRs_Input) { - if (map.containsKey(pumpHistoryEntry.getDT())) { - medtronicPumpHistoryDecoder.decodeTempBasal(map.get(pumpHistoryEntry.getDT()), pumpHistoryEntry); - pumpHistoryEntry.setEntryType(medtronicUtil.getMedtronicPumpModel(), PumpHistoryEntryType.TempBasalCombined); - TBRs.add(pumpHistoryEntry); - map.remove(pumpHistoryEntry.getDT()); - } else { - map.put(pumpHistoryEntry.getDT(), pumpHistoryEntry); - } - } - - return TBRs; - } - - - private List getFilteredItems(PumpHistoryEntryType... entryTypes) { - return getFilteredItems(this.newHistory, entryTypes); - } - - - private boolean getStateFromFilteredList(PumpHistoryEntryType... entryTypes) { - if (isInit) { - return false; - } else { - List filteredItems = getFilteredItems(entryTypes); - - aapsLogger.debug(LTag.PUMP, "Items: " + filteredItems); - - return filteredItems.size() > 0; - } - } - - - private List getFilteredItems(List inList, PumpHistoryEntryType... entryTypes) { - - // aapsLogger.debug(LTag.PUMP, "InList: " + inList.size()); - List outList = new ArrayList<>(); - - if (inList != null && inList.size() > 0) { - for (PumpHistoryEntry pumpHistoryEntry : inList) { - - if (!isEmpty(entryTypes)) { - for (PumpHistoryEntryType pumpHistoryEntryType : entryTypes) { - - if (pumpHistoryEntry.getEntryType() == pumpHistoryEntryType) { - outList.add(pumpHistoryEntry); - break; - } - } - } else { - outList.add(pumpHistoryEntry); - } - } - } - - // aapsLogger.debug(LTag.PUMP, "OutList: " + outList.size()); - - return outList; - } - - - private boolean isEmpty(PumpHistoryEntryType... entryTypes) { - return (entryTypes == null || (entryTypes.length == 1 && entryTypes[0] == null)); - } - - - private String getLogPrefix() { - return "MedtronicHistoryData::"; - } - -} diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt new file mode 100644 index 0000000000..dd81eafd00 --- /dev/null +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -0,0 +1,1152 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.data + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.db.* +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.interfaces.DatabaseHelperInterface +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +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.MedtronicPumpHistoryDecoder +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.* +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType +import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType +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 +import info.nightscout.androidaps.utils.Round +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.apache.commons.lang3.StringUtils +import org.joda.time.LocalDateTime +import org.joda.time.Minutes +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Created by andy on 10/12/18. + */ +// TODO: After release we need to refactor how data is retrieved from pump, each entry in history needs to be marked, and sorting +// needs to happen according those markings, not on time stamp (since AAPS can change time anytime it drifts away). This +// needs to include not returning any records if TZ goes into -x area. To fully support this AAPS would need to take note of +// all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can +// handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) +// All things marked with "TODO: Fix db code" needs to be updated in new 2.5 database code +@Suppress("DEPRECATION") +@Singleton +class MedtronicHistoryData @Inject constructor( + val injector: HasAndroidInjector, + val aapsLogger: AAPSLogger, + val sp: SP, + val activePlugin: ActivePlugin, + val medtronicUtil: MedtronicUtil, + val medtronicPumpHistoryDecoder: MedtronicPumpHistoryDecoder, + val medtronicPumpStatus: MedtronicPumpStatus, + val databaseHelper: DatabaseHelperInterface, + val pumpSync: PumpSync +) { + + val allHistory: MutableList = mutableListOf() + private var newHistory: MutableList = mutableListOf() + private var isInit = false + + private var pumpTime: ClockDTO? = null + private var lastIdUsed: Long = 0 + private var gson: Gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() + private var gsonCore: Gson = GsonBuilder().create() + + + /** + * Add New History entries + * + * @param result PumpHistoryResult instance + */ + fun addNewHistory(result: PumpHistoryResult) { + val validEntries: List = result.validEntries + val newEntries: MutableList = mutableListOf() + for (validEntry in validEntries) { + if (!allHistory.contains(validEntry)) { + newEntries.add(validEntry) + } + } + newHistory = newEntries + showLogs("List of history (before filtering): [" + newHistory.size + "]", gson.toJson(newHistory)) + } + + private fun showLogs(header: String?, data: String) { + if (header != null) { + aapsLogger.debug(LTag.PUMP, header) + } + if (StringUtils.isNotBlank(data)) { + for (token in StringUtil.splitString(data, 3500)) { + aapsLogger.debug(LTag.PUMP, token) + } + } else { + aapsLogger.debug(LTag.PUMP, "No data.") + } + } + + // fun getAllHistory(): List { + // return allHistory + // } + + fun filterNewEntries() { + val newHistory2: MutableList = mutableListOf() + var tbrs: MutableList = mutableListOf() + val bolusEstimates: MutableList = mutableListOf() + val atechDate = DateTimeUtil.toATechDate(GregorianCalendar()) + + //aapsLogger.debug(LTag.PUMP, "Filter new entries: Before {}", newHistory); + if (!isCollectionEmpty(newHistory)) { + for (pumpHistoryEntry in newHistory) { + if (!allHistory.contains(pumpHistoryEntry)) { + val type = pumpHistoryEntry.entryType + if (type === PumpHistoryEntryType.TempBasalRate || type === PumpHistoryEntryType.TempBasalDuration) { + tbrs.add(pumpHistoryEntry) + } else if (type === PumpHistoryEntryType.BolusWizard || type === PumpHistoryEntryType.BolusWizard512) { + bolusEstimates.add(pumpHistoryEntry) + newHistory2.add(pumpHistoryEntry) + } else { + if (type === PumpHistoryEntryType.EndResultTotals) { + if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.atechDateTime!!)) { + newHistory2.add(pumpHistoryEntry) + } + } else { + newHistory2.add(pumpHistoryEntry) + } + } + } + } + tbrs = preProcessTBRs(tbrs) + if (bolusEstimates.size > 0) { + extendBolusRecords(bolusEstimates, newHistory2) + } + newHistory2.addAll(tbrs) + newHistory = newHistory2 + sort(newHistory) + } + aapsLogger.debug(LTag.PUMP, "New History entries found: " + newHistory.size) + showLogs("List of history (after filtering): [" + newHistory.size + "]", gson.toJson(newHistory)) + } + + private fun extendBolusRecords(bolusEstimates: MutableList, newHistory2: MutableList) { + val boluses: MutableList = getFilteredItems(newHistory2, PumpHistoryEntryType.Bolus) + for (bolusEstimate in bolusEstimates) { + for (bolus in boluses) { + if (bolusEstimate.atechDateTime == bolus.atechDateTime) { + bolus.addDecodedData("Estimate", bolusEstimate.decodedData!!["Object"]) + } + } + } + } + + fun finalizeNewHistoryRecords() { + if (newHistory.isEmpty()) return + var pheLast = newHistory[0] + + // find last entry + for (pumpHistoryEntry in newHistory) { + if (pumpHistoryEntry.atechDateTime != null && pumpHistoryEntry.isAfter(pheLast.atechDateTime!!)) { + pheLast = pumpHistoryEntry + } + } + + // add new entries + newHistory.reverse() + for (pumpHistoryEntry in newHistory) { + if (!allHistory.contains(pumpHistoryEntry)) { + lastIdUsed++ + pumpHistoryEntry.id = lastIdUsed + allHistory.add(pumpHistoryEntry) + } + } + // if (pheLast == null) // if we don't have any valid record we don't do the filtering and setting + // return + //setLastHistoryRecordTime(pheLast.atechDateTime) + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.atechDateTime!!) + var dt: LocalDateTime? = null + try { + dt = DateTimeUtil.toLocalDateTime(pheLast.atechDateTime!!) + } catch (ex: Exception) { + aapsLogger.error("Problem decoding date from last record: $pheLast") + } + if (dt != null) { + dt = dt.minusDays(1) // we keep 24 hours + val dtRemove = DateTimeUtil.toATechDate(dt) + val removeList: MutableList = ArrayList() + for (pumpHistoryEntry in allHistory) { + if (!pumpHistoryEntry.isAfter(dtRemove)) { + removeList.add(pumpHistoryEntry) + } + } + allHistory.removeAll(removeList) + this.sort(allHistory) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "All History records [afterFilterCount=%d, removedItemsCount=%d, newItemsCount=%d]", + allHistory.size, removeList.size, newHistory.size)) + } else { + aapsLogger.error("Since we couldn't determine date, we don't clean full history. This is just workaround.") + } + newHistory.clear() + } + + fun hasRelevantConfigurationChanged(): Boolean { + return getStateFromFilteredList( // + setOf(PumpHistoryEntryType.ChangeBasalPattern, // + PumpHistoryEntryType.ClearSettings, // + PumpHistoryEntryType.SaveSettings, // + PumpHistoryEntryType.ChangeMaxBolus, // + PumpHistoryEntryType.ChangeMaxBasal, // + PumpHistoryEntryType.ChangeTempBasalType)) + } + + private fun isCollectionEmpty(col: List<*>?): Boolean { + return col == null || col.isEmpty() + } + + private fun isCollectionNotEmpty(col: List<*>?): Boolean { + return col != null && !col.isEmpty() + }//////// + + // + val isPumpSuspended: Boolean + get() { + val items = getDataForPumpSuspends() + showLogs("isPumpSuspended: ", gson.toJson(items)) + return if (isCollectionNotEmpty(items)) { + val pumpHistoryEntryType = items[0].entryType + val isSuspended = !(pumpHistoryEntryType === PumpHistoryEntryType.TempBasalCombined || // + pumpHistoryEntryType === PumpHistoryEntryType.BasalProfileStart || // + pumpHistoryEntryType === PumpHistoryEntryType.Bolus || // + pumpHistoryEntryType === PumpHistoryEntryType.ResumePump || // + pumpHistoryEntryType === PumpHistoryEntryType.BatteryChange || // + pumpHistoryEntryType === PumpHistoryEntryType.Prime) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "isPumpSuspended. Last entry type=%s, isSuspended=%b", pumpHistoryEntryType, isSuspended)) + isSuspended + } else false + } + + private fun getDataForPumpSuspends(): MutableList { + val newAndAll: MutableList = mutableListOf() + if (isCollectionNotEmpty(allHistory)) { + newAndAll.addAll(allHistory) + } + if (isCollectionNotEmpty(newHistory)) { + for (pumpHistoryEntry in newHistory!!) { + if (!newAndAll.contains(pumpHistoryEntry)) { + newAndAll.add(pumpHistoryEntry) + } + } + } + if (newAndAll.isEmpty()) return newAndAll + this.sort(newAndAll) + var newAndAll2: MutableList = getFilteredItems(newAndAll, // + setOf(PumpHistoryEntryType.Bolus, // + PumpHistoryEntryType.TempBasalCombined, // + PumpHistoryEntryType.Prime, // + PumpHistoryEntryType.SuspendPump, // + PumpHistoryEntryType.ResumePump, // + PumpHistoryEntryType.Rewind, // + PumpHistoryEntryType.NoDeliveryAlarm, // + PumpHistoryEntryType.BatteryChange, // + PumpHistoryEntryType.BasalProfileStart)) + newAndAll2 = filterPumpSuspend(newAndAll2, 10) + return newAndAll2 + } + + private fun filterPumpSuspend(newAndAll: MutableList, filterCount: Int): MutableList { + if (newAndAll.size <= filterCount) { + return newAndAll + } + val newAndAllOut: MutableList = ArrayList() + for (i in 0 until filterCount) { + newAndAllOut.add(newAndAll[i]) + } + return newAndAllOut + } + + /** + * Process History Data: Boluses(Treatments), TDD, TBRs, Suspend-Resume (or other pump stops: battery, prime) + */ + fun processNewHistoryData() { + + // TODO: Fix db code + // Prime (for reseting autosense) + val primeRecords: MutableList = getFilteredItems(PumpHistoryEntryType.Prime) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Prime [count=%d, items=%s]", primeRecords.size, gson.toJson(primeRecords))) + if (isCollectionNotEmpty(primeRecords)) { + try { + processPrime(primeRecords) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Prime entries: " + ex.message, ex) + throw ex + } + } + + // Rewind (for marking insulin change) + val rewindRecords: MutableList = getFilteredItems(PumpHistoryEntryType.Rewind) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Rewind [count=%d, items=%s]", rewindRecords.size, gson.toJson(rewindRecords))) + if (isCollectionNotEmpty(rewindRecords)) { + try { + processRewind(rewindRecords) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Rewind entries: " + ex.message, ex) + throw ex + } + } + + // TDD + val tdds: MutableList = getFilteredItems(setOf(PumpHistoryEntryType.EndResultTotals, tDDType)) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TDD [count=%d, items=%s]", tdds.size, gson.toJson(tdds))) + if (isCollectionNotEmpty(tdds)) { + try { + processTDDs(tdds) + } catch (ex: Exception) { + aapsLogger.error("ProcessHistoryData: Error processing TDD entries: " + ex.message, ex) + throw ex + } + } + pumpTime = medtronicUtil.pumpTime + + // Bolus + val treatments = getFilteredItems(PumpHistoryEntryType.Bolus) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Bolus [count=%d, items=%s]", treatments.size, gson.toJson(treatments))) + if (treatments.size > 0) { + try { + processBolusEntries(treatments) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Bolus entries: " + ex.message, ex) + throw ex + } + } + + // TBR + val tbrs: MutableList = getFilteredItems(PumpHistoryEntryType.TempBasalCombined) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TBRs Processed [count=%d, items=%s]", tbrs.size, gson.toJson(tbrs))) + if (tbrs.size > 0) { + try { + processTBREntries(tbrs) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing TBR entries: " + ex.message, ex) + throw ex + } + } + + // 'Delivery Suspend' + val suspends: MutableList + suspends = try { + getSuspendRecords() + } catch (ex: Exception) { + aapsLogger.error("ProcessHistoryData: Error getting Suspend entries: " + ex.message, ex) + throw ex + } + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: 'Delivery Suspend' Processed [count=%d, items=%s]", suspends.size, + gson.toJson(suspends))) + if (isCollectionNotEmpty(suspends)) { + try { + processSuspends(suspends) + } catch (ex: Exception) { + aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Suspends entries: " + ex.message, ex) + throw ex + } + } + } + + private fun processPrime(primeRecords: List) { + val maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(GregorianCalendar(), -30) + var lastPrimeRecord = 0L + for (primeRecord in primeRecords) { + val fixedAmount = primeRecord!!.getDecodedDataEntry("FixedAmount") + if (fixedAmount != null && fixedAmount as Float == 0.0f) { + // non-fixed primes are used to prime the tubing + // fixed primes are used to prime the cannula + // so skip the prime entry if it was not a fixed prime + continue + } + if (primeRecord.atechDateTime!! > maxAllowedTimeInPast) { + if (lastPrimeRecord < primeRecord.atechDateTime!!) { + lastPrimeRecord = primeRecord.atechDateTime!! + } + } + } + if (lastPrimeRecord != 0L) { + val lastPrimeFromAAPS = sp.getLong(MedtronicConst.Statistics.LastPrime, 0L) + if (lastPrimeRecord != lastPrimeFromAAPS) { + uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastPrimeRecord), DetailedBolusInfo.EventType.CANNULA_CHANGE) + sp.putLong(MedtronicConst.Statistics.LastPrime, lastPrimeRecord) + } + } + } + + private fun processRewind(rewindRecords: List) { + val maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(GregorianCalendar(), -30) + var lastRewindRecord = 0L + for (rewindRecord in rewindRecords) { + if (rewindRecord!!.atechDateTime!! > maxAllowedTimeInPast) { + if (lastRewindRecord < rewindRecord.atechDateTime!!) { + lastRewindRecord = rewindRecord.atechDateTime!! + } + } + } + if (lastRewindRecord != 0L) { + val lastRewindFromAAPS = sp.getLong(MedtronicConst.Statistics.LastRewind, 0L) + if (lastRewindRecord != lastRewindFromAAPS) { + uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastRewindRecord), DetailedBolusInfo.EventType.INSULIN_CHANGE) + sp.putLong(MedtronicConst.Statistics.LastRewind, lastRewindRecord) + } + } + } + + private fun uploadCareportalEvent(date: Long, event: DetailedBolusInfo.EventType) { + pumpSync.insertTherapyEventIfNewWithTimestamp(date, event, null, null, + medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) + } + + private fun processTDDs(tddsIn: MutableList) { + val tdds = filterTDDs(tddsIn) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, """ + ${logPrefix}TDDs found: %d. + %s + """.trimIndent(), tdds.size, gson.toJson(tdds))) + val tddsDb = databaseHelper.getTDDsForLastXDays(3) + for (tdd in tdds) { + val tddDbEntry = findTDD(tdd.atechDateTime!!, tddsDb) + val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO? + + //aapsLogger.debug(LTag.PUMP, "DailyTotals: {}", totalsDTO); + if (tddDbEntry == null) { + val tddNew = TDD() + totalsDTO!!.setTDD(tddNew) + aapsLogger.debug(LTag.PUMP, "TDD Add: $tddNew") + databaseHelper.createOrUpdateTDD(tddNew) + } else { + if (!totalsDTO!!.doesEqual(tddDbEntry)) { + totalsDTO.setTDD(tddDbEntry) + aapsLogger.debug(LTag.PUMP, "TDD Edit: $tddDbEntry") + databaseHelper.createOrUpdateTDD(tddDbEntry) + } + } + } + } + + private enum class ProcessHistoryRecord(val description: String) { + Bolus("Bolus"), + TBR("TBR"), + Suspend("Suspend"); + } + + private fun processBolusEntries(entryList: MutableList) { + val oldestTimestamp = getOldestTimestamp(entryList) + val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.Bolus) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (before filter): %s, FromDb=%s", gson.toJson(entryList), + gsonCore.toJson(entriesFromHistory))) + filterOutAlreadyAddedEntries(entryList, entriesFromHistory) + if (entryList.isEmpty()) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: EntryList was filtered out.") + return + } + filterOutNonInsulinEntries(entriesFromHistory) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (after filter): %s, FromDb=%s", gson.toJson(entryList), + gsonCore.toJson(entriesFromHistory))) + if (isCollectionEmpty(entriesFromHistory)) { + for (treatment in entryList) { + aapsLogger.debug(LTag.PUMP, "Add Bolus (no db entry): $treatment") + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: Add Bolus: FromDb=null, Treatment=$treatment") + addBolus(treatment, null) + } + } else { + for (treatment in entryList) { + val treatmentDb = findDbEntry(treatment, entriesFromHistory) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add Bolus %s - (entryFromDb=%s) ", treatment, treatmentDb)) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: Add Bolus: FromDb=%s, Treatment=%s", treatmentDb, treatment)) + addBolus(treatment, treatmentDb as Treatment?) + } + } + } + + private fun filterOutNonInsulinEntries(entriesFromHistory: MutableList) { + // when we try to pair PumpHistory with AAPS treatments, we need to ignore all non-insulin entries + val removeList: MutableList = mutableListOf() + for (dbObjectBase in entriesFromHistory) { + val treatment = dbObjectBase as Treatment + if (Round.isSame(treatment.insulin, 0.0)) { + removeList.add(dbObjectBase) + } + } + entriesFromHistory.removeAll(removeList) + } + + private fun processTBREntries(entryList: MutableList) { + Collections.reverse(entryList) + val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? + var readOldItem = false + if (tbr!!.isCancelTBR) { + val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) + if (oneMoreEntryFromHistory != null) { + entryList.add(0, oneMoreEntryFromHistory) + readOldItem = true + } else { + entryList.removeAt(0) + } + } + val oldestTimestamp = getOldestTimestamp(entryList) + val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.TBR) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.description + " List (before filter): %s, FromDb=%s", gson.toJson(entryList), + gson.toJson(entriesFromHistory))) + var processDTO: TempBasalProcessDTO? = null + val processList: MutableList = ArrayList() + for (treatment in entryList) { + val tbr2 = treatment!!.getDecodedDataEntry("Object") as TempBasalPair? + if (tbr2!!.isCancelTBR) { + if (processDTO != null) { + processDTO.itemTwo = treatment + if (readOldItem) { + processDTO.processOperation = TempBasalProcessDTO.Operation.Edit + readOldItem = false + } + } else { + aapsLogger.error("processDTO was null - shouldn't happen. ItemTwo=$treatment") + } + } else { + if (processDTO != null) { + processList.add(processDTO) + } + processDTO = TempBasalProcessDTO() + processDTO.itemOne = treatment + processDTO.processOperation = TempBasalProcessDTO.Operation.Add + } + } + if (processDTO != null) { + processList.add(processDTO) + } + if (isCollectionNotEmpty(processList)) { + for (tempBasalProcessDTO in processList) { + if (tempBasalProcessDTO.processOperation === TempBasalProcessDTO.Operation.Edit) { + // edit + val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) + if (tempBasal != null) { + tempBasal.durationInMinutes = tempBasalProcessDTO.duration + databaseHelper.createOrUpdate(tempBasal) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Edit " + ProcessHistoryRecord.TBR.description + " - (entryFromDb=%s) ", tempBasal)) + } else { + aapsLogger.error(LTag.PUMP, "TempBasal not found. Item: " + tempBasalProcessDTO.itemOne) + } + } else { + // add + val treatment = tempBasalProcessDTO.itemOne + val tbr2 = treatment!!.decodedData!!["Object"] as TempBasalPair? + tbr2!!.durationMinutes = tempBasalProcessDTO.duration + val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) + if (tempBasal == null) { + val treatmentDb = findDbEntry(treatment, entriesFromHistory) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add " + ProcessHistoryRecord.TBR.description + " %s - (entryFromDb=%s) ", treatment, treatmentDb)) + addTBR(treatment, treatmentDb as TemporaryBasal?) + } else { + // this shouldn't happen + if (tempBasal.durationInMinutes != tempBasalProcessDTO.duration) { + aapsLogger.debug(LTag.PUMP, "Found entry with wrong duration (shouldn't happen)... updating") + tempBasal.durationInMinutes = tempBasalProcessDTO.duration + } + } + } // if + } // for + } // collection + } + + private fun findTempBasalWithPumpId(pumpId: Long, entriesFromHistory: List): TemporaryBasal? { + for (dbObjectBase in entriesFromHistory) { + val tbr = dbObjectBase as TemporaryBasal + if (tbr.pumpId == pumpId) { + return tbr + } + } + return databaseHelper.findTempBasalByPumpId(pumpId) + } + + /** + * findDbEntry - finds Db entries in database, while theoretically this should have same dateTime they + * don't. Entry on pump is few seconds before treatment in AAPS, and on manual boluses on pump there + * is no treatment at all. For now we look fro tratment that was from 0s - 1m59s within pump entry. + * + * @param treatment Pump Entry + * @param entriesFromHistory entries from history + * @return DbObject from AAPS (if found) + */ + private fun findDbEntry(treatment: PumpHistoryEntry?, entriesFromHistory: List): DbObjectBase? { + val proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) + + //proposedTime += (this.pumpTime.timeDifference * 1000); + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s", treatment, gson.toJson(entriesFromHistory))) + if (entriesFromHistory.size == 0) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=null", treatment)) + return null + } else if (entriesFromHistory.size == 1) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s. Type=SingleEntry", treatment, entriesFromHistory[0])) + + // TODO: Fix db code + // if difference is bigger than 2 minutes we discard entry + val maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.atechDateTime!!, 2) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry maxMillisAllowed=%d, AtechDateTime=%d (add 2 minutes). ", maxMillisAllowed, treatment.atechDateTime)) + if (entriesFromHistory[0].getDate() > maxMillisAllowed) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: findDbEntry entry filtered out, returning null. ") + return null + } + return entriesFromHistory[0] + } + var min = 0 + while (min < 2) { + var sec = 0 + while (sec <= 50) { + if (min == 1 && sec == 50) { + sec = 59 + } + val diff = sec * 1000 + val outList: MutableList = ArrayList() + for (treatment1 in entriesFromHistory) { + if (treatment1.getDate() > proposedTime - diff && treatment1.getDate() < proposedTime + diff) { + outList.add(treatment1) + } + } + if (outList.size == 1) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}. Type=EntrySelected, AtTimeMin={}, AtTimeSec={}", treatment, entriesFromHistory[0], min, sec)) + return outList[0] + } + if (min == 0 && sec == 10 && outList.size > 1) { + aapsLogger.error(String.format(Locale.ENGLISH, "Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", + min, sec, outList.size, gson.toJson(outList))) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Error - Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", + min, sec, outList.size, gson.toJson(outList))) + } + sec += 10 + } + min += 1 + } + return null + } + + private fun getDatabaseEntriesByLastTimestamp(startTimestamp: Long, processHistoryRecord: ProcessHistoryRecord): MutableList { + var outList: MutableList = mutableListOf() + + if (processHistoryRecord == ProcessHistoryRecord.Bolus) { + // TODO pumpSync + outList.addAll(activePlugin.activeTreatments.getTreatmentsFromHistoryAfterTimestamp(startTimestamp)) + } else { + // TODO pumpSync + outList.addAll(databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true)) + } + + return outList + } + + private fun filterOutAlreadyAddedEntries(entryList: MutableList, treatmentsFromHistory: MutableList) { + if (isCollectionEmpty(treatmentsFromHistory)) + return + + val removeTreatmentsFromHistory: MutableList = ArrayList() + val removeTreatmentsFromPH: MutableList = ArrayList() + + for (treatment in treatmentsFromHistory) { + if (treatment.getPumpId() != 0L) { + var selectedBolus: PumpHistoryEntry? = null + for (bolus in entryList) { + if (bolus.pumpId == treatment.getPumpId()) { + selectedBolus = bolus + break + } + } + if (selectedBolus != null) { + entryList.remove(selectedBolus) + removeTreatmentsFromPH.add(selectedBolus) + removeTreatmentsFromHistory.add(treatment) + } + } + } + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: filterOutAlreadyAddedEntries: PumpHistory=%s, Treatments=%s", + gson.toJson(removeTreatmentsFromPH), + gsonCore.toJson(removeTreatmentsFromHistory))) + treatmentsFromHistory.removeAll(removeTreatmentsFromHistory) + } + + private fun addBolus(bolus: PumpHistoryEntry?, treatment: Treatment?) { + val bolusDTO = bolus!!.decodedData!!["Object"] as BolusDTO? + if (treatment == null) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): Bolus=$bolusDTO") + when (bolusDTO!!.bolusType) { + PumpBolusType.Normal -> { + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.bolusTimestamp = tryToGetByLocalTime(bolus.atechDateTime!!) + detailedBolusInfo.pumpType = medtronicPumpStatus.pumpType + detailedBolusInfo.pumpSerial = medtronicPumpStatus.serialNumber + detailedBolusInfo.bolusPumpId = bolus.pumpId + detailedBolusInfo.insulin = bolusDTO.deliveredAmount!! + addCarbsFromEstimate(detailedBolusInfo, bolus) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): DetailedBolusInfo=$detailedBolusInfo") + // TODO pumpSync + val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) + bolus.linkedObject = detailedBolusInfo + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.timestamp, + detailedBolusInfo.bolusPumpId, detailedBolusInfo.insulin, newRecord)) + } + + PumpBolusType.Audio, PumpBolusType.Extended -> { + val extendedBolus = ExtendedBolus(injector) + extendedBolus.date = tryToGetByLocalTime(bolus.atechDateTime!!) + extendedBolus.source = Source.PUMP + extendedBolus.insulin = bolusDTO.deliveredAmount!! + extendedBolus.pumpId = bolus.pumpId!! + extendedBolus.isValid = true + extendedBolus.durationInMinutes = bolusDTO.duration!! + bolus.linkedObject = extendedBolus + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): ExtendedBolus=$extendedBolus") + // TODO pumpSync + activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - Extended [date=%d,pumpId=%d, insulin=%.3f, duration=%d]", extendedBolus.date, + extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes)) + } + } + } else { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(OldTreatment=%s): Bolus=%s", treatment, bolusDTO)) + treatment.source = Source.PUMP + treatment.pumpId = bolus.pumpId!! + treatment.insulin = bolusDTO!!.deliveredAmount!! + // TODO pumpSync + val updateReturn = activePlugin.activeTreatments.createOrUpdateMedtronic(treatment, false) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(tretament!=null): NewTreatment=%s, UpdateReturn=%s", treatment, updateReturn)) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "editBolus - [date=%d,pumpId=%d, insulin=%.3f, newRecord=%s]", treatment.date, + treatment.pumpId, treatment.insulin, updateReturn.toString())) + bolus.linkedObject = treatment + } + } + + private fun addCarbsFromEstimate(detailedBolusInfo: DetailedBolusInfo, bolus: PumpHistoryEntry?) { + if (bolus!!.containsDecodedData("Estimate")) { + val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO? + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard)) + detailedBolusInfo.carbs = bolusWizard!!.carbs.toDouble() + } + } + + private fun addTBR(treatment: PumpHistoryEntry?, temporaryBasalDbInput: TemporaryBasal?) { + val tbr = treatment!!.decodedData!!["Object"] as TempBasalPair? + var temporaryBasalDb = temporaryBasalDbInput + var operation = "editTBR" + if (temporaryBasalDb == null) { + temporaryBasalDb = TemporaryBasal(injector) + temporaryBasalDb.date = tryToGetByLocalTime(treatment.atechDateTime!!) + operation = "addTBR" + } + temporaryBasalDb.source = Source.PUMP + temporaryBasalDb.pumpId = treatment.pumpId!! + temporaryBasalDb.durationInMinutes = tbr!!.durationMinutes + temporaryBasalDb.absoluteRate = tbr.insulinRate + temporaryBasalDb.isAbsolute = !tbr.isPercent + treatment.linkedObject = temporaryBasalDb + databaseHelper.createOrUpdate(temporaryBasalDb) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "$operation - [date=%d,pumpId=%d, rate=%s %s, duration=%d]", // + temporaryBasalDb.getDate(), // + temporaryBasalDb.getPumpId(), // + if (temporaryBasalDb.isAbsolute) String.format(Locale.ENGLISH, "%.2f", temporaryBasalDb.absoluteRate) else String.format(Locale.ENGLISH, "%d", temporaryBasalDb.percentRate), // + if (temporaryBasalDb.isAbsolute) "U/h" else "%", // + temporaryBasalDb.durationInMinutes)) + } + + private fun processSuspends(tempBasalProcessList: List) { + for (tempBasalProcess in tempBasalProcessList) { + var tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne!!.pumpId!!) + if (tempBasal == null) { + // add + tempBasal = TemporaryBasal(injector) + tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne!!.atechDateTime!!) + tempBasal.source = Source.PUMP + tempBasal.pumpId = tempBasalProcess.itemOne!!.pumpId!! + tempBasal.durationInMinutes = tempBasalProcess.duration + tempBasal.absoluteRate = 0.0 + tempBasal.isAbsolute = true + tempBasalProcess.itemOne!!.linkedObject = tempBasal + tempBasalProcess.itemTwo!!.linkedObject = tempBasal + databaseHelper.createOrUpdate(tempBasal) + } + } + } + + // suspend/resume + // no_delivery/prime & rewind/prime + private fun getSuspendRecords(): MutableList { + val outList: MutableList = ArrayList() + + // suspend/resume + outList.addAll(getSuspendResumeRecordsList()) + // no_delivery/prime & rewind/prime + outList.addAll(getNoDeliveryRewindPrimeRecordsList()) + return outList + }// remove last and have paired items// remove last (unpaired R)// get one more from history (R S R) -> ([S] R S R)// remove last (unpaired R)// not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS])// full resume suspends (S R S R) + + // + // + private fun getSuspendResumeRecordsList(): List { + val filteredItems = getFilteredItems(newHistory, // + setOf(PumpHistoryEntryType.SuspendPump, PumpHistoryEntryType.ResumePump)) + val outList: MutableList = mutableListOf() + if (filteredItems.size > 0) { + val filtered2Items: MutableList = mutableListOf() + if (filteredItems.size % 2 == 0 && filteredItems[0].entryType === PumpHistoryEntryType.ResumePump) { + // full resume suspends (S R S R) + filtered2Items.addAll(filteredItems) + } else if (filteredItems.size % 2 == 0 && filteredItems[0].entryType === PumpHistoryEntryType.SuspendPump) { + // not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS]) + filteredItems.removeAt(0) + val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump) + if (oneMoreEntryFromHistory != null) { + filteredItems.add(oneMoreEntryFromHistory) + } else { + filteredItems.removeAt(filteredItems.size - 1) // remove last (unpaired R) + } + filtered2Items.addAll(filteredItems) + } else { + if (filteredItems[0].entryType === PumpHistoryEntryType.ResumePump) { + // get one more from history (R S R) -> ([S] R S R) + val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump) + if (oneMoreEntryFromHistory != null) { + filteredItems.add(oneMoreEntryFromHistory) + } else { + filteredItems.removeAt(filteredItems.size - 1) // remove last (unpaired R) + } + filtered2Items.addAll(filteredItems) + } else { + // remove last and have paired items + filteredItems.removeAt(0) + filtered2Items.addAll(filteredItems) + } + } + if (filtered2Items.size > 0) { + sort(filtered2Items) + Collections.reverse(filtered2Items) + var i = 0 + while (i < filtered2Items.size) { + val dto = TempBasalProcessDTO() + dto.itemOne = filtered2Items[i] + dto.itemTwo = filtered2Items[i + 1] + dto.processOperation = TempBasalProcessDTO.Operation.Add + outList.add(dto) + i += 2 + } + } + } + return outList + }////////// + + // + private fun getNoDeliveryRewindPrimeRecordsList(): List { + val primeItems: MutableList = getFilteredItems(newHistory, // + setOf(PumpHistoryEntryType.Prime)) + val outList: MutableList = ArrayList() + if (primeItems.size == 0) return outList + val filteredItems: MutableList = getFilteredItems(newHistory, // + setOf(PumpHistoryEntryType.Prime, + PumpHistoryEntryType.Rewind, + PumpHistoryEntryType.NoDeliveryAlarm, + PumpHistoryEntryType.Bolus, + PumpHistoryEntryType.TempBasalCombined) + ) + val tempData: MutableList = mutableListOf() + var startedItems = false + var finishedItems = false + for (filteredItem in filteredItems) { + if (filteredItem.entryType === PumpHistoryEntryType.Prime) { + startedItems = true + } + if (startedItems) { + if (filteredItem.entryType === PumpHistoryEntryType.Bolus || + filteredItem.entryType === PumpHistoryEntryType.TempBasalCombined) { + finishedItems = true + break + } + tempData.add(filteredItem) + } + } + if (!finishedItems) { + val filteredItemsOld: MutableList = getFilteredItems(allHistory, // + setOf(PumpHistoryEntryType.Rewind, + PumpHistoryEntryType.NoDeliveryAlarm, + PumpHistoryEntryType.Bolus, + PumpHistoryEntryType.TempBasalCombined) + ) + for (filteredItem in filteredItemsOld) { + if (filteredItem.entryType === PumpHistoryEntryType.Bolus || + filteredItem.entryType === PumpHistoryEntryType.TempBasalCombined) { + finishedItems = true + break + } + tempData.add(filteredItem) + } + } + if (!finishedItems) { + showLogs("NoDeliveryRewindPrimeRecords: Not finished Items: ", gson.toJson(tempData)) + return outList + } + showLogs("NoDeliveryRewindPrimeRecords: Records to evaluate: ", gson.toJson(tempData)) + var items: MutableList = getFilteredItems(tempData, PumpHistoryEntryType.Prime) + val processDTO = TempBasalProcessDTO() + processDTO.itemTwo = items[0] + items = getFilteredItems(tempData, PumpHistoryEntryType.NoDeliveryAlarm) + if (items.size > 0) { + processDTO.itemOne = items[items.size - 1] + processDTO.processOperation = TempBasalProcessDTO.Operation.Add + outList.add(processDTO) + return outList + } + items = getFilteredItems(tempData, PumpHistoryEntryType.Rewind) + if (items.size > 0) { + processDTO.itemOne = items[0] + processDTO.processOperation = TempBasalProcessDTO.Operation.Add + outList.add(processDTO) + return outList + } + return outList + } + + private fun getOneMoreEntryFromHistory(entryType: PumpHistoryEntryType): PumpHistoryEntry? { + val filteredItems: List = getFilteredItems(allHistory, entryType) + return if (filteredItems.size == 0) null else filteredItems[0] + } + + private fun filterTDDs(tdds: MutableList): MutableList { + val tddsOut: MutableList = mutableListOf() + for (tdd in tdds) { + if (tdd.entryType !== PumpHistoryEntryType.EndResultTotals) { + tddsOut.add(tdd) + } + } + return if (tddsOut.size == 0) tdds else tddsOut + } + + private fun findTDD(atechDateTime: Long, tddsDb: List): TDD? { + for (tdd in tddsDb) { + if (DateTimeUtil.isSameDayATDAndMillis(atechDateTime, tdd.date)) { + return tdd + } + } + return null + } + + private fun tryToGetByLocalTime(atechDateTime: Long): Long { + return DateTimeUtil.toMillisFromATD(atechDateTime) + } + +// private fun getOldestDateDifference(treatments: List): Int { +// var dt = Long.MAX_VALUE +// var currentTreatment: PumpHistoryEntry? = null +// if (isCollectionEmpty(treatments)) { +// return 8 // default return of 6 (5 for diif on history reading + 2 for max allowed difference) minutes +// } +// for (treatment in treatments) { +// if (treatment.atechDateTime!! < dt) { +// dt = treatment.atechDateTime!! +// currentTreatment = treatment +// } +// } +// var oldestEntryTime: LocalDateTime +// try { +// oldestEntryTime = DateTimeUtil.toLocalDateTime(dt) +// oldestEntryTime = oldestEntryTime.minusMinutes(3) +// +// // if (this.pumpTime.timeDifference < 0) { +// // oldestEntryTime = oldestEntryTime.plusSeconds(this.pumpTime.timeDifference); +// // } +// } catch (ex: Exception) { +// aapsLogger.error("Problem decoding date from last record: $currentTreatment") +// return 8 // default return of 6 minutes +// } +// val now = LocalDateTime() +// val minutes = Minutes.minutesBetween(oldestEntryTime, now) +// +// // 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, +// pumpTime!!.timeDifference, oldestEntryTime, now, minutes.minutes)) +// return minutes.minutes +// } + + private fun getOldestTimestamp(treatments: List): Long { + var dt = Long.MAX_VALUE + var currentTreatment: PumpHistoryEntry? = null + for (treatment in treatments) { + if (treatment!!.atechDateTime!! < dt) { + dt = treatment.atechDateTime!! + currentTreatment = treatment + } + } + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. Oldest entry found: time=%d, object=%s", dt, currentTreatment)) + return try { + val oldestEntryTime = DateTimeUtil.toGregorianCalendar(dt) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. oldestEntryTime: %s", DateTimeUtil.toString(oldestEntryTime))) + oldestEntryTime.add(Calendar.MINUTE, -2) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. oldestEntryTime (-2m): %s, timeInMillis=%d", DateTimeUtil.toString(oldestEntryTime), oldestEntryTime.timeInMillis)) + oldestEntryTime.timeInMillis + } catch (ex: Exception) { + aapsLogger.error("Problem decoding date from last record: $currentTreatment") + 8 // default return of 6 minutes + } + } + + private val tDDType: PumpHistoryEntryType + get() = if (medtronicUtil.medtronicPumpModel == null) { + PumpHistoryEntryType.EndResultTotals + } else when (medtronicUtil.medtronicPumpModel) { + MedtronicDeviceType.Medtronic_515, MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 + MedtronicDeviceType.Medtronic_522, MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 + MedtronicDeviceType.Medtronic_523_Revel, + MedtronicDeviceType.Medtronic_723_Revel, + MedtronicDeviceType.Medtronic_554_Veo, + MedtronicDeviceType.Medtronic_754_Veo -> PumpHistoryEntryType.DailyTotals523 + else -> { + PumpHistoryEntryType.EndResultTotals + } + } + + fun hasBasalProfileChanged(): Boolean { + val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) + aapsLogger.debug(LTag.PUMP, "hasBasalProfileChanged. Items: " + gson.toJson(filteredItems)) + return filteredItems.size > 0 + } + + fun processLastBasalProfileChange(pumpType: PumpType?, mdtPumpStatus: MedtronicPumpStatus) { + val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) + aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. Items: $filteredItems") + var newProfile: PumpHistoryEntry? = null + var lastDate: Long? = null + if (filteredItems.size == 1) { + newProfile = filteredItems[0] + } else if (filteredItems.size > 1) { + for (filteredItem in filteredItems) { + if (lastDate == null || lastDate < filteredItem!!.atechDateTime!!) { + newProfile = filteredItem + lastDate = newProfile!!.atechDateTime + } + } + } + if (newProfile != null) { + aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. item found, setting new basalProfileLocally: $newProfile") + val basalProfile = newProfile.decodedData!!["Object"] as BasalProfile? + mdtPumpStatus.basalsByHour = basalProfile!!.getProfilesByHour(pumpType!!) + } + } + + fun hasPumpTimeChanged(): Boolean { + return getStateFromFilteredList(setOf(PumpHistoryEntryType.NewTimeSet, // + PumpHistoryEntryType.ChangeTime)) + } + + // fun setLastHistoryRecordTime(lastHistoryRecordTime: Long?) { + // // this.previousLastHistoryRecordTime = this.lastHistoryRecordTime; + // } + + fun setIsInInit(init: Boolean) { + isInit = init + } + + // HELPER METHODS + private fun sort(list: MutableList) { + // if (list != null && !list.isEmpty()) { + // Collections.sort(list, PumpHistoryEntry.Comparator()) + // } + list.sortWith(PumpHistoryEntry.Comparator()) + } + + private fun preProcessTBRs(TBRs_Input: MutableList): MutableList { + val TBRs: MutableList = mutableListOf() + val map: MutableMap = HashMap() + for (pumpHistoryEntry in TBRs_Input) { + if (map.containsKey(pumpHistoryEntry.DT)) { + medtronicPumpHistoryDecoder.decodeTempBasal(map[pumpHistoryEntry.DT]!!, pumpHistoryEntry) + pumpHistoryEntry.setEntryType(medtronicUtil.medtronicPumpModel!!, PumpHistoryEntryType.TempBasalCombined) + TBRs.add(pumpHistoryEntry) + map.remove(pumpHistoryEntry.DT) + } else { + map[pumpHistoryEntry.DT] = pumpHistoryEntry + } + } + return TBRs + } + + private fun getFilteredItems(entryTypes: Set?): MutableList { + return getFilteredItems(newHistory, entryTypes) + } + + private fun getFilteredItems(entryType: PumpHistoryEntryType): MutableList { + return getFilteredItems(newHistory, setOf(entryType)) + } + + private fun getStateFromFilteredList(entryTypes: Set?): Boolean { + return if (isInit) { + false + } else { + val filteredItems: List = getFilteredItems(entryTypes) + aapsLogger.debug(LTag.PUMP, "Items: $filteredItems") + filteredItems.size > 0 + } + } + + private fun getFilteredItems(inList: MutableList?, entryType: PumpHistoryEntryType): MutableList { + return getFilteredItems(inList, setOf(entryType)) + } + + private fun getFilteredItems(inList: MutableList?, entryTypes: Set?): MutableList { + + // aapsLogger.debug(LTag.PUMP, "InList: " + inList.size()); + val outList: MutableList = mutableListOf() + if (inList != null && inList.size > 0) { + for (pumpHistoryEntry in inList) { + if (!isEmpty(entryTypes)) { + if (entryTypes!!.contains(pumpHistoryEntry.entryType)) { + outList.add(pumpHistoryEntry) + } + } else { + outList.add(pumpHistoryEntry) + } + } + } + + // aapsLogger.debug(LTag.PUMP, "OutList: " + outList.size()); + return outList + } + + private fun isEmpty(entryTypes: Set?): Boolean { + return entryTypes.isNullOrEmpty() + //return entryTypes == null || entryTypes.size == 1 && entryTypes[0] == null + } + + private val logPrefix: String + get() = "MedtronicHistoryData::" + + companion object { + /** + * Double bolus debug. We seem to have small problem with double Boluses (or sometimes also missing boluses + * from history. This flag turns on debugging for that (default is off=false)... Debugging is pretty detailed, + * so log files will get bigger. + * Note: June 2020. Since this seems to be fixed, I am disabling this per default. I will leave code inside + * in case we need it again. Code that turns this on is commented out RileyLinkMedtronicService#verifyConfiguration() + */ + const val doubleBolusDebug = false + } + + init { + //allHistory = ArrayList() + //this.injector = injector + //this.aapsLogger = aapsLogger + // this.sp = sp + // this.activePlugin = activePlugin + // this.medtronicUtil = medtronicUtil + // this.medtronicPumpHistoryDecoder = medtronicPumpHistoryDecoder + // this.medtronicPumpStatus = medtronicPumpStatus + // databaseHelper = databaseHelperInterface + //this.pumpSync = pumpSync + } +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt index b1af19654a..0d4d896fab 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -54,10 +54,10 @@ class BasalProfile { private fun setRawData(data: ByteArray): Boolean { var dataInternal: ByteArray = data - if (dataInternal == null) { - aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") - return false - } + // if (dataInternal == null) { + // aapsLogger.error(LTag.PUMPCOMM, "setRawData: buffer is null!") + // return false + // } // if we have just one entry through all day it looks like just length 1 if (dataInternal.size == 1) { @@ -219,7 +219,7 @@ class BasalProfile { fun generateRawDataFromEntries() { val outData: MutableList = ArrayList() for (profileEntry in listEntries!!) { - val strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true) + //val strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true) outData.add(profileEntry.rate_raw[0]) outData.add(profileEntry.rate_raw[1]) outData.add(profileEntry.startTime_raw) @@ -238,17 +238,17 @@ class BasalProfile { aapsLogger.error(LTag.PUMPCOMM, " Error generating entries. Ex.: $ex", ex) aapsLogger.error(LTag.PUMPCOMM, " rawBasalValues: " + ByteUtil.shortHexString(rawData)) aapsLogger.error(LTag.PUMPCOMM, "=============================================================================") - //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); } + + val basalByHour = arrayOf() + if (entriesCopy == null || entriesCopy.size == 0) { - val basalByHour = arrayOfNulls(24) for (i in 0..23) { basalByHour[i] = 0.0 } - return basalByHour as Array + return basalByHour } - val basalByHour = arrayOfNulls(24) for (i in entriesCopy.indices) { val current = entriesCopy[i] var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1 @@ -264,13 +264,13 @@ class BasalProfile { // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour); for (j in currentTime until lastHour) { - if (pumpType == null) - basalByHour[j] = current.rate - else + // if (pumpType == null) + // basalByHour[j] = current.rate + // else basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate) } } - return basalByHour as Array + return basalByHour } override fun toString(): String { @@ -285,7 +285,7 @@ class BasalProfile { } val profilesByHour = getProfilesByHour(pumpType) for (aDouble in profilesByHour) { - if (aDouble!! > 35.0) return false + if (aDouble > 35.0) return false } return true } @@ -296,7 +296,6 @@ class BasalProfile { const val MAX_RAW_DATA_SIZE = 48 * 3 + 1 private const val DEBUG_BASALPROFILE = false - // this asUINT8 should be combined with Record.asUINT8, and placed in a new util class. private fun readUnsignedByte(b: Byte): Int { return if (b < 0) b + 256 else b.toInt() } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index 47d4f4f1ba..f419c7f56c 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -4,9 +4,7 @@ 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.* /** @@ -136,35 +134,14 @@ enum class MedtronicCommandType companion object { var mapByCode: MutableMap = HashMap() - private fun getDeviceTypesArray(vararg types: MedtronicDeviceType): HashMap { - val hashMap = HashMap() - 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() + // private fun getDeviceTypesArray(vararg types: MedtronicDeviceType): HashMap { + // val hashMap = HashMap() + // for (type in types) { + // hashMap[type] = null // } - // return array + // return hashMap // } - // 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] @@ -203,7 +180,6 @@ enum class MedtronicCommandType var maxRecords = 1 var resourceId: Int? = null private set - var command_type = 0 var allowedRetries = 2 var maxAllowedTime = 2000 var parameterType: MinimedCommandParameterType? = null @@ -217,7 +193,7 @@ enum class MedtronicCommandType } constructor(code: Int, description: String, devices: MedtronicDeviceType?, - parameterType: MinimedCommandParameterType?, cmd_params: ByteArray) : this(code, description, devices, parameterType, 0, 1, 0, 0, 11, 0) { + parameterType: MinimedCommandParameterType?, cmd_params: ByteArray) : this(code, description, devices, parameterType) { commandParameters = cmd_params commandParametersCount = cmd_params.size } @@ -233,10 +209,14 @@ enum class MedtronicCommandType } // NEW - constructor(code: Int, description: String, - devices: MedtronicDeviceType?, // - parameterType: MinimedCommandParameterType?, recordLength: Int = 64, max_recs: Int = 1, expectedLength: Int = 0, - resourceId: Int? = null) { + 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 @@ -252,25 +232,25 @@ enum class MedtronicCommandType } } - @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 - } - } + // @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 { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt index 6f4cf7704c..6f8be29bd6 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicDeviceType.kt @@ -16,28 +16,28 @@ enum class MedtronicDeviceType { Medtronic_511("511"), // Medtronic_512("512"), // Medtronic_712("712"), // - Medtronic_512_712(Medtronic_512, Medtronic_712), // + Medtronic_512_712(listOf(Medtronic_512, Medtronic_712)), // Medtronic_515("515"), // Medtronic_715("715"), // - Medtronic_515_715(Medtronic_515, Medtronic_715), // + Medtronic_515_715(listOf(Medtronic_515, Medtronic_715)), // Medtronic_522("522"), // Medtronic_722("722"), // - Medtronic_522_722(Medtronic_522, Medtronic_722), // + Medtronic_522_722(listOf(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), // + Medtronic_512andHigher(listOf(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(listOf(Medtronic_515, Medtronic_715, Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo)), // + Medtronic_522andHigher(listOf(Medtronic_522, Medtronic_722, Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo)), // + Medtronic_523andHigher(listOf(Medtronic_523_Revel, Medtronic_723_Revel, Medtronic_554_Veo, Medtronic_754_Veo)), // + Medtronic_554andHigher(listOf(Medtronic_554_Veo, Medtronic_754_Veo)), // // All; companion object { - var mapByDescription: MutableMap? = null + var mapByDescription: MutableMap = mutableMapOf() @JvmStatic fun isSameDevice(deviceWeCheck: MedtronicDeviceType, deviceSources: MedtronicDeviceType): Boolean { @@ -52,20 +52,17 @@ enum class MedtronicDeviceType { } fun getByDescription(desc: String): MedtronicDeviceType { - return if (mapByDescription==null) { - Unknown_Device - } else if (mapByDescription!!.containsKey(desc)) { - mapByDescription!![desc]!! + return if (mapByDescription.containsKey(desc)) { + mapByDescription[desc]!! } else { Unknown_Device } } init { - mapByDescription = HashMap() for (minimedDeviceType in values()) { - if (!minimedDeviceType.isFamily) { - mapByDescription!![minimedDeviceType.pumpModel!!] = minimedDeviceType + if (!minimedDeviceType.isFamily && minimedDeviceType.pumpModel!=null) { + mapByDescription[minimedDeviceType.pumpModel!!] = minimedDeviceType } } } @@ -78,16 +75,20 @@ enum class MedtronicDeviceType { // return isSameDevice(model, Medtronic_523andHigher); // } val isFamily: Boolean - var familyMembers: Array? = null + var familyMembers: List? = null private set + constructor() { + isFamily = false + } + constructor(pumpModel: String?) { isFamily = false this.pumpModel = pumpModel } - constructor(vararg familyMembers: MedtronicDeviceType) { - this.familyMembers = familyMembers as Array? + constructor(familyMembers: List) { + this.familyMembers = familyMembers isFamily = true } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt index 5e9958fee9..30bbf1681d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt @@ -6,6 +6,7 @@ import dagger.android.ContributesAndroidInjector import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicFragment 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.MedtronicUITask import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity import info.nightscout.androidaps.plugins.pump.medtronic.dialog.RileyLinkStatusDeviceMedtronic @@ -22,6 +23,8 @@ abstract class MedtronicModule { @ContributesAndroidInjector abstract fun medtronicCommunicationManagerProvider(): MedtronicCommunicationManager @ContributesAndroidInjector abstract fun medtronicUITaskProvider(): MedtronicUITask @ContributesAndroidInjector abstract fun contributesRileyLinkStatusDeviceMedtronic(): RileyLinkStatusDeviceMedtronic + @ContributesAndroidInjector abstract fun medtronicUICommProvider(): MedtronicUIComm + companion object { @Provides diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt index d8fb29c42a..1310b483b5 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -17,9 +17,7 @@ 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 @@ -34,13 +32,11 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi @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 + @Inject lateinit var medtronicUIComm: MedtronicUIComm - var medtronicUIComm: MedtronicUIComm? = null - private set private val mBinder: IBinder = LocalBinder() private var serialChanged = false private var frequencies: Array? = null @@ -82,7 +78,6 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi 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") } From 727862c7434ac65a1821003324c3027be910fe84 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sun, 25 Apr 2021 18:15:53 +0100 Subject: [PATCH 09/39] - DailyTotals changes - GraphData merge --- .../general/overview/graphData/GraphData.kt | 7 -- .../plugins/pump/common/PumpPluginAbstract.kt | 25 ++-- .../pump/medtronic/MedtronicPumpPlugin.kt | 7 +- .../comm/MedtronicCommunicationManager.kt | 2 +- .../comm/ui/MedtronicUIPostprocessor.kt | 12 -- .../medtronic/data/MedtronicHistoryData.kt | 111 ++++++++---------- .../pump/medtronic/data/dto/DailyTotalsDTO.kt | 28 ++--- 7 files changed, 80 insertions(+), 112 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt index 9f87d3d0b0..aa7016d10a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt @@ -582,17 +582,10 @@ class GraphData( val ratioScale = if (useForScale) Scale(100.0) else Scale() var time = fromTime while (time <= toTime) { -<<<<<<<<< Temporary merge branch 1 iobCobCalculator.ads.getAutosensDataAtTime(time)?.let { autosensData -> - ratioArray.add(ScaledDataPoint(time, autosensData.autosensResult.ratio - 1, ratioScale)) - maxRatioValueFound = max(maxRatioValueFound, autosensData.autosensResult.ratio - 1) - minRatioValueFound = min(minRatioValueFound, autosensData.autosensResult.ratio - 1) -========= - iobCobCalculatorPlugin.getAutosensData(time)?.let { autosensData -> ratioArray.add(ScaledDataPoint(time, 100.0 * (autosensData.autosensResult.ratio - 1 ), ratioScale)) maxRatioValueFound = max(maxRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1)) minRatioValueFound = min(minRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1)) ->>>>>>>>> Temporary merge branch 2 } time += 5 * 60 * 1000L } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index 6b7e738929..4ac44e2627 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -404,18 +404,19 @@ abstract class PumpPluginAbstract protected constructor( } // TODO - protected fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal?, b: Boolean) { -// long temporaryId = generateTempId(temporaryBasal.timestamp); -// boolean response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, -// generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), -// getPumpType(), serialNumber()); -// -// if (response && writeToInternalHistory) { -// driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); -// sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); -// } -// -// return response; + protected fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal, b: Boolean) { + val temporaryId = generateTempId(temporaryBasal.date) + val response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, + generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), + getPumpType(), serialNumber()); + + if (response && writeToInternalHistory) { + driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); + sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); + } + + return response; + } fun removeTemporaryId(temporaryId: Long) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index a32a8937e2..6df557318f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -756,7 +756,6 @@ class MedtronicPumpPlugin @Inject constructor( val response = responseTask.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - setTBR. Response: " + response) return if (response!!) { - // FIXME put this into UIPostProcessor medtronicPumpStatus.tempBasalStart = Date() medtronicPumpStatus.tempBasalAmount = absoluteRate medtronicPumpStatus.tempBasalLength = durationInMinutes @@ -1015,7 +1014,11 @@ class MedtronicPumpPlugin @Inject constructor( .source(Source.USER) // TODO fix - activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) + if (usePumpSync) { + addTemporaryBasalRateWithTempId(tempBasal, true) + } else { + activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) + } PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) } else { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index 531e6f3422..ee509ffd7d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -348,7 +348,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth override fun createPumpMessageContent(type: RLMessageType): ByteArray { return when (type) { - RLMessageType.PowerOn -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.RFPowerOn, byteArrayOf(2, 1, receiverDeviceAwakeForMinutes.toByte())) // maybe this is better FIXME + RLMessageType.PowerOn -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.RFPowerOn, byteArrayOf(2, 1, receiverDeviceAwakeForMinutes.toByte())) RLMessageType.ReadSimpleData -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.PumpModel, null) else -> ByteArray(0) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index 21945e1707..9c340798be 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -133,18 +133,6 @@ class MedtronicUIPostprocessor @Inject constructor( 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) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index dd81eafd00..6ffbb556ae 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -40,7 +40,6 @@ import javax.inject.Singleton // needs to include not returning any records if TZ goes into -x area. To fully support this AAPS would need to take note of // all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can // handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) -// All things marked with "TODO: Fix db code" needs to be updated in new 2.5 database code @Suppress("DEPRECATION") @Singleton class MedtronicHistoryData @Inject constructor( @@ -278,7 +277,6 @@ class MedtronicHistoryData @Inject constructor( */ fun processNewHistoryData() { - // TODO: Fix db code // Prime (for reseting autosense) val primeRecords: MutableList = getFilteredItems(PumpHistoryEntryType.Prime) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Prime [count=%d, items=%s]", primeRecords.size, gson.toJson(primeRecords))) @@ -416,24 +414,37 @@ class MedtronicHistoryData @Inject constructor( ${logPrefix}TDDs found: %d. %s """.trimIndent(), tdds.size, gson.toJson(tdds))) - val tddsDb = databaseHelper.getTDDsForLastXDays(3) + //val tddsDb = databaseHelper.getTDDsForLastXDays(3) for (tdd in tdds) { - val tddDbEntry = findTDD(tdd.atechDateTime!!, tddsDb) - val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO? + //val tddDbEntry = findTDD(tdd.atechDateTime!!, tddsDb) + val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO + + pumpSync.createOrUpdateTotalDailyDose( + DateTimeUtil.toMillisFromATD(tdd.atechDateTime!!), + totalsDTO.insulinBolus, + totalsDTO.insulinBasal!!, + totalsDTO.insulinTotal, + tdd.pumpId, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!! + ) + + // timestamp: Long, bolusAmount: Double, basalAmount: Double, totalAmount: Double, + // pumpId: Long?, pumpType: PumpType, pumpSerial: String //aapsLogger.debug(LTag.PUMP, "DailyTotals: {}", totalsDTO); - if (tddDbEntry == null) { - val tddNew = TDD() - totalsDTO!!.setTDD(tddNew) - aapsLogger.debug(LTag.PUMP, "TDD Add: $tddNew") - databaseHelper.createOrUpdateTDD(tddNew) - } else { - if (!totalsDTO!!.doesEqual(tddDbEntry)) { - totalsDTO.setTDD(tddDbEntry) - aapsLogger.debug(LTag.PUMP, "TDD Edit: $tddDbEntry") - databaseHelper.createOrUpdateTDD(tddDbEntry) - } - } + // if (tddDbEntry == null) { + // val tddNew = TDD() + // totalsDTO!!.setTDD(tddNew) + // aapsLogger.debug(LTag.PUMP, "TDD Add: $tddNew") + // databaseHelper.createOrUpdateTDD(tddNew) + // } else { + // if (!totalsDTO!!.doesEqual(tddDbEntry)) { + // totalsDTO.setTDD(tddDbEntry) + // aapsLogger.debug(LTag.PUMP, "TDD Edit: $tddDbEntry") + // databaseHelper.createOrUpdateTDD(tddDbEntry) + // } + // } } } @@ -534,6 +545,7 @@ class MedtronicHistoryData @Inject constructor( val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) if (tempBasal != null) { tempBasal.durationInMinutes = tempBasalProcessDTO.duration + // TODO pumpSync - createOrUpdate(tempBasal) databaseHelper.createOrUpdate(tempBasal) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Edit " + ProcessHistoryRecord.TBR.description + " - (entryFromDb=%s) ", tempBasal)) } else { @@ -568,6 +580,7 @@ class MedtronicHistoryData @Inject constructor( return tbr } } + // TODO pumpSync - findTempBasalByPumpId return databaseHelper.findTempBasalByPumpId(pumpId) } @@ -591,7 +604,6 @@ class MedtronicHistoryData @Inject constructor( } else if (entriesFromHistory.size == 1) { if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s. Type=SingleEntry", treatment, entriesFromHistory[0])) - // TODO: Fix db code // if difference is bigger than 2 minutes we discard entry val maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.atechDateTime!!, 2) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry maxMillisAllowed=%d, AtechDateTime=%d (add 2 minutes). ", maxMillisAllowed, treatment.atechDateTime)) @@ -636,10 +648,10 @@ class MedtronicHistoryData @Inject constructor( var outList: MutableList = mutableListOf() if (processHistoryRecord == ProcessHistoryRecord.Bolus) { - // TODO pumpSync + // TODO pumpSync - activeTreatments.getTreatmentsFromHistoryAfterTimestamp outList.addAll(activePlugin.activeTreatments.getTreatmentsFromHistoryAfterTimestamp(startTimestamp)) } else { - // TODO pumpSync + // TODO pumpSync - databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true) outList.addAll(databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true)) } @@ -689,7 +701,7 @@ class MedtronicHistoryData @Inject constructor( detailedBolusInfo.insulin = bolusDTO.deliveredAmount!! addCarbsFromEstimate(detailedBolusInfo, bolus) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): DetailedBolusInfo=$detailedBolusInfo") - // TODO pumpSync + // TODO pumpSync - activeTreatments.addToHistoryTreatment val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) bolus.linkedObject = detailedBolusInfo aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.timestamp, @@ -706,7 +718,7 @@ class MedtronicHistoryData @Inject constructor( extendedBolus.durationInMinutes = bolusDTO.duration!! bolus.linkedObject = extendedBolus if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): ExtendedBolus=$extendedBolus") - // TODO pumpSync + // TODO pumpSync - activeTreatments.addToHistoryExtendedBolus activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - Extended [date=%d,pumpId=%d, insulin=%.3f, duration=%d]", extendedBolus.date, extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes)) @@ -717,7 +729,7 @@ class MedtronicHistoryData @Inject constructor( treatment.source = Source.PUMP treatment.pumpId = bolus.pumpId!! treatment.insulin = bolusDTO!!.deliveredAmount!! - // TODO pumpSync + // TODO pumpSync - activeTreatments.createOrUpdateMedtronic(treatment) val updateReturn = activePlugin.activeTreatments.createOrUpdateMedtronic(treatment, false) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(tretament!=null): NewTreatment=%s, UpdateReturn=%s", treatment, updateReturn)) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "editBolus - [date=%d,pumpId=%d, insulin=%.3f, newRecord=%s]", treatment.date, @@ -730,6 +742,7 @@ class MedtronicHistoryData @Inject constructor( if (bolus!!.containsDecodedData("Estimate")) { val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO? if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard)) + // TODO pumpSync - Carbs detailedBolusInfo.carbs = bolusWizard!!.carbs.toDouble() } } @@ -749,6 +762,7 @@ class MedtronicHistoryData @Inject constructor( temporaryBasalDb.absoluteRate = tbr.insulinRate temporaryBasalDb.isAbsolute = !tbr.isPercent treatment.linkedObject = temporaryBasalDb + // TODO pumpSync - databaseHelper.createOrUpdate(tbr) databaseHelper.createOrUpdate(temporaryBasalDb) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "$operation - [date=%d,pumpId=%d, rate=%s %s, duration=%d]", // temporaryBasalDb.getDate(), // @@ -760,6 +774,7 @@ class MedtronicHistoryData @Inject constructor( private fun processSuspends(tempBasalProcessList: List) { for (tempBasalProcess in tempBasalProcessList) { + // TODO pumpSync - databaseHelper.findTempBasalByPumpId var tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne!!.pumpId!!) if (tempBasal == null) { // add @@ -772,6 +787,7 @@ class MedtronicHistoryData @Inject constructor( tempBasal.isAbsolute = true tempBasalProcess.itemOne!!.linkedObject = tempBasal tempBasalProcess.itemTwo!!.linkedObject = tempBasal + // TODO pumpSync -databaseHelper.createOrUpdate(tbr-suspebd( databaseHelper.createOrUpdate(tempBasal) } } @@ -928,52 +944,19 @@ class MedtronicHistoryData @Inject constructor( return if (tddsOut.size == 0) tdds else tddsOut } - private fun findTDD(atechDateTime: Long, tddsDb: List): TDD? { - for (tdd in tddsDb) { - if (DateTimeUtil.isSameDayATDAndMillis(atechDateTime, tdd.date)) { - return tdd - } - } - return null - } + // private fun findTDD(atechDateTime: Long, tddsDb: List): TDD? { + // for (tdd in tddsDb) { + // if (DateTimeUtil.isSameDayATDAndMillis(atechDateTime, tdd.date)) { + // return tdd + // } + // } + // return null + // } private fun tryToGetByLocalTime(atechDateTime: Long): Long { return DateTimeUtil.toMillisFromATD(atechDateTime) } -// private fun getOldestDateDifference(treatments: List): Int { -// var dt = Long.MAX_VALUE -// var currentTreatment: PumpHistoryEntry? = null -// if (isCollectionEmpty(treatments)) { -// return 8 // default return of 6 (5 for diif on history reading + 2 for max allowed difference) minutes -// } -// for (treatment in treatments) { -// if (treatment.atechDateTime!! < dt) { -// dt = treatment.atechDateTime!! -// currentTreatment = treatment -// } -// } -// var oldestEntryTime: LocalDateTime -// try { -// oldestEntryTime = DateTimeUtil.toLocalDateTime(dt) -// oldestEntryTime = oldestEntryTime.minusMinutes(3) -// -// // if (this.pumpTime.timeDifference < 0) { -// // oldestEntryTime = oldestEntryTime.plusSeconds(this.pumpTime.timeDifference); -// // } -// } catch (ex: Exception) { -// aapsLogger.error("Problem decoding date from last record: $currentTreatment") -// return 8 // default return of 6 minutes -// } -// val now = LocalDateTime() -// val minutes = Minutes.minutesBetween(oldestEntryTime, now) -// -// // 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, -// pumpTime!!.timeDifference, oldestEntryTime, now, minutes.minutes)) -// return minutes.minutes -// } - private fun getOldestTimestamp(treatments: List): Long { var dt = Long.MAX_VALUE var currentTreatment: PumpHistoryEntry? = null diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt index 37284cffe1..f6f5c99300 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt @@ -1,7 +1,7 @@ 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.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 @@ -34,13 +34,13 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { private val sensorDataCount: Int? = null @Expose - private var insulinTotal = 0.0 + var insulinTotal = 0.0 @Expose - private var insulinBasal: Double? = 0.0 + var insulinBasal: Double? = 0.0 @Expose - private var insulinBolus = 0.0 + var insulinBolus = 0.0 private var insulinCarbs: Double? = null private var bolusTotal: Double? = null private var bolusFood: Double? = null @@ -177,16 +177,16 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { .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 - } + // 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) { From 6504498cd246ba78622ec6e62f467d59938ce82b Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Fri, 30 Apr 2021 15:28:24 +0100 Subject: [PATCH 10/39] - added bolus handling (complete) - added PumpSyncStorage class for handling temporary data --- .../dependencyInjection/AppModule.kt | 11 + .../plugins/pump/common/sync/PumpDbEntry.kt | 32 +++ .../common/sync/PumpSyncEntriesCreator.java | 13 + .../pump/common/sync/PumpSyncStorage.kt | 154 ++++++++++ .../plugins/pump/common/PumpPluginAbstract.kt | 58 +--- .../plugins/pump/common/data/PumpDbEntry.kt | 9 - .../plugins/pump/common/data/PumpStatus.kt | 2 +- .../pump/medtronic/MedtronicPumpPlugin.kt | 74 ++--- .../comm/MedtronicCommunicationManager.kt | 11 +- .../comm/history/pump/PumpHistoryEntryType.kt | 2 +- .../comm/history/pump/PumpHistoryResult.kt | 2 + .../medtronic/data/MedtronicHistoryData.kt | 268 +++++++++++++++--- .../pump/medtronic/data/dto/BasalProfile.kt | 7 +- .../medtronic/defs/MedtronicCommandType.kt | 3 +- .../medtronic/driver/MedtronicPumpStatus.kt | 17 +- medtronic/src/main/res/values/strings.xml | 1 + 16 files changed, 515 insertions(+), 149 deletions(-) create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt index 740426792c..46af1a1228 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt @@ -21,6 +21,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.CommandQueue import info.nightscout.androidaps.utils.androidNotification.NotificationHolderImpl @@ -72,6 +73,16 @@ open class AppModule { rxBus: RxBusWrapper ): UploadQueueAdminInterface = UploadQueue(aapsLogger, databaseHelper, context, sp, rxBus) + @Provides + @Singleton + fun providesPumpSyncStorage( + pumpSync: PumpSync, + sp: SP, + aapsLogger: AAPSLogger + ): PumpSyncStorage { + return PumpSyncStorage(pumpSync, sp, aapsLogger) + } + @Module interface AppBindings { @Binds fun bindContext(mainApp: MainApp): Context diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt new file mode 100644 index 0000000000..08a782c918 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.common.sync + +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType + + +data class PumpDbEntry constructor(var temporaryId: Long, + var date: Long, + var pumpType: PumpType, + var serialNumber: String, + var bolusData: PumpDbEntryBolus? = null, + var tbrData: PumpDbEntryTBR? = null ) { + + constructor(temporaryId: Long, + date: Long, + pumpType: PumpType, + serialNumber: String, + detailedBolusInfo: DetailedBolusInfo) : this(temporaryId, date, pumpType, serialNumber) { + this.bolusData = PumpDbEntryBolus( + detailedBolusInfo.insulin, + detailedBolusInfo.carbs, + detailedBolusInfo.bolusType) + } +} + + +data class PumpDbEntryBolus(var insulin: Double, + var carbs: Double, + var bolusType: DetailedBolusInfo.BolusType) + + +data class PumpDbEntryTBR(var temporaryId: Long) \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java new file mode 100644 index 0000000000..1ba73df0bb --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.pump.common.sync; + +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; + +public interface PumpSyncEntriesCreator { + + long generateTempId(Object dataObject); + + PumpType model(); + + String serialNumber(); + +} diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt new file mode 100644 index 0000000000..3bb07b770c --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -0,0 +1,154 @@ +package info.nightscout.androidaps.plugins.pump.common.sync + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.reflect.TypeToken +import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.db.TemporaryBasal +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.utils.sharedPreferences.SP +import java.lang.reflect.Type +import javax.inject.Inject +import javax.inject.Singleton + +/** + * This class is intended for Pump Drivers that use temporaryId and need way to pair records + */ +@Singleton +class PumpSyncStorage @Inject constructor( + val pumpSync: PumpSync, + val sp: SP, + val aapsLogger: AAPSLogger +) { + + val pumpSyncStorageKey: String = "pump_sync_storage" + var pumpSyncStorage: MutableMap> = mutableMapOf() + var TBR: String = "TBR" + var BOLUS: String = "BOLUS" + var storageInitialized: Boolean = false + var gson: Gson = GsonBuilder().create() + + + init { + initStorage() + } + + + fun initStorage() { + if (storageInitialized) + return + + var loaded = false + + if (sp.contains(pumpSyncStorageKey)) { + val jsonData: String = sp.getString("pump_sync_storage", ""); + + if (!jsonData.isBlank()) { + + val pumpSyncStorageType: Type = object : TypeToken>>() {}.getType() + + val baseMap: MutableMap> = gson.fromJson(jsonData, pumpSyncStorageType) //as MutableMap> + + pumpSyncStorage = baseMap + + aapsLogger.debug(String.format("Loading Pump Sync Storage: boluses=%d, tbrs=%d.", pumpSyncStorage[BOLUS]!!.size, pumpSyncStorage[TBR]!!.size)) + loaded = true + } + } + + if (!loaded) { + pumpSyncStorage[BOLUS] = mutableListOf() + pumpSyncStorage[TBR] = mutableListOf() + } + } + + + fun saveStorage() { + if (!isStorageEmpty()) { + sp.putString(pumpSyncStorageKey, gson.toJson(pumpSyncStorage)) + aapsLogger.debug(String.format("Saving Pump Sync Storage: boluses=%d, tbrs=%d.", pumpSyncStorage[BOLUS]!!.size, pumpSyncStorage[TBR]!!.size)) + } + } + + + fun isStorageEmpty() : Boolean { + return pumpSyncStorage[BOLUS]!!.isEmpty() && pumpSyncStorage[TBR]!!.isEmpty() + } + + + fun getBoluses() : MutableList { + return pumpSyncStorage[BOLUS]!!; + } + + fun getTBRs() : MutableList { + return pumpSyncStorage[TBR]!!; + } + + + //abstract fun generateTempId(timeMillis: Long): Long + + fun addBolusWithTempId(detailedBolusInfo: DetailedBolusInfo, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator): Boolean { + val temporaryId = creator.generateTempId(detailedBolusInfo.timestamp) + val response = pumpSync.addBolusWithTempId( + detailedBolusInfo.timestamp, + detailedBolusInfo.insulin, + temporaryId, + detailedBolusInfo.bolusType, + creator.model(), + creator.serialNumber()) + if (response && writeToInternalHistory) { + var innerList: MutableList = pumpSyncStorage[BOLUS]!! + + innerList.add(PumpDbEntry(temporaryId, detailedBolusInfo.timestamp, creator.model(), creator.serialNumber(), detailedBolusInfo)) + pumpSyncStorage[BOLUS] = innerList + saveStorage() + } + return response + } + + // TODO + fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator) : Boolean { + // val temporaryId = generateTempId(temporaryBasal.date) + // val response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, + // generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), + // getPumpType(), serialNumber()); + // + // if (response && writeToInternalHistory) { + // driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); + // sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); + // } + // + // return response; + return false + } + + fun removeBolusWithTemporaryId(temporaryId: Long) { + val bolusList = removeTemporaryId(temporaryId, pumpSyncStorage[BOLUS]!!) + pumpSyncStorage[BOLUS] = bolusList + saveStorage() + } + + fun removeTemporaryBasalWithTemporaryId(temporaryId: Long) { + val tbrList = removeTemporaryId(temporaryId, pumpSyncStorage[TBR]!!) + pumpSyncStorage[TBR] = tbrList + saveStorage() + } + + private fun removeTemporaryId(temporaryId: Long, list: MutableList): MutableList { + var dbEntry: PumpDbEntry? = null + + for (pumpDbEntry in list) { + if (pumpDbEntry.temporaryId == temporaryId) { + dbEntry = pumpDbEntry + } + } + + if (dbEntry!=null) { + list.remove(dbEntry) + } + + return list + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index 4ac44e2627..d88a3d362d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -23,7 +23,6 @@ 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 @@ -56,14 +55,14 @@ abstract class PumpPluginAbstract protected constructor( var sp: SP, var context: Context, var fabricPrivacy: FabricPrivacy, - dateUtil: DateUtil, - aapsSchedulers: AapsSchedulers, - pumpSync: PumpSync + var dateUtil: DateUtil, + var aapsSchedulers: AapsSchedulers, + var pumpSync: PumpSync ) : PumpPluginBase(pluginDescription!!, injector!!, aapsLogger, resourceHelper, commandQueue), Pump, Constraints { private val disposable = CompositeDisposable() //protected override var injector: HasAndroidInjector? = null - protected var dateUtil: DateUtil + //protected var dateUtil: DateUtil // Pump capabilities final override var pumpDescription = PumpDescription() @@ -82,8 +81,8 @@ abstract class PumpPluginAbstract protected constructor( } - protected var aapsSchedulers: AapsSchedulers - protected var pumpSync: PumpSync + //protected var aapsSchedulers: AapsSchedulers + //protected var pumpSync: PumpSync protected var gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() abstract fun initPumpStatusData() @@ -344,12 +343,12 @@ abstract class PumpPluginAbstract protected constructor( // bolus needed, ask pump to deliver it deliverBolus(detailedBolusInfo) } else { - - // TODO fix // no bolus required, carb only treatment - activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) + // TODO carb only bolus - DONE + pumpSync.syncCarbsWithTimestamp(System.currentTimeMillis(), detailedBolusInfo.carbs, null, model(), serialNumber()); + // activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) val bolusingEvent = EventOverviewBolusProgress - bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) + bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) bolusingEvent.percent = 100 rxBus.send(bolusingEvent) aapsLogger.debug(LTag.PUMP, "deliverTreatment: Carb only treatment.") @@ -386,48 +385,13 @@ abstract class PumpPluginAbstract protected constructor( return PumpEnactResult(injector).success(false).enacted(false).comment(resourceId) } - // PumpSync - var driverHistory: MutableMap = HashMap() - abstract fun generateTempId(timeMillis: Long): Long - - protected fun addBolusWithTempId(detailedBolusInfo: DetailedBolusInfo, writeToInternalHistory: Boolean): Boolean { - val temporaryId = generateTempId(detailedBolusInfo.timestamp) - val response = pumpSync.addBolusWithTempId(detailedBolusInfo.timestamp, detailedBolusInfo.insulin, - temporaryId, detailedBolusInfo.bolusType, - pumpType, serialNumber()) - if (response && writeToInternalHistory) { - driverHistory[temporaryId] = PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo) - sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)) - } - return response - } - - // TODO - protected fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal, b: Boolean) { - val temporaryId = generateTempId(temporaryBasal.date) - val response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, - generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), - getPumpType(), serialNumber()); - - if (response && writeToInternalHistory) { - driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); - sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); - } - - return response; - - } - - fun removeTemporaryId(temporaryId: Long) { - driverHistory.remove(temporaryId) - } init { pumpDescription.setPumpDescription(pumpType) this.pumpType = pumpType this.dateUtil = dateUtil this.aapsSchedulers = aapsSchedulers - this.pumpSync = pumpSync + //this.pumpSync = pumpSync } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt deleted file mode 100644 index 6dfe38133a..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpDbEntry.kt +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.common.data - -import info.nightscout.androidaps.data.DetailedBolusInfo -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType - -data class PumpDbEntry(var temporaryId: Long, - var pumpType: PumpType, - var serialNumber: String, - var detailedBolusInfo: DetailedBolusInfo) \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt index 061465c354..42bc97f6ee 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt @@ -34,7 +34,7 @@ abstract class PumpStatus(var pumpType: PumpType) { var maxDailyTotalUnits: String? = null var units : String? = null // Constants.MGDL or Constants.MMOL var pumpStatusType = PumpStatusType.Running - var basalsByHour: Array? = null + var basalsByHour: DoubleArray? = null var tempBasalStart: Date? = null var tempBasalAmount: Double? = 0.0 var tempBasalLength: Int? = 0 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 6df557318f..f66c7b531f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -37,7 +37,9 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData @@ -88,7 +90,8 @@ class MedtronicPumpPlugin @Inject constructor( private val serviceTaskExecutor: ServiceTaskExecutor, dateUtil: DateUtil, aapsSchedulers: AapsSchedulers, - pumpSync: PumpSync + pumpSync: PumpSync, + val pumpSyncStorage: PumpSyncStorage ) : PumpPluginAbstract(PluginDescription() // .mainType(PluginType.PUMP) // .fragmentClass(MedtronicFragment::class.java.name) // @@ -99,7 +102,7 @@ class MedtronicPumpPlugin @Inject constructor( .description(R.string.description_pump_medtronic), // PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync -), Pump, RileyLinkPumpDevice { +), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator { private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null @@ -167,6 +170,8 @@ class MedtronicPumpPlugin @Inject constructor( sp.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis()) } migrateSettings() + + pumpSyncStorage.initStorage(); } override fun triggerPumpConfigurationChangedEvent() { @@ -482,7 +487,7 @@ class MedtronicPumpPlugin @Inject constructor( private fun isProfileSame(profile: Profile): Boolean { var invalid = false - val basalsByHour: Array? = medtronicPumpStatus.basalsByHour + val basalsByHour: DoubleArray? = medtronicPumpStatus.basalsByHour aapsLogger.debug(LTag.PUMP, "Current Basals (h): " + (basalsByHour?.let { getProfilesByHourToString(it) } ?: "null")) @@ -526,13 +531,12 @@ class MedtronicPumpPlugin @Inject constructor( rxBus.send(EventMedtronicPumpValuesChanged()) } - override fun generateTempId(timeMillis: Long): Long { - return 0 + override fun generateTempId(objectA: Any): Long { + val timestamp: Long = objectA as Long + return DateTimeUtil.toATechDate(timestamp) } - // @Override public String getSerial() { - // return null; - // } + private var bolusDeliveryType = BolusDeliveryType.Idle private enum class BolusDeliveryType { @@ -629,12 +633,15 @@ class MedtronicPumpPlugin @Inject constructor( detailedBolusInfo.timestamp = now detailedBolusInfo.deliverAtTheLatest = now // not sure about that one - // TODO fix - if (usePumpSync) { - addBolusWithTempId(detailedBolusInfo, true) - } else { - activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) - } + pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) + + + // // TODO fix + // if (usePumpSync) { + // pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) + // } else { + // activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) + // } // we subtract insulin, exact amount will be visible with next remainingInsulin update. medtronicPumpStatus.reservoirRemainingUnits = medtronicPumpStatus.reservoirRemainingUnits - detailedBolusInfo.insulin @@ -767,7 +774,7 @@ class MedtronicPumpPlugin @Inject constructor( // TODO fix if (usePumpSync) { - addTemporaryBasalRateWithTempId(tempStart, true) + pumpSyncStorage.addTemporaryBasalRateWithTempId(tempStart, true, this) } else { activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) } @@ -834,7 +841,7 @@ class MedtronicPumpPlugin @Inject constructor( val debugHistory = false var targetDate: LocalDateTime? = null - if (lastPumpHistoryEntry == null) { + if (lastPumpHistoryEntry == null) { // first read if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntry: null") val lastPumpHistoryEntryTime = lastPumpEntryTime var timeMinus36h = LocalDateTime() @@ -858,12 +865,9 @@ class MedtronicPumpPlugin @Inject constructor( targetDate = if (timeMinus36h.isAfter(lastHistoryRecordTime)) timeMinus36h else lastHistoryRecordTime if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): targetDate: " + targetDate) } - } else { + } else { // all other reads if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.gsonInstance.toJson(lastPumpHistoryEntry)) medtronicHistoryData.setIsInInit(false) - // medtronicHistoryData.setLastHistoryRecordTime(lastPumpHistoryEntry.atechDateTime); - - // targetDate = lastPumpHistoryEntry.atechDateTime; } //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); @@ -883,22 +887,22 @@ class MedtronicPumpPlugin @Inject constructor( medtronicHistoryData.filterNewEntries() // determine if first run, if yes detrmine how much of update do we need - // first run: - // get last hiostory entry, if not there download 1.5 days of data - // - there: check if last entry is older than 1.5 days - // - yes: download 1.5 days - // - no: download with last entry - // - not there: download 1.5 days + // - first run: + // - get last history entry + // - if not there download 1.5 days of data + // - there: check if last entry is older than 1.5 days + // - yes: download 1.5 days + // - no: download with last entry TODO 5min + // - not there: download 1.5 days // - // upload all new entries to NightScout (TBR, Bolus) - // determine pump status + // upload all new entries to NightScout (TBR, Bolus) + // determine pump status + // save last entry // - // save last entry - // - // not first run: - // update to last entry - // - save - // - determine pump status + // - not first run: + // - update to last entry TODO 5min + // - save + // - determine pump status } private val lastPumpEntryTime: Long @@ -1015,7 +1019,7 @@ class MedtronicPumpPlugin @Inject constructor( // TODO fix if (usePumpSync) { - addTemporaryBasalRateWithTempId(tempBasal, true) + pumpSyncStorage.addTemporaryBasalRateWithTempId(tempBasal, true, this) } else { activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index ee509ffd7d..acdbcc2e10 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -551,10 +551,13 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth errorResponse = check } - var basalProfile: BasalProfile? = null - checkResponseRawContent(data, commandType) { - basalProfile = medtronicConverter.decodeBasalProfile(medtronicPumpPlugin.pumpDescription.pumpType, data) - } + + aapsLogger.debug(LTag.PUMPCOMM,"End Response: {}", ByteUtil.getHex(data)) + + var basalProfile: BasalProfile? = medtronicConverter.decodeBasalProfile(medtronicPumpPlugin.pumpDescription.pumpType, data) + // checkResponseRawContent(data, commandType) { + // basalProfile = medtronicConverter.decodeBasalProfile(medtronicPumpPlugin.pumpDescription.pumpType, data) + // } if (basalProfile != null) { aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, basalProfile)) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt index 796ec828db..3151131838 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt @@ -47,7 +47,7 @@ enum class PumpHistoryEntryType // implements CodeEnum BolusWizardEnabled(0x2d, "Bolus Wizard Enabled", PumpHistoryEntryGroup.Configuration), // V3 ? /* TODO */ EventUnknown_MM512_0x2e(0x2e, "Unknown Event 0x2e", PumpHistoryEntryGroup.Unknown, 2, 5, 100), // BolusWizard512(0x2f, "Bolus Wizard (512)", PumpHistoryEntryGroup.Bolus, 2, 5, 12), // - UnabsorbedInsulin512(0x30, "Unabsorbed Insulin (512)", PumpHistoryEntryGroup.Statistic, 5, 0, 0), // FIXME + UnabsorbedInsulin512(0x30, "Unabsorbed Insulin (512)", PumpHistoryEntryGroup.Statistic, 5, 0, 0), ChangeBGReminderOffset(0x31, "Change BG Reminder Offset", PumpHistoryEntryGroup.Configuration), // ChangeAlarmClockTime(0x32, "Change Alarm Clock Time", PumpHistoryEntryGroup.Configuration), // TempBasalRate(0x33, "TBR Rate", PumpHistoryEntryGroup.Basal, 2, 5, 1), // diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt index 09d694f061..5fd484628d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt @@ -51,8 +51,10 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis } //aapsLogger.debug(LTag.PUMPCOMM,"PE. Entry {} added.", unprocessedEntry); + validEntries.add(unprocessedEntry) } + // TODO 5minutes back } SearchType.Date -> { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 6ffbb556ae..3264694d06 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -11,6 +11,8 @@ import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage 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.MedtronicPumpHistoryDecoder @@ -27,7 +29,6 @@ import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.sharedPreferences.SP import org.apache.commons.lang3.StringUtils import org.joda.time.LocalDateTime -import org.joda.time.Minutes import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -51,7 +52,8 @@ class MedtronicHistoryData @Inject constructor( val medtronicPumpHistoryDecoder: MedtronicPumpHistoryDecoder, val medtronicPumpStatus: MedtronicPumpStatus, val databaseHelper: DatabaseHelperInterface, - val pumpSync: PumpSync + val pumpSync: PumpSync, + val pumpSyncStorage: PumpSyncStorage ) { val allHistory: MutableList = mutableListOf() @@ -304,7 +306,7 @@ class MedtronicHistoryData @Inject constructor( // TDD val tdds: MutableList = getFilteredItems(setOf(PumpHistoryEntryType.EndResultTotals, tDDType)) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TDD [count=%d, items=%s]", tdds.size, gson.toJson(tdds))) - if (isCollectionNotEmpty(tdds)) { + if (tdds.isNotEmpty()) { try { processTDDs(tdds) } catch (ex: Exception) { @@ -317,7 +319,7 @@ class MedtronicHistoryData @Inject constructor( // Bolus val treatments = getFilteredItems(PumpHistoryEntryType.Bolus) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: Bolus [count=%d, items=%s]", treatments.size, gson.toJson(treatments))) - if (treatments.size > 0) { + if (treatments.isNotEmpty()) { try { processBolusEntries(treatments) } catch (ex: Exception) { @@ -329,9 +331,9 @@ class MedtronicHistoryData @Inject constructor( // TBR val tbrs: MutableList = getFilteredItems(PumpHistoryEntryType.TempBasalCombined) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TBRs Processed [count=%d, items=%s]", tbrs.size, gson.toJson(tbrs))) - if (tbrs.size > 0) { + if (tbrs.isNotEmpty()) { try { - processTBREntries(tbrs) + processTBREntries(tbrs) // TODO not implemented yet } catch (ex: Exception) { aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing TBR entries: " + ex.message, ex) throw ex @@ -348,9 +350,9 @@ class MedtronicHistoryData @Inject constructor( } aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: 'Delivery Suspend' Processed [count=%d, items=%s]", suspends.size, gson.toJson(suspends))) - if (isCollectionNotEmpty(suspends)) { + if (suspends.isNotEmpty()) { try { - processSuspends(suspends) + processSuspends(suspends) // TODO not tested yet } catch (ex: Exception) { aapsLogger.error(LTag.PUMP, "ProcessHistoryData: Error processing Suspends entries: " + ex.message, ex) throw ex @@ -410,13 +412,11 @@ class MedtronicHistoryData @Inject constructor( private fun processTDDs(tddsIn: MutableList) { val tdds = filterTDDs(tddsIn) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, """ - ${logPrefix}TDDs found: %d. - %s - """.trimIndent(), tdds.size, gson.toJson(tdds))) - //val tddsDb = databaseHelper.getTDDsForLastXDays(3) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, logPrefix + "TDDs found: %d.\n%s", + tdds.size, gson.toJson(tdds))) + for (tdd in tdds) { - //val tddDbEntry = findTDD(tdd.atechDateTime!!, tddsDb) val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO pumpSync.createOrUpdateTotalDailyDose( @@ -428,33 +428,148 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!! ) - - // timestamp: Long, bolusAmount: Double, basalAmount: Double, totalAmount: Double, - // pumpId: Long?, pumpType: PumpType, pumpSerial: String - - //aapsLogger.debug(LTag.PUMP, "DailyTotals: {}", totalsDTO); - // if (tddDbEntry == null) { - // val tddNew = TDD() - // totalsDTO!!.setTDD(tddNew) - // aapsLogger.debug(LTag.PUMP, "TDD Add: $tddNew") - // databaseHelper.createOrUpdateTDD(tddNew) - // } else { - // if (!totalsDTO!!.doesEqual(tddDbEntry)) { - // totalsDTO.setTDD(tddDbEntry) - // aapsLogger.debug(LTag.PUMP, "TDD Edit: $tddDbEntry") - // databaseHelper.createOrUpdateTDD(tddDbEntry) - // } - // } } } + + // private fun processTDDs_Old(tddsIn: MutableList) { + // val tdds = filterTDDs(tddsIn) + // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, """ + // ${logPrefix}TDDs found: %d. + // %s + // """.trimIndent(), tdds.size, gson.toJson(tdds))) + // //val tddsDb = databaseHelper.getTDDsForLastXDays(3) + // for (tdd in tdds) { + // //val tddDbEntry = findTDD(tdd.atechDateTime!!, tddsDb) + // val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO + // + // aapsLogger.debug(LTag.PUMP, "DailyTotals: {}", totalsDTO); + // if (tddDbEntry == null) { + // val tddNew = TDD() + // totalsDTO!!.setTDD(tddNew) + // aapsLogger.debug(LTag.PUMP, "TDD Add: $tddNew") + // databaseHelper.createOrUpdateTDD(tddNew) + // } else { + // if (!totalsDTO!!.doesEqual(tddDbEntry)) { + // totalsDTO.setTDD(tddDbEntry) + // aapsLogger.debug(LTag.PUMP, "TDD Edit: $tddDbEntry") + // databaseHelper.createOrUpdateTDD(tddDbEntry) + // } + // } + // } + // } + private enum class ProcessHistoryRecord(val description: String) { Bolus("Bolus"), TBR("TBR"), Suspend("Suspend"); } + private fun processBolusEntries(entryList: MutableList) { + + val boluses = pumpSyncStorage.getBoluses() + + for (bolus in entryList) { + + val bolusDTO = bolus.decodedData!!["Object"]!! as BolusDTO + var type: DetailedBolusInfo.BolusType = DetailedBolusInfo.BolusType.NORMAL + var multiwave = false + + if (bolusDTO.bolusType==PumpBolusType.Extended) { + addExtendedBolus(bolus, bolusDTO, multiwave) + continue; + } else if (bolusDTO.bolusType==PumpBolusType.Multiwave) { + multiwave = true + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Multiwave bolus from pump, extended bolus and normal bolus will be added.")) + addExtendedBolus(bolus, bolusDTO, multiwave); + } + + val deliveredAmount: Double = if (multiwave) bolusDTO.immediateAmount!! else bolusDTO.deliveredAmount!! + + var temporaryId: Long? = null + + if (!multiwave) { + val entryWithTempId = findDbEntry(bolus, boluses) + + if (entryWithTempId != null) { + temporaryId = entryWithTempId.temporaryId + pumpSyncStorage.removeBolusWithTemporaryId(temporaryId) + boluses.remove(entryWithTempId) + type = entryWithTempId.bolusData!!.bolusType + } + } + + if (temporaryId!=null) { + val result = pumpSync.syncBolusWithTempId( + tryToGetByLocalTime(bolus.atechDateTime!!), + deliveredAmount, + temporaryId, + type, + bolus.pumpId, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithTempId [date=%d, temporaryId=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", + bolus.atechDateTime!!, temporaryId, bolus.pumpId, deliveredAmount, + medtronicPumpStatus.serialNumber!!, result)) + } else { + val result = pumpSync.syncBolusWithPumpId( + tryToGetByLocalTime(bolus.atechDateTime!!), + deliveredAmount, + type, + bolus.pumpId!!, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithPumpId [date=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", + bolus.atechDateTime!!, bolus.pumpId, deliveredAmount, + medtronicPumpStatus.serialNumber!!, result)) + } + + addCarbs(bolus) + } + } + + + private fun addExtendedBolus(bolus: PumpHistoryEntry, bolusDTO: BolusDTO, isMultiwave: Boolean) { + + val durationMs : Long = bolusDTO.duration!! * 60L * 1000L + + val result = pumpSync.syncExtendedBolusWithPumpId( + tryToGetByLocalTime(bolus.atechDateTime!!), + bolusDTO.deliveredAmount!!, + durationMs, + false, + bolus.pumpId!!, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncExtendedBolusWithPumpId [date=%d, amount=%.2f, duration=%d, pumpId=%d, pumpSerial=%s, multiwave=%b] - Result: %b", + bolus.atechDateTime!!, bolusDTO.deliveredAmount!!, bolusDTO.duration, bolus.pumpId, + medtronicPumpStatus.serialNumber!!, isMultiwave, result)) + } + + + private fun addCarbs(bolus: PumpHistoryEntry) { + if (bolus.containsDecodedData("Estimate")) { + val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO + + val result = pumpSync.syncCarbsWithTimestamp( + tryToGetByLocalTime(bolus.atechDateTime!!), + bolusWizard.carbs.toDouble(), + bolus.pumpId!!, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncCarbsWithTimestamp [date=%d, pumpId=%d, carbs=%.2f, pumpSerial=%s] - Result: %b", + bolus.atechDateTime!!, bolusWizard.carbs.toDouble(), bolus.pumpId, + medtronicPumpStatus.serialNumber!!, result)) + } + } + + + private fun processBolusEntries_Old(entryList: MutableList) { val oldestTimestamp = getOldestTimestamp(entryList) val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.Bolus) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (before filter): %s, FromDb=%s", gson.toJson(entryList), @@ -475,7 +590,7 @@ class MedtronicHistoryData @Inject constructor( } } else { for (treatment in entryList) { - val treatmentDb = findDbEntry(treatment, entriesFromHistory) + val treatmentDb = findDbEntry_Old(treatment, entriesFromHistory) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add Bolus %s - (entryFromDb=%s) ", treatment, treatmentDb)) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: Add Bolus: FromDb=%s, Treatment=%s", treatmentDb, treatment)) addBolus(treatment, treatmentDb as Treatment?) @@ -558,7 +673,7 @@ class MedtronicHistoryData @Inject constructor( tbr2!!.durationMinutes = tempBasalProcessDTO.duration val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) if (tempBasal == null) { - val treatmentDb = findDbEntry(treatment, entriesFromHistory) + val treatmentDb = findDbEntry_Old(treatment, entriesFromHistory) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add " + ProcessHistoryRecord.TBR.description + " %s - (entryFromDb=%s) ", treatment, treatmentDb)) addTBR(treatment, treatmentDb as TemporaryBasal?) } else { @@ -593,7 +708,7 @@ class MedtronicHistoryData @Inject constructor( * @param entriesFromHistory entries from history * @return DbObject from AAPS (if found) */ - private fun findDbEntry(treatment: PumpHistoryEntry?, entriesFromHistory: List): DbObjectBase? { + private fun findDbEntry_Old(treatment: PumpHistoryEntry?, entriesFromHistory: List): DbObjectBase? { val proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) //proposedTime += (this.pumpTime.timeDifference * 1000); @@ -644,11 +759,69 @@ class MedtronicHistoryData @Inject constructor( return null } + /** + * Looks at all boluses that have temporaryId and find one that is correct for us (if such entry exists) + */ + private fun findDbEntry(treatment: PumpHistoryEntry?, temporaryEntries: MutableList): PumpDbEntry? { + + if (temporaryEntries.isEmpty()) { + return null + } + + var proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) + proposedTime += (this.pumpTime!!.timeDifference * 1000) + + val proposedTimeDiff : LongArray = longArrayOf(proposedTime-(2*60*1000), proposedTime+(2L*60L*1000L)) + val tempEntriesList: MutableList = mutableListOf() + + for (temporaryEntry in temporaryEntries) { + if (temporaryEntry.date > proposedTimeDiff[0] && temporaryEntry.date < proposedTimeDiff[1]) { + tempEntriesList.add(temporaryEntry) + } + } + + if (tempEntriesList.isEmpty()) { + return null + } else if (tempEntriesList.size==1) { + return tempEntriesList[0] + } + + var min = 0 + while (min < 2) { + var sec = 0 + while (sec <= 50) { + if (min == 1 && sec == 50) { + sec = 59 + } + val diff = sec * 1000 + val outList: MutableList = mutableListOf() + for (treatment1 in tempEntriesList) { + if (treatment1.date > proposedTime - diff && treatment1.date < proposedTime + diff) { + outList.add(treatment1) + } + } + if (outList.size == 1) { + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}. Type=EntrySelected, AtTimeMin={}, AtTimeSec={}", treatment, outList[0], min, sec)) + return outList[0] + } + if (min == 0 && sec == 10 && outList.size > 1) { + aapsLogger.error(String.format(Locale.ENGLISH, "Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", + min, sec, outList.size, gson.toJson(outList))) + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Error - Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", + min, sec, outList.size, gson.toJson(outList))) + } + sec += 10 + } + min += 1 + } + return null + } + + private fun getDatabaseEntriesByLastTimestamp(startTimestamp: Long, processHistoryRecord: ProcessHistoryRecord): MutableList { var outList: MutableList = mutableListOf() if (processHistoryRecord == ProcessHistoryRecord.Bolus) { - // TODO pumpSync - activeTreatments.getTreatmentsFromHistoryAfterTimestamp outList.addAll(activePlugin.activeTreatments.getTreatmentsFromHistoryAfterTimestamp(startTimestamp)) } else { // TODO pumpSync - databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true) @@ -701,7 +874,6 @@ class MedtronicHistoryData @Inject constructor( detailedBolusInfo.insulin = bolusDTO.deliveredAmount!! addCarbsFromEstimate(detailedBolusInfo, bolus) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): DetailedBolusInfo=$detailedBolusInfo") - // TODO pumpSync - activeTreatments.addToHistoryTreatment val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) bolus.linkedObject = detailedBolusInfo aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.timestamp, @@ -718,7 +890,6 @@ class MedtronicHistoryData @Inject constructor( extendedBolus.durationInMinutes = bolusDTO.duration!! bolus.linkedObject = extendedBolus if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): ExtendedBolus=$extendedBolus") - // TODO pumpSync - activeTreatments.addToHistoryExtendedBolus activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - Extended [date=%d,pumpId=%d, insulin=%.3f, duration=%d]", extendedBolus.date, extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes)) @@ -729,7 +900,6 @@ class MedtronicHistoryData @Inject constructor( treatment.source = Source.PUMP treatment.pumpId = bolus.pumpId!! treatment.insulin = bolusDTO!!.deliveredAmount!! - // TODO pumpSync - activeTreatments.createOrUpdateMedtronic(treatment) val updateReturn = activePlugin.activeTreatments.createOrUpdateMedtronic(treatment, false) if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(tretament!=null): NewTreatment=%s, UpdateReturn=%s", treatment, updateReturn)) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "editBolus - [date=%d,pumpId=%d, insulin=%.3f, newRecord=%s]", treatment.date, @@ -742,7 +912,6 @@ class MedtronicHistoryData @Inject constructor( if (bolus!!.containsDecodedData("Estimate")) { val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO? if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard)) - // TODO pumpSync - Carbs detailedBolusInfo.carbs = bolusWizard!!.carbs.toDouble() } } @@ -772,7 +941,28 @@ class MedtronicHistoryData @Inject constructor( temporaryBasalDb.durationInMinutes)) } + private fun processSuspends(tempBasalProcessList: List) { + for (tempBasalProcess in tempBasalProcessList) { + + val result = pumpSync.syncTemporaryBasalWithPumpId( + tryToGetByLocalTime(tempBasalProcess.itemOne!!.atechDateTime!!), + 0.0, + tempBasalProcess.duration * 60 * 1000L, + true, + PumpSync.TemporaryBasalType.PUMP_SUSPEND, + tempBasalProcess.itemOne!!.pumpId!!, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "processSuspends::syncTemporaryBasalWithPumpId [date=%d, rate=%.2f, duration=%d, pumpId=%d, pumpSerial=%s] - Result: %b", + tempBasalProcess.itemOne!!.atechDateTime!!, 0.0, tempBasalProcess.duration, tempBasalProcess.itemOne!!.pumpId!!, + medtronicPumpStatus.serialNumber!!, result)) + } + } + + + private fun processSuspends_Old(tempBasalProcessList: List) { for (tempBasalProcess in tempBasalProcessList) { // TODO pumpSync - databaseHelper.findTempBasalByPumpId var tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne!!.pumpId!!) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt index 0d4d896fab..2dc14b7c06 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -229,7 +229,7 @@ class BasalProfile { // return this.mRawData; } - fun getProfilesByHour(pumpType: PumpType): Array { + fun getProfilesByHour(pumpType: PumpType): DoubleArray { var entriesCopy: List? = null try { entriesCopy = getEntries() @@ -241,7 +241,7 @@ class BasalProfile { //FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null); } - val basalByHour = arrayOf() + val basalByHour = DoubleArray(24) if (entriesCopy == null || entriesCopy.size == 0) { for (i in 0..23) { @@ -249,6 +249,7 @@ class BasalProfile { } return basalByHour } + for (i in entriesCopy.indices) { val current = entriesCopy[i] var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1 @@ -301,7 +302,7 @@ class BasalProfile { } @JvmStatic - fun getProfilesByHourToString(data: Array): String { + fun getProfilesByHourToString(data: DoubleArray): String { val stringBuilder = StringBuilder() for (value in data) { stringBuilder.append(String.format("%.3f", value)) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index f419c7f56c..60dd954b20 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -58,7 +58,8 @@ enum class MedtronicCommandType 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 + GetRemainingInsulin(0x73, "Read Remaining Insulin", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, + 2, R.string.medtronic_cmd_desc_get_remaining_insulin), // 115 SetBolus(0x42, "Set Bolus", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, // 0, R.string.medtronic_cmd_desc_set_bolus), // 66 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index e0b65dcf54..c54bbcf90d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -41,11 +41,10 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour rileyLinkUtil.rileyLinkHistory.add(RLHistoryItem(pumpDeviceState, RileyLinkTargetDevice.MedtronicPump)) rxBus.send(EventRileyLinkDeviceStatusChange(pumpDeviceState)) } - var medtronicDeviceType: MedtronicDeviceType? = null - // fixme - var medtronicPumpMap: MutableMap = HashMap() - var medtronicDeviceTypeMap: MutableMap = HashMap() + var medtronicDeviceType: MedtronicDeviceType? = null + var medtronicPumpMap: MutableMap = mutableMapOf() + var medtronicDeviceTypeMap: MutableMap = mutableMapOf() var basalProfileStatus = BasalProfileStatus.NotInitialized var batteryType = BatteryType.None @@ -98,16 +97,16 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour } // Battery type - private var mapByDescription: MutableMap = HashMap() + private var batteryTypeByDescMap: MutableMap = HashMap() fun getBatteryTypeByDescription(batteryTypeStr: String?): BatteryType? { - if (mapByDescription.size == 0) { + if (batteryTypeByDescMap.size == 0) { for (value in BatteryType.values()) { - mapByDescription[resourceHelper.gs(value.description)] = value + batteryTypeByDescMap[resourceHelper.gs(value.description)] = value } } - return if (mapByDescription.containsKey(batteryTypeStr)) { - mapByDescription[batteryTypeStr] + return if (batteryTypeByDescMap.containsKey(batteryTypeStr)) { + batteryTypeByDescMap[batteryTypeStr] } else BatteryType.None } diff --git a/medtronic/src/main/res/values/strings.xml b/medtronic/src/main/res/values/strings.xml index 801413be38..f2831199cb 100644 --- a/medtronic/src/main/res/values/strings.xml +++ b/medtronic/src/main/res/values/strings.xml @@ -105,6 +105,7 @@ Get Temporary Basal Set Temporary Basal Set Bolus + Get Remaining Insulin Pump unreachable Warning From a3f0bf41cdfdadc0c9d22f6d61bb6b52146efe5b Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Fri, 30 Apr 2021 20:05:03 +0100 Subject: [PATCH 11/39] - removed unused (old) methods from MedtronicHistoryData - PumpSyncStorage added method addCarbs, that is now used in PUmpPluginAbstract and in MetronicPumpPlugin and MedtronicHistoryData - extended PumpDbEntry with other data classes: for Bolus, TBR (incomplete) and Carbs --- .../plugins/pump/common/sync/PumpDbEntry.kt | 11 + .../pump/common/sync/PumpSyncStorage.kt | 34 +- .../plugins/pump/common/PumpPluginAbstract.kt | 19 +- .../pump/medtronic/MedtronicPumpPlugin.kt | 5 +- .../medtronic/data/MedtronicHistoryData.kt | 310 ++++-------------- 5 files changed, 117 insertions(+), 262 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt index 08a782c918..e7ebc46ba4 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt @@ -28,5 +28,16 @@ data class PumpDbEntryBolus(var insulin: Double, var carbs: Double, var bolusType: DetailedBolusInfo.BolusType) +data class PumpDbEntryCarbs(var date: Long, + var carbs: Double, + var pumpType: PumpType, + var serialNumber: String, + var pumpId: Long? = null) { + constructor(detailedBolusInfo: DetailedBolusInfo, + creator: PumpSyncEntriesCreator) : this(detailedBolusInfo.timestamp, + detailedBolusInfo.carbs, + creator.model(), + creator.serialNumber()) +} data class PumpDbEntryTBR(var temporaryId: Long) \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt index 3bb07b770c..31e1a733f3 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -7,8 +7,10 @@ import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.utils.sharedPreferences.SP import java.lang.reflect.Type +import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -86,25 +88,45 @@ class PumpSyncStorage @Inject constructor( } - //abstract fun generateTempId(timeMillis: Long): Long - fun addBolusWithTempId(detailedBolusInfo: DetailedBolusInfo, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator): Boolean { val temporaryId = creator.generateTempId(detailedBolusInfo.timestamp) - val response = pumpSync.addBolusWithTempId( + val result = pumpSync.addBolusWithTempId( detailedBolusInfo.timestamp, detailedBolusInfo.insulin, temporaryId, detailedBolusInfo.bolusType, creator.model(), creator.serialNumber()) - if (response && writeToInternalHistory) { + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolusWithTempId [date=%d, temporaryId=%d, insulin=%.2f, type=%s, pumpSerial=%s] - Result: %b", + detailedBolusInfo.timestamp, temporaryId, detailedBolusInfo.insulin, detailedBolusInfo.bolusType, + creator.serialNumber(), result)) + + if (detailedBolusInfo.carbs>0.0) { + addCarbs(PumpDbEntryCarbs(detailedBolusInfo, creator)) + } + + if (result && writeToInternalHistory) { var innerList: MutableList = pumpSyncStorage[BOLUS]!! innerList.add(PumpDbEntry(temporaryId, detailedBolusInfo.timestamp, creator.model(), creator.serialNumber(), detailedBolusInfo)) pumpSyncStorage[BOLUS] = innerList saveStorage() } - return response + return result + } + + + fun addCarbs(carbsDto: PumpDbEntryCarbs) { + val result = pumpSync.syncCarbsWithTimestamp( + carbsDto.date, + carbsDto.carbs, + null, + carbsDto.pumpType, + carbsDto.serialNumber) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncCarbsWithTimestamp [date=%d, carbs=%.2f, pumpSerial=%s] - Result: %b", + carbsDto.date, carbsDto.carbs, carbsDto.serialNumber, result)) } // TODO @@ -123,6 +145,8 @@ class PumpSyncStorage @Inject constructor( return false } + + fun removeBolusWithTemporaryId(temporaryId: Long) { val bolusList = removeTemporaryId(temporaryId, pumpSyncStorage[BOLUS]!!) pumpSyncStorage[BOLUS] = bolusList diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index d88a3d362d..5a16531766 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -26,6 +26,9 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewB 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.plugins.pump.common.sync.PumpDbEntryCarbs +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal @@ -57,12 +60,11 @@ abstract class PumpPluginAbstract protected constructor( var fabricPrivacy: FabricPrivacy, var dateUtil: DateUtil, var aapsSchedulers: AapsSchedulers, - var pumpSync: PumpSync -) : PumpPluginBase(pluginDescription!!, injector!!, aapsLogger, resourceHelper, commandQueue), Pump, Constraints { + var pumpSync: PumpSync, + var pumpSyncStorage: PumpSyncStorage +) : PumpPluginBase(pluginDescription!!, injector!!, aapsLogger, resourceHelper, commandQueue), Pump, Constraints, PumpSyncEntriesCreator { private val disposable = CompositeDisposable() - //protected override var injector: HasAndroidInjector? = null - //protected var dateUtil: DateUtil // Pump capabilities final override var pumpDescription = PumpDescription() @@ -81,8 +83,6 @@ abstract class PumpPluginAbstract protected constructor( } - //protected var aapsSchedulers: AapsSchedulers - //protected var pumpSync: PumpSync protected var gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() abstract fun initPumpStatusData() @@ -343,10 +343,11 @@ abstract class PumpPluginAbstract protected constructor( // bolus needed, ask pump to deliver it deliverBolus(detailedBolusInfo) } else { + detailedBolusInfo.timestamp = System.currentTimeMillis() + // no bolus required, carb only treatment - // TODO carb only bolus - DONE - pumpSync.syncCarbsWithTimestamp(System.currentTimeMillis(), detailedBolusInfo.carbs, null, model(), serialNumber()); - // activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) + pumpSyncStorage.addCarbs(PumpDbEntryCarbs(detailedBolusInfo, this)) + val bolusingEvent = EventOverviewBolusProgress bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) bolusingEvent.percent = 100 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index f66c7b531f..4a91046067 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -91,7 +91,7 @@ class MedtronicPumpPlugin @Inject constructor( dateUtil: DateUtil, aapsSchedulers: AapsSchedulers, pumpSync: PumpSync, - val pumpSyncStorage: PumpSyncStorage + pumpSyncStorage: PumpSyncStorage ) : PumpPluginAbstract(PluginDescription() // .mainType(PluginType.PUMP) // .fragmentClass(MedtronicFragment::class.java.name) // @@ -101,7 +101,7 @@ class MedtronicPumpPlugin @Inject constructor( .preferencesId(R.xml.pref_medtronic) .description(R.string.description_pump_medtronic), // PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later - injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync + injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage ), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator { private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null @@ -635,7 +635,6 @@ class MedtronicPumpPlugin @Inject constructor( pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) - // // TODO fix // if (usePumpSync) { // pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 3264694d06..093947ec78 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -12,6 +12,7 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil @@ -215,9 +216,9 @@ class MedtronicHistoryData @Inject constructor( private fun isCollectionNotEmpty(col: List<*>?): Boolean { return col != null && !col.isEmpty() - }//////// + } + - // val isPumpSuspended: Boolean get() { val items = getDataForPumpSuspends() @@ -304,7 +305,7 @@ class MedtronicHistoryData @Inject constructor( } // TDD - val tdds: MutableList = getFilteredItems(setOf(PumpHistoryEntryType.EndResultTotals, tDDType)) + val tdds: MutableList = getFilteredItems(setOf(PumpHistoryEntryType.EndResultTotals, getTDDType())) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "ProcessHistoryData: TDD [count=%d, items=%s]", tdds.size, gson.toJson(tdds))) if (tdds.isNotEmpty()) { try { @@ -432,33 +433,6 @@ class MedtronicHistoryData @Inject constructor( } - // private fun processTDDs_Old(tddsIn: MutableList) { - // val tdds = filterTDDs(tddsIn) - // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, """ - // ${logPrefix}TDDs found: %d. - // %s - // """.trimIndent(), tdds.size, gson.toJson(tdds))) - // //val tddsDb = databaseHelper.getTDDsForLastXDays(3) - // for (tdd in tdds) { - // //val tddDbEntry = findTDD(tdd.atechDateTime!!, tddsDb) - // val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO - // - // aapsLogger.debug(LTag.PUMP, "DailyTotals: {}", totalsDTO); - // if (tddDbEntry == null) { - // val tddNew = TDD() - // totalsDTO!!.setTDD(tddNew) - // aapsLogger.debug(LTag.PUMP, "TDD Add: $tddNew") - // databaseHelper.createOrUpdateTDD(tddNew) - // } else { - // if (!totalsDTO!!.doesEqual(tddDbEntry)) { - // totalsDTO.setTDD(tddDbEntry) - // aapsLogger.debug(LTag.PUMP, "TDD Edit: $tddDbEntry") - // databaseHelper.createOrUpdateTDD(tddDbEntry) - // } - // } - // } - // } - private enum class ProcessHistoryRecord(val description: String) { Bolus("Bolus"), TBR("TBR"), @@ -533,7 +507,6 @@ class MedtronicHistoryData @Inject constructor( private fun addExtendedBolus(bolus: PumpHistoryEntry, bolusDTO: BolusDTO, isMultiwave: Boolean) { - val durationMs : Long = bolusDTO.duration!! * 60L * 1000L val result = pumpSync.syncExtendedBolusWithPumpId( @@ -555,61 +528,17 @@ class MedtronicHistoryData @Inject constructor( if (bolus.containsDecodedData("Estimate")) { val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO - val result = pumpSync.syncCarbsWithTimestamp( + pumpSyncStorage.addCarbs(PumpDbEntryCarbs( tryToGetByLocalTime(bolus.atechDateTime!!), bolusWizard.carbs.toDouble(), - bolus.pumpId!!, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) - - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncCarbsWithTimestamp [date=%d, pumpId=%d, carbs=%.2f, pumpSerial=%s] - Result: %b", - bolus.atechDateTime!!, bolusWizard.carbs.toDouble(), bolus.pumpId, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber!!, + bolus.pumpId!! + )) } } - private fun processBolusEntries_Old(entryList: MutableList) { - val oldestTimestamp = getOldestTimestamp(entryList) - val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.Bolus) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (before filter): %s, FromDb=%s", gson.toJson(entryList), - gsonCore.toJson(entriesFromHistory))) - filterOutAlreadyAddedEntries(entryList, entriesFromHistory) - if (entryList.isEmpty()) { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: EntryList was filtered out.") - return - } - filterOutNonInsulinEntries(entriesFromHistory) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: List (after filter): %s, FromDb=%s", gson.toJson(entryList), - gsonCore.toJson(entriesFromHistory))) - if (isCollectionEmpty(entriesFromHistory)) { - for (treatment in entryList) { - aapsLogger.debug(LTag.PUMP, "Add Bolus (no db entry): $treatment") - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: Add Bolus: FromDb=null, Treatment=$treatment") - addBolus(treatment, null) - } - } else { - for (treatment in entryList) { - val treatmentDb = findDbEntry_Old(treatment, entriesFromHistory) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add Bolus %s - (entryFromDb=%s) ", treatment, treatmentDb)) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: Add Bolus: FromDb=%s, Treatment=%s", treatmentDb, treatment)) - addBolus(treatment, treatmentDb as Treatment?) - } - } - } - - private fun filterOutNonInsulinEntries(entriesFromHistory: MutableList) { - // when we try to pair PumpHistory with AAPS treatments, we need to ignore all non-insulin entries - val removeList: MutableList = mutableListOf() - for (dbObjectBase in entriesFromHistory) { - val treatment = dbObjectBase as Treatment - if (Round.isSame(treatment.insulin, 0.0)) { - removeList.add(dbObjectBase) - } - } - entriesFromHistory.removeAll(removeList) - } - private fun processTBREntries(entryList: MutableList) { Collections.reverse(entryList) val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? @@ -831,82 +760,6 @@ class MedtronicHistoryData @Inject constructor( return outList } - private fun filterOutAlreadyAddedEntries(entryList: MutableList, treatmentsFromHistory: MutableList) { - if (isCollectionEmpty(treatmentsFromHistory)) - return - - val removeTreatmentsFromHistory: MutableList = ArrayList() - val removeTreatmentsFromPH: MutableList = ArrayList() - - for (treatment in treatmentsFromHistory) { - if (treatment.getPumpId() != 0L) { - var selectedBolus: PumpHistoryEntry? = null - for (bolus in entryList) { - if (bolus.pumpId == treatment.getPumpId()) { - selectedBolus = bolus - break - } - } - if (selectedBolus != null) { - entryList.remove(selectedBolus) - removeTreatmentsFromPH.add(selectedBolus) - removeTreatmentsFromHistory.add(treatment) - } - } - } - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: filterOutAlreadyAddedEntries: PumpHistory=%s, Treatments=%s", - gson.toJson(removeTreatmentsFromPH), - gsonCore.toJson(removeTreatmentsFromHistory))) - treatmentsFromHistory.removeAll(removeTreatmentsFromHistory) - } - - private fun addBolus(bolus: PumpHistoryEntry?, treatment: Treatment?) { - val bolusDTO = bolus!!.decodedData!!["Object"] as BolusDTO? - if (treatment == null) { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): Bolus=$bolusDTO") - when (bolusDTO!!.bolusType) { - PumpBolusType.Normal -> { - val detailedBolusInfo = DetailedBolusInfo() - detailedBolusInfo.bolusTimestamp = tryToGetByLocalTime(bolus.atechDateTime!!) - detailedBolusInfo.pumpType = medtronicPumpStatus.pumpType - detailedBolusInfo.pumpSerial = medtronicPumpStatus.serialNumber - detailedBolusInfo.bolusPumpId = bolus.pumpId - detailedBolusInfo.insulin = bolusDTO.deliveredAmount!! - addCarbsFromEstimate(detailedBolusInfo, bolus) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): DetailedBolusInfo=$detailedBolusInfo") - val newRecord = activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, false) - bolus.linkedObject = detailedBolusInfo - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - [date=%d,pumpId=%d, insulin=%.2f, newRecord=%b]", detailedBolusInfo.timestamp, - detailedBolusInfo.bolusPumpId, detailedBolusInfo.insulin, newRecord)) - } - - PumpBolusType.Audio, PumpBolusType.Extended -> { - val extendedBolus = ExtendedBolus(injector) - extendedBolus.date = tryToGetByLocalTime(bolus.atechDateTime!!) - extendedBolus.source = Source.PUMP - extendedBolus.insulin = bolusDTO.deliveredAmount!! - extendedBolus.pumpId = bolus.pumpId!! - extendedBolus.isValid = true - extendedBolus.durationInMinutes = bolusDTO.duration!! - bolus.linkedObject = extendedBolus - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: addBolus(tretament==null): ExtendedBolus=$extendedBolus") - activePlugin.activeTreatments.addToHistoryExtendedBolus(extendedBolus) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "addBolus - Extended [date=%d,pumpId=%d, insulin=%.3f, duration=%d]", extendedBolus.date, - extendedBolus.pumpId, extendedBolus.insulin, extendedBolus.durationInMinutes)) - } - } - } else { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(OldTreatment=%s): Bolus=%s", treatment, bolusDTO)) - treatment.source = Source.PUMP - treatment.pumpId = bolus.pumpId!! - treatment.insulin = bolusDTO!!.deliveredAmount!! - val updateReturn = activePlugin.activeTreatments.createOrUpdateMedtronic(treatment, false) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addBolus(tretament!=null): NewTreatment=%s, UpdateReturn=%s", treatment, updateReturn)) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "editBolus - [date=%d,pumpId=%d, insulin=%.3f, newRecord=%s]", treatment.date, - treatment.pumpId, treatment.insulin, updateReturn.toString())) - bolus.linkedObject = treatment - } - } private fun addCarbsFromEstimate(detailedBolusInfo: DetailedBolusInfo, bolus: PumpHistoryEntry?) { if (bolus!!.containsDecodedData("Estimate")) { @@ -962,53 +815,41 @@ class MedtronicHistoryData @Inject constructor( } - private fun processSuspends_Old(tempBasalProcessList: List) { - for (tempBasalProcess in tempBasalProcessList) { - // TODO pumpSync - databaseHelper.findTempBasalByPumpId - var tempBasal = databaseHelper.findTempBasalByPumpId(tempBasalProcess.itemOne!!.pumpId!!) - if (tempBasal == null) { - // add - tempBasal = TemporaryBasal(injector) - tempBasal.date = tryToGetByLocalTime(tempBasalProcess.itemOne!!.atechDateTime!!) - tempBasal.source = Source.PUMP - tempBasal.pumpId = tempBasalProcess.itemOne!!.pumpId!! - tempBasal.durationInMinutes = tempBasalProcess.duration - tempBasal.absoluteRate = 0.0 - tempBasal.isAbsolute = true - tempBasalProcess.itemOne!!.linkedObject = tempBasal - tempBasalProcess.itemTwo!!.linkedObject = tempBasal - // TODO pumpSync -databaseHelper.createOrUpdate(tbr-suspebd( - databaseHelper.createOrUpdate(tempBasal) - } - } - } - // suspend/resume // no_delivery/prime & rewind/prime private fun getSuspendRecords(): MutableList { - val outList: MutableList = ArrayList() + val outList: MutableList = mutableListOf() + + // suspend/resume + outList.addAll(getSuspendResumeRecordsList()) + // no_delivery/prime & rewind/prime + outList.addAll(getNoDeliveryRewindPrimeRecordsList()) + return outList + } - // suspend/resume - outList.addAll(getSuspendResumeRecordsList()) - // no_delivery/prime & rewind/prime - outList.addAll(getNoDeliveryRewindPrimeRecordsList()) - return outList - }// remove last and have paired items// remove last (unpaired R)// get one more from history (R S R) -> ([S] R S R)// remove last (unpaired R)// not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS])// full resume suspends (S R S R) - // - // private fun getSuspendResumeRecordsList(): List { - val filteredItems = getFilteredItems(newHistory, // - setOf(PumpHistoryEntryType.SuspendPump, PumpHistoryEntryType.ResumePump)) - val outList: MutableList = mutableListOf() - if (filteredItems.size > 0) { - val filtered2Items: MutableList = mutableListOf() - if (filteredItems.size % 2 == 0 && filteredItems[0].entryType === PumpHistoryEntryType.ResumePump) { - // full resume suspends (S R S R) - filtered2Items.addAll(filteredItems) - } else if (filteredItems.size % 2 == 0 && filteredItems[0].entryType === PumpHistoryEntryType.SuspendPump) { - // not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS]) - filteredItems.removeAt(0) + val filteredItems = getFilteredItems(newHistory, // + setOf(PumpHistoryEntryType.SuspendPump, PumpHistoryEntryType.ResumePump)) + val outList: MutableList = mutableListOf() + if (filteredItems.size > 0) { + val filtered2Items: MutableList = mutableListOf() + if (filteredItems.size % 2 == 0 && filteredItems[0].entryType === PumpHistoryEntryType.ResumePump) { + // full resume suspends (S R S R) + filtered2Items.addAll(filteredItems) + } else if (filteredItems.size % 2 == 0 && filteredItems[0].entryType === PumpHistoryEntryType.SuspendPump) { + // not full suspends, need to retrive one more record and discard first one (R S R S) -> ([S] R S R [xS]) + filteredItems.removeAt(0) + val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump) + if (oneMoreEntryFromHistory != null) { + filteredItems.add(oneMoreEntryFromHistory) + } else { + filteredItems.removeAt(filteredItems.size - 1) // remove last (unpaired R) + } + filtered2Items.addAll(filteredItems) + } else { + if (filteredItems[0].entryType === PumpHistoryEntryType.ResumePump) { + // get one more from history (R S R) -> ([S] R S R) val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump) if (oneMoreEntryFromHistory != null) { filteredItems.add(oneMoreEntryFromHistory) @@ -1017,39 +858,29 @@ class MedtronicHistoryData @Inject constructor( } filtered2Items.addAll(filteredItems) } else { - if (filteredItems[0].entryType === PumpHistoryEntryType.ResumePump) { - // get one more from history (R S R) -> ([S] R S R) - val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.SuspendPump) - if (oneMoreEntryFromHistory != null) { - filteredItems.add(oneMoreEntryFromHistory) - } else { - filteredItems.removeAt(filteredItems.size - 1) // remove last (unpaired R) - } - filtered2Items.addAll(filteredItems) - } else { - // remove last and have paired items - filteredItems.removeAt(0) - filtered2Items.addAll(filteredItems) - } - } - if (filtered2Items.size > 0) { - sort(filtered2Items) - Collections.reverse(filtered2Items) - var i = 0 - while (i < filtered2Items.size) { - val dto = TempBasalProcessDTO() - dto.itemOne = filtered2Items[i] - dto.itemTwo = filtered2Items[i + 1] - dto.processOperation = TempBasalProcessDTO.Operation.Add - outList.add(dto) - i += 2 - } + // remove last and have paired items + filteredItems.removeAt(0) + filtered2Items.addAll(filteredItems) } } - return outList - }////////// + if (filtered2Items.size > 0) { + sort(filtered2Items) + Collections.reverse(filtered2Items) + var i = 0 + while (i < filtered2Items.size) { + val dto = TempBasalProcessDTO() + dto.itemOne = filtered2Items[i] + dto.itemTwo = filtered2Items[i + 1] + dto.processOperation = TempBasalProcessDTO.Operation.Add + outList.add(dto) + i += 2 + } + } + } + return outList + } + - // private fun getNoDeliveryRewindPrimeRecordsList(): List { val primeItems: MutableList = getFilteredItems(newHistory, // setOf(PumpHistoryEntryType.Prime)) @@ -1134,15 +965,6 @@ class MedtronicHistoryData @Inject constructor( return if (tddsOut.size == 0) tdds else tddsOut } - // private fun findTDD(atechDateTime: Long, tddsDb: List): TDD? { - // for (tdd in tddsDb) { - // if (DateTimeUtil.isSameDayATDAndMillis(atechDateTime, tdd.date)) { - // return tdd - // } - // } - // return null - // } - private fun tryToGetByLocalTime(atechDateTime: Long): Long { return DateTimeUtil.toMillisFromATD(atechDateTime) } @@ -1169,20 +991,22 @@ class MedtronicHistoryData @Inject constructor( } } - private val tDDType: PumpHistoryEntryType - get() = if (medtronicUtil.medtronicPumpModel == null) { + private fun getTDDType(): PumpHistoryEntryType { + return if (medtronicUtil.medtronicPumpModel == null) { PumpHistoryEntryType.EndResultTotals } else when (medtronicUtil.medtronicPumpModel) { - MedtronicDeviceType.Medtronic_515, MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 - MedtronicDeviceType.Medtronic_522, MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 + MedtronicDeviceType.Medtronic_515, MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 + MedtronicDeviceType.Medtronic_522, MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 MedtronicDeviceType.Medtronic_523_Revel, MedtronicDeviceType.Medtronic_723_Revel, MedtronicDeviceType.Medtronic_554_Veo, - MedtronicDeviceType.Medtronic_754_Veo -> PumpHistoryEntryType.DailyTotals523 - else -> { + MedtronicDeviceType.Medtronic_754_Veo -> PumpHistoryEntryType.DailyTotals523 + + else -> { PumpHistoryEntryType.EndResultTotals } } + } fun hasBasalProfileChanged(): Boolean { val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) @@ -1217,10 +1041,6 @@ class MedtronicHistoryData @Inject constructor( PumpHistoryEntryType.ChangeTime)) } - // fun setLastHistoryRecordTime(lastHistoryRecordTime: Long?) { - // // this.previousLastHistoryRecordTime = this.lastHistoryRecordTime; - // } - fun setIsInInit(init: Boolean) { isInit = init } From 5bd41d9abdbc6486bc628c73c12f1c9ea46f3251 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 1 May 2021 11:24:50 +0100 Subject: [PATCH 12/39] - some cleanup - prelim work on TBR --- .../plugins/pump/common/sync/PumpDbEntry.kt | 23 +++++++++++- .../pump/common/sync/PumpSyncStorage.kt | 27 ++++++++------ .../pump/medtronic/MedtronicPumpPlugin.kt | 36 +++++++++---------- .../medtronic/data/MedtronicHistoryData.kt | 4 +++ 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt index e7ebc46ba4..9301d0c891 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.pump.common.sync import info.nightscout.androidaps.data.DetailedBolusInfo +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.pump.common.defs.PumpType @@ -21,6 +23,22 @@ data class PumpDbEntry constructor(var temporaryId: Long, detailedBolusInfo.carbs, detailedBolusInfo.bolusType) } + + constructor(temporaryId: Long, + date: Long, + pumpType: PumpType, + serialNumber: String, + rate: Double, + isAbsolute: Boolean, + durationInMinutes: Int, + tbrType: PumpSync.TemporaryBasalType) : this(temporaryId, date, pumpType, serialNumber) { + this.tbrData = PumpDbEntryTBR( + rate, + isAbsolute, + durationInMinutes, + tbrType) + } + } @@ -40,4 +58,7 @@ data class PumpDbEntryCarbs(var date: Long, creator.serialNumber()) } -data class PumpDbEntryTBR(var temporaryId: Long) \ No newline at end of file +data class PumpDbEntryTBR(var rate: Double, + var isAbsolute: Boolean, + var durationInMinutes: Int, + var tbrType: PumpSync.TemporaryBasalType) \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt index 31e1a733f3..ef13ad9f0d 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -130,19 +130,24 @@ class PumpSyncStorage @Inject constructor( } // TODO - fun addTemporaryBasalRateWithTempId(temporaryBasal: TemporaryBasal, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator) : Boolean { - // val temporaryId = generateTempId(temporaryBasal.date) - // val response = pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, + fun addTemporaryBasalRateWithTempId(temporaryBasal: PumpDbEntryTBR, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator) : Boolean { + val timenow : Long = System.currentTimeMillis() + + val temporaryId = creator.generateTempId(timenow) + val response = false + // pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, // generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), // getPumpType(), serialNumber()); - // - // if (response && writeToInternalHistory) { - // driverHistory.put(temporaryId, new PumpDbEntry(temporaryId, model(), serialNumber(), detailedBolusInfo)); - // sp.putString(MedtronicConst.Statistics.InternalTemporaryDatabase, gson.toJson(driverHistory)); - // } - // - // return response; - return false + + if (response && writeToInternalHistory) { + var innerList: MutableList = pumpSyncStorage[TBR]!! + + innerList.add(PumpDbEntry(temporaryId, timenow, creator.model(), creator.serialNumber(), null, temporaryBasal)) + pumpSyncStorage[BOLUS] = innerList + saveStorage() + } + + return response; } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 4a91046067..53d72dc076 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -37,6 +37,8 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage @@ -354,7 +356,7 @@ class MedtronicPumpPlugin @Inject constructor( } // execute - val refreshTypesNeededToReschedule: MutableSet = HashSet() + val refreshTypesNeededToReschedule: MutableSet = mutableSetOf() for ((key, value) in statusRefresh!!) { if (value!! > 0 && System.currentTimeMillis() > value) { when (key) { @@ -635,13 +637,6 @@ class MedtronicPumpPlugin @Inject constructor( pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) - // // TODO fix - // if (usePumpSync) { - // pumpSyncStorage.addBolusWithTempId(detailedBolusInfo, true, this) - // } else { - // activePlugin.activeTreatments.addToHistoryTreatment(detailedBolusInfo, true) - // } - // we subtract insulin, exact amount will be visible with next remainingInsulin update. medtronicPumpStatus.reservoirRemainingUnits = medtronicPumpStatus.reservoirRemainingUnits - detailedBolusInfo.insulin incrementStatistics(if (detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) MedtronicConst.Statistics.SMBBoluses else MedtronicConst.Statistics.StandardBoluses) @@ -771,12 +766,12 @@ class MedtronicPumpPlugin @Inject constructor( .absolute(absoluteRate) // .source(Source.USER) - // TODO fix - if (usePumpSync) { - pumpSyncStorage.addTemporaryBasalRateWithTempId(tempStart, true, this) - } else { - activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) - } + activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) + + // val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + // + // pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) + incrementStatistics(MedtronicConst.Statistics.TBRsSet) finishAction("TBR") PumpEnactResult(injector).success(true).enacted(true) // @@ -1016,12 +1011,13 @@ class MedtronicPumpPlugin @Inject constructor( .duration(0) // .source(Source.USER) - // TODO fix - if (usePumpSync) { - pumpSyncStorage.addTemporaryBasalRateWithTempId(tempBasal, true, this) - } else { - activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) - } + activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) + + // TODO need to find solution for this !? + // val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + // + // pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) + PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) } else { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 093947ec78..1e82d2b35e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -42,6 +42,10 @@ import javax.inject.Singleton // needs to include not returning any records if TZ goes into -x area. To fully support this AAPS would need to take note of // all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can // handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) +// +// TODO New Database changes, we need to read 35 minutes from history on each read and then compare if items have the same +// amounts, if not send them back to database changes. ALSO we need to remove and invalidate TBRs that are cancels from +// PumpSyncStorage @Suppress("DEPRECATION") @Singleton class MedtronicHistoryData @Inject constructor( From 49f345d42514c35d86c1852710181c85229d9579 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sun, 2 May 2021 13:45:56 +0100 Subject: [PATCH 13/39] - startted adding 35 minut - before reading functionality - some refactoring --- .../pump/medtronic/MedtronicPumpPlugin.kt | 12 ++-- .../comm/history/MedtronicHistoryDecoder.kt | 21 +++--- .../comm/history/pump/PumpHistoryEntry.kt | 15 ++++- .../comm/ui/MedtronicUIPostprocessor.kt | 1 + .../pump/medtronic/comm/ui/MedtronicUITask.kt | 9 +-- .../medtronic/data/MedtronicHistoryData.kt | 65 +++++++++++++------ .../dialog/RileyLinkStatusDeviceMedtronic.kt | 9 +-- 7 files changed, 81 insertions(+), 51 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 8a1c1ff14e..511f6ef70e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -466,7 +466,7 @@ class MedtronicPumpPlugin @Inject constructor( } private val basalProfiles: Unit - private get() { + get() { val medtronicUITask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) if (medtronicUITask.responseType === MedtronicUIResponseType.Error) { rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) @@ -816,7 +816,7 @@ class MedtronicPumpPlugin @Inject constructor( medtronicHistoryData.processLastBasalProfileChange(pumpDescription.pumpType, medtronicPumpStatus) } val previousState = pumpState - if (medtronicHistoryData.isPumpSuspended) { + if (medtronicHistoryData.isPumpSuspended()) { pumpState = PumpDriverState.Suspended aapsLogger.debug(LTag.PUMP, logPrefix + "isPumpSuspended: true") } else { @@ -852,20 +852,19 @@ class MedtronicPumpPlugin @Inject constructor( lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12) // we get last 12 hours of history to // determine pump state // (we don't process that data), we process only - if (timeMinus36h.isAfter(lastHistoryRecordTime)) { - targetDate = timeMinus36h - } targetDate = if (timeMinus36h.isAfter(lastHistoryRecordTime)) timeMinus36h else lastHistoryRecordTime if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): targetDate: " + targetDate) } } else { // all other reads if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.gsonInstance.toJson(lastPumpHistoryEntry)) medtronicHistoryData.setIsInInit(false) + // we need to read 35 minutes in the past so that we can repair any TBR or Bolus values if neeeded + targetDate = LocalDateTime(DateTimeUtil.getMillisFromATDWithAddedMinutes(lastPumpHistoryEntry!!.atechDateTime!!, -35)) } //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData, - arrayListOf(lastPumpHistoryEntry, targetDate) as ArrayList?) + arrayListOf(/*lastPumpHistoryEntry*/ null, targetDate) as ArrayList?) if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task") val historyResult = responseTask2.result as PumpHistoryResult? if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History Result: " + historyResult.toString()) @@ -949,7 +948,6 @@ class MedtronicPumpPlugin @Inject constructor( HashMap(statusRefreshMap) } - else -> null } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 91d64f3efc..65b03e70cb 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -35,7 +35,7 @@ abstract class MedtronicHistoryDecoder : MedtronicHi // TODO_ extend this to also use bigger pages (for now we support only 1024 pages) @Throws(RuntimeException::class) - private fun checkPage(page: RawHistoryPage, partial: Boolean): MutableList { + private fun checkPage(page: RawHistoryPage): MutableList { //val byteList: MutableList = mutableListOf() if (medtronicUtil.medtronicPumpModel == null) { @@ -51,8 +51,14 @@ abstract class MedtronicHistoryDecoder : MedtronicHi } } - fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): List { - return processPageAndCreateRecords(rawHistoryPage, false) + fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): MutableList { + val dataClear = checkPage(rawHistoryPage) + val records: MutableList = createRecords(dataClear) + for (record in records) { + decodeRecord(record) + } + runPostDecodeTasks() + return records } protected fun prepareStatistics() { @@ -117,13 +123,4 @@ abstract class MedtronicHistoryDecoder : MedtronicHi return StringUtil.getFormatedValueUS(value, decimals) } - private fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage, partial: Boolean): MutableList { - val dataClear = checkPage(rawHistoryPage, partial) - val records: MutableList = createRecords(dataClear) - for (record in records) { - decodeRecord(record) - } - runPostDecodeTasks() - return records - } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index a5a7cbfaa8..b8f37cf379 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -72,9 +72,10 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is PumpHistoryEntry) return false - val that = other - return entryType == that.entryType && // - atechDateTime === that.atechDateTime // && // + val that = other as PumpHistoryEntry + return this.pumpId === that.pumpId + // return entryType == that.entryType && // + // atechDateTime === that.atechDateTime // && // // Objects.equals(this.decodedData, that.decodedData); } @@ -111,4 +112,12 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { set(pumpId) { super.pumpId = pumpId } + + fun hasBolusOrTBRDataChanged(entry: PumpHistoryEntry) : Boolean { + if (entryType!=null && (entryType!! == PumpHistoryEntryType.Bolus || entryType!! == PumpHistoryEntryType.TempBasalCombined)) { + return false // TODO needs to be implemented + } + + return false + } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index 9c340798be..f4398bee62 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -55,6 +55,7 @@ class MedtronicUIPostprocessor @Inject constructor( //aapsLogger.debug("D: basal profile on read: " + basalProfile); try { + // TODO need to refactor val profilesByHour = basalProfile!!.getProfilesByHour(medtronicPumpPlugin.pumpDescription.pumpType) if (profilesByHour != null) { medtronicPumpStatus.basalsByHour = profilesByHour diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt index addcd5d2c3..be334adf76 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt @@ -101,7 +101,8 @@ class MedtronicUITask { result = communicationManager.cancelTBR() } - MedtronicCommandType.SetBasalProfileSTD, MedtronicCommandType.SetBasalProfileA -> { + MedtronicCommandType.SetBasalProfileSTD, + MedtronicCommandType.SetBasalProfileA -> { val profile = parameters!![0] as BasalProfile result = communicationManager.setBasalProfile(profile) } @@ -128,7 +129,7 @@ class MedtronicUITask { } private fun getTbrSettings(): TempBasalPair? { - return TempBasalPair(getDoubleFromParameters(0), // + return TempBasalPair(getDoubleFromParameters(0)!!, // false, // getIntegerFromParameters(1)) } @@ -137,8 +138,8 @@ class MedtronicUITask { return parameters!![index] as Float } - fun getDoubleFromParameters(index: Int): Double { - return parameters!![index] as Double + fun getDoubleFromParameters(index: Int): Double? { + return parameters!![index] as Double? } private fun getIntegerFromParameters(index: Int): Int { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 1e82d2b35e..e731eb1ce9 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -43,9 +43,10 @@ import javax.inject.Singleton // all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can // handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) // -// TODO New Database changes, we need to read 35 minutes from history on each read and then compare if items have the same -// amounts, if not send them back to database changes. ALSO we need to remove and invalidate TBRs that are cancels from -// PumpSyncStorage +// TODO New Database changes: +// + we need to read 35 minutes from history on each read +// - compare all read items if they have the same amounts, if not send them back to database changes. +// - we need to remove and invalidate TBRs that are cancels from PumpSyncStorage @Suppress("DEPRECATION") @Singleton class MedtronicHistoryData @Inject constructor( @@ -82,12 +83,35 @@ class MedtronicHistoryData @Inject constructor( for (validEntry in validEntries) { if (!allHistory.contains(validEntry)) { newEntries.add(validEntry) + } else { + val entryByPumpId = getEntryByPumpId(validEntry.pumpId!!) + + // TODO not implemented + if (entryByPumpId!=null && entryByPumpId.hasBolusOrTBRDataChanged(validEntry)) { + newEntries.add(validEntry) + allHistory.remove(entryByPumpId) + } } } newHistory = newEntries showLogs("List of history (before filtering): [" + newHistory.size + "]", gson.toJson(newHistory)) } + private fun getEntryByPumpId(pumpId: Long): PumpHistoryEntry? { + val findFirst = this.allHistory.stream() + .filter { f -> f.pumpId!! == pumpId } + .findFirst() + + return if (findFirst.isPresent()) findFirst.get() else null + // + // for (pumpHistoryEntry in allHistory) { + // if (pumpHistoryEntry.pumpId == pumpId) { + // return pumpHistoryEntry + // } + // } + // return null + } + private fun showLogs(header: String?, data: String) { if (header != null) { aapsLogger.debug(LTag.PUMP, header) @@ -223,22 +247,21 @@ class MedtronicHistoryData @Inject constructor( } - val isPumpSuspended: Boolean - get() { - val items = getDataForPumpSuspends() - showLogs("isPumpSuspended: ", gson.toJson(items)) - return if (isCollectionNotEmpty(items)) { - val pumpHistoryEntryType = items[0].entryType - val isSuspended = !(pumpHistoryEntryType === PumpHistoryEntryType.TempBasalCombined || // - pumpHistoryEntryType === PumpHistoryEntryType.BasalProfileStart || // - pumpHistoryEntryType === PumpHistoryEntryType.Bolus || // - pumpHistoryEntryType === PumpHistoryEntryType.ResumePump || // - pumpHistoryEntryType === PumpHistoryEntryType.BatteryChange || // - pumpHistoryEntryType === PumpHistoryEntryType.Prime) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "isPumpSuspended. Last entry type=%s, isSuspended=%b", pumpHistoryEntryType, isSuspended)) - isSuspended - } else false - } + fun isPumpSuspended(): Boolean { + val items = getDataForPumpSuspends() + showLogs("isPumpSuspended: ", gson.toJson(items)) + return if (isCollectionNotEmpty(items)) { + val pumpHistoryEntryType = items[0].entryType + val isSuspended = !(pumpHistoryEntryType === PumpHistoryEntryType.TempBasalCombined || // + pumpHistoryEntryType === PumpHistoryEntryType.BasalProfileStart || // + pumpHistoryEntryType === PumpHistoryEntryType.Bolus || // + pumpHistoryEntryType === PumpHistoryEntryType.ResumePump || // + pumpHistoryEntryType === PumpHistoryEntryType.BatteryChange || // + pumpHistoryEntryType === PumpHistoryEntryType.Prime) + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "isPumpSuspended. Last entry type=%s, isSuspended=%b", pumpHistoryEntryType, isSuspended)) + isSuspended + } else false + } private fun getDataForPumpSuspends(): MutableList { val newAndAll: MutableList = mutableListOf() @@ -246,7 +269,7 @@ class MedtronicHistoryData @Inject constructor( newAndAll.addAll(allHistory) } if (isCollectionNotEmpty(newHistory)) { - for (pumpHistoryEntry in newHistory!!) { + for (pumpHistoryEntry in newHistory) { if (!newAndAll.contains(pumpHistoryEntry)) { newAndAll.add(pumpHistoryEntry) } @@ -563,7 +586,7 @@ class MedtronicHistoryData @Inject constructor( var processDTO: TempBasalProcessDTO? = null val processList: MutableList = ArrayList() for (treatment in entryList) { - val tbr2 = treatment!!.getDecodedDataEntry("Object") as TempBasalPair? + val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair? if (tbr2!!.isCancelTBR) { if (processDTO != null) { processDTO.itemTwo = treatment diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt index 3fe1eb4d8e..fade5fbed0 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt @@ -112,16 +112,17 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { var view = viewIn val viewHolder: ViewHolder // General ListView optimization code. - if (view == null) { +// if (view == null) { view = mInflator.inflate(R.layout.rileylink_status_device_item, null) viewHolder = ViewHolder() viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) view.tag = viewHolder - } else { - viewHolder = view.tag as ViewHolder - } + // } + // else { + // viewHolder = view.tag as ViewHolder + // } val item = historyItemList[i] viewHolder.itemTime!!.text = StringUtil.toDateTimeString(dateUtil, item.dateTime) viewHolder.itemSource!!.text = "Riley Link" // for now From 12a3609565ea52c9ca2edebdd5894756a560f17e Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 5 May 2021 16:57:48 +0100 Subject: [PATCH 14/39] - started working TBR - added Dropbox stuff (not part of project) --- .../maintenance/dropbox/UploadFileTask.java | 72 +++++++ .../maintenance/dropbox/UriHelpers.java | 119 ++++++++++++ .../pump/common/sync/PumpSyncStorage.kt | 16 +- .../pump/medtronic/MedtronicPumpPlugin.kt | 38 ++-- .../medtronic/data/MedtronicHistoryData.kt | 181 ++++++++++++++---- .../medtronic/data/dto/TempBasalProcessDTO.kt | 14 +- 6 files changed, 378 insertions(+), 62 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java new file mode 100644 index 0000000000..0bedd145a8 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java @@ -0,0 +1,72 @@ +package info.nightscout.androidaps.plugins.general.maintenance.dropbox; + +import android.content.Context; +import android.net.Uri; +import android.os.AsyncTask; + +import com.dropbox.core.DbxException; +import com.dropbox.core.v2.DbxClientV2; +import com.dropbox.core.v2.files.FileMetadata; +import com.dropbox.core.v2.files.WriteMode; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class UploadFileTask extends AsyncTask { + + private final Context mContext; + private final DbxClientV2 mDbxClient; + private final Callback mCallback; + private Exception mException; + + public interface Callback { + void onUploadComplete(FileMetadata result); + void onError(Exception e); + } + + UploadFileTask(Context context, DbxClientV2 dbxClient, Callback callback) { + mContext = context; + mDbxClient = dbxClient; + mCallback = callback; + } + + @Override + protected void onPostExecute(FileMetadata result) { + super.onPostExecute(result); + if (mException != null) { + mCallback.onError(mException); + } else if (result == null) { + mCallback.onError(null); + } else { + mCallback.onUploadComplete(result); + } + } + + @Override + protected FileMetadata doInBackground(String... params) { + String localUri = params[0]; + File localFile = UriHelpers.getFileForUri(mContext, Uri.parse(localUri)); + + if (localFile != null) { + String remoteFolderPath = params[1]; + + // Note - this is not ensuring the name is a valid dropbox file name + String remoteFileName = localFile.getName(); + + try (InputStream inputStream = new FileInputStream(localFile)) { + return mDbxClient.files().uploadBuilder(remoteFolderPath + "/" + remoteFileName) + .withMode(WriteMode.OVERWRITE) + .uploadAndFinish(inputStream); + } catch (DbxException | IOException e) { + mException = e; + } + } + + return null; + } + + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java new file mode 100644 index 0000000000..67a1d9c0dd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java @@ -0,0 +1,119 @@ +package info.nightscout.androidaps.plugins.general.maintenance.dropbox; + +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; + +import java.io.File; + +public class UriHelpers { + + private UriHelpers() {} + + /** + * Get the file path for a uri. This is a convoluted way to get the path for an Uri created using the + * StorageAccessFramework. This in no way is the official way to do this but there does not seem to be a better + * way to do this at this point. It is taken from https://github.com/iPaulPro/aFileChooser. + * + * @param context The context of the application + * @param uri The uri of the saved file + * @return The file with path pointing to the saved file. It can return null if we can't resolve the uri properly. + */ + public static File getFileForUri(final Context context, final Uri uri) { + String path = null; + // DocumentProvider + if (DocumentsContract.isDocumentUri(context, uri)) { + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + path = Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } else if (isDownloadsDocument(uri)) { + // DownloadsProvider + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris + .withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + + path = getDataColumn(context, contentUri, null, null); + } else if (isMediaDocument(uri)) { + // MediaProvider + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { + split[1] + }; + + path = getDataColumn(context, contentUri, selection, selectionArgs); + } + } else if ("content".equalsIgnoreCase(uri.getScheme())) { + // MediaStore (and general) + path = getDataColumn(context, uri, null, null); + } else if ("file".equalsIgnoreCase(uri.getScheme())) { + // File + path = uri.getPath(); + } + + if (path != null) { + return new File(path); + } + return null; + } + + private static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, + null); + if (cursor != null && cursor.moveToFirst()) { + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + return null; + } + + + private static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + private static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + private static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + +} diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt index ef13ad9f0d..83d4a85745 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -8,6 +8,7 @@ import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.sharedPreferences.SP import java.lang.reflect.Type import java.util.* @@ -132,12 +133,17 @@ class PumpSyncStorage @Inject constructor( // TODO fun addTemporaryBasalRateWithTempId(temporaryBasal: PumpDbEntryTBR, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator) : Boolean { val timenow : Long = System.currentTimeMillis() - val temporaryId = creator.generateTempId(timenow) - val response = false - // pumpSync.addBolusWithTempId(temporaryBasal.timestamp, detailedBolusInfo.insulin, - // generateTempId(detailedBolusInfo.timestamp), detailedBolusInfo.getBolusType(), - // getPumpType(), serialNumber()); + + val response = pumpSync.addTemporaryBasalWithTempId( + timenow, + temporaryBasal.rate, + (temporaryBasal.durationInMinutes * 60L * 1000L), + temporaryBasal.isAbsolute, + temporaryId, + temporaryBasal.tbrType, + creator.model(), + creator.serialNumber()) if (response && writeToInternalHistory) { var innerList: MutableList = pumpSyncStorage[TBR]!! diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 511f6ef70e..2fe0482bd1 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -759,17 +759,17 @@ class MedtronicPumpPlugin @Inject constructor( medtronicPumpStatus.tempBasalStart = Date() medtronicPumpStatus.tempBasalAmount = absoluteRate medtronicPumpStatus.tempBasalLength = durationInMinutes - val tempStart = TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // - .duration(durationInMinutes) // - .absolute(absoluteRate) // - .source(Source.USER) - - activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) - - // val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + // val tempStart = TemporaryBasal(injector) // + // .date(System.currentTimeMillis()) // + // .duration(durationInMinutes) // + // .absolute(absoluteRate) // + // .source(Source.USER) // - // pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) + // activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) + + val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + + pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) incrementStatistics(MedtronicConst.Statistics.TBRsSet) finishAction("TBR") @@ -1003,17 +1003,17 @@ class MedtronicPumpPlugin @Inject constructor( finishAction("TBR") return if (response!!) { aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR successful.") - val tempBasal = TemporaryBasal(injector) // - .date(System.currentTimeMillis()) // - .duration(0) // - .source(Source.USER) - - activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) + // val tempBasal = TemporaryBasal(injector) // + // .date(System.currentTimeMillis()) // + // .duration(0) // + // .source(Source.USER) + // + // activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) // TODO need to find solution for this !? - // val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) - // - // pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) + val tempData = PumpDbEntryTBR(0.0, true, 0, TemporaryBasalType.NORMAL) + + pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index e731eb1ce9..22068001b2 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -26,7 +26,6 @@ import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType 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 -import info.nightscout.androidaps.utils.Round import info.nightscout.androidaps.utils.sharedPreferences.SP import org.apache.commons.lang3.StringUtils import org.joda.time.LocalDateTime @@ -579,23 +578,24 @@ class MedtronicHistoryData @Inject constructor( entryList.removeAt(0) } } - val oldestTimestamp = getOldestTimestamp(entryList) - val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.TBR) + + val tbrRecords = pumpSyncStorage.getTBRs() aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.description + " List (before filter): %s, FromDb=%s", gson.toJson(entryList), - gson.toJson(entriesFromHistory))) + gson.toJson(tbrRecords))) var processDTO: TempBasalProcessDTO? = null - val processList: MutableList = ArrayList() + val processList: MutableList = mutableListOf() for (treatment in entryList) { val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair? if (tbr2!!.isCancelTBR) { if (processDTO != null) { processDTO.itemTwo = treatment + processDTO.cancelPresent = true if (readOldItem) { processDTO.processOperation = TempBasalProcessDTO.Operation.Edit readOldItem = false } } else { - aapsLogger.error("processDTO was null - shouldn't happen. ItemTwo=$treatment") + aapsLogger.warn(LTag.PUMP,"processDTO was null - shouldn't happen, ignoring item. ItemTwo=$treatment") } } else { if (processDTO != null) { @@ -609,41 +609,152 @@ class MedtronicHistoryData @Inject constructor( if (processDTO != null) { processList.add(processDTO) } - if (isCollectionNotEmpty(processList)) { + if (processList.isNotEmpty()) { for (tempBasalProcessDTO in processList) { - if (tempBasalProcessDTO.processOperation === TempBasalProcessDTO.Operation.Edit) { - // edit - val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) - if (tempBasal != null) { - tempBasal.durationInMinutes = tempBasalProcessDTO.duration - // TODO pumpSync - createOrUpdate(tempBasal) - databaseHelper.createOrUpdate(tempBasal) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Edit " + ProcessHistoryRecord.TBR.description + " - (entryFromDb=%s) ", tempBasal)) - } else { - aapsLogger.error(LTag.PUMP, "TempBasal not found. Item: " + tempBasalProcessDTO.itemOne) - } + + val entryWithTempId = findDbEntry(tempBasalProcessDTO.itemOne, tbrRecords) + + val tbrEntry = tempBasalProcessDTO.itemOne!!.getDecodedDataEntry("Object") as TempBasalPair + + removeCancelTBRTemporaryRecord(tempBasalProcessDTO, tbrRecords) // TODO + + if (entryWithTempId!=null) { + val result = pumpSync.syncTemporaryBasalWithTempId( + tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), + tbrEntry.insulinRate, + tempBasalProcessDTO.duration * 60L * 1000L, + !tbrEntry.isPercent, + entryWithTempId.temporaryId, + PumpSync.TemporaryBasalType.NORMAL, + tempBasalProcessDTO.pumpId, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncTemporaryBasalWithTempId [date=%d, temporaryId=%d, pumpId=%d, rate=%.2f %s, duration=%d, pumpSerial=%s] - Result: %b", + tempBasalProcessDTO.atechDateTime, entryWithTempId.temporaryId, tempBasalProcessDTO.pumpId, + tbrEntry.insulinRate, (if (tbrEntry.isPercent) "%" else "U"), tempBasalProcessDTO.duration, + medtronicPumpStatus.serialNumber!!, result)) + + pumpSyncStorage.removeTemporaryBasalWithTemporaryId(entryWithTempId.temporaryId) + } else { - // add - val treatment = tempBasalProcessDTO.itemOne - val tbr2 = treatment!!.decodedData!!["Object"] as TempBasalPair? - tbr2!!.durationMinutes = tempBasalProcessDTO.duration - val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) - if (tempBasal == null) { - val treatmentDb = findDbEntry_Old(treatment, entriesFromHistory) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add " + ProcessHistoryRecord.TBR.description + " %s - (entryFromDb=%s) ", treatment, treatmentDb)) - addTBR(treatment, treatmentDb as TemporaryBasal?) - } else { - // this shouldn't happen - if (tempBasal.durationInMinutes != tempBasalProcessDTO.duration) { - aapsLogger.debug(LTag.PUMP, "Found entry with wrong duration (shouldn't happen)... updating") - tempBasal.durationInMinutes = tempBasalProcessDTO.duration - } - } - } // if + val result = pumpSync.syncTemporaryBasalWithPumpId( + tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), + tbrEntry.insulinRate, + tempBasalProcessDTO.duration * 60L * 1000L, + !tbrEntry.isPercent, + PumpSync.TemporaryBasalType.NORMAL, + tempBasalProcessDTO.pumpId, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncTemporaryBasalWithPumpId [date=%d, pumpId=%d, rate=%.2f %s, duration=%d, pumpSerial=%s] - Result: %b", + tempBasalProcessDTO.atechDateTime, tempBasalProcessDTO.pumpId, + tbrEntry.insulinRate, (if (tbrEntry.isPercent) "%" else "U"), tempBasalProcessDTO.duration, + medtronicPumpStatus.serialNumber!!, result)) + } } // for } // collection } + + private fun removeCancelTBRTemporaryRecord(tempBasalProcessDTO: TempBasalProcessDTO, tbrRecords: MutableList) { + //fun syncTemporaryBasalWithPumpId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, type: PumpSync.TemporaryBasalType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean + if (tempBasalProcessDTO.cancelPresent) { + + //val dateTime : Long = DateTimeUtil.getMillisFromATDWithAddedMinutes(tempBasalProcessDTO.atechDateTime, tempBasalProcessDTO.duration) + + val dbEntry = findDbEntry(tempBasalProcessDTO.itemTwo!!, tbrRecords) + + if (dbEntry!=null) { + if (dbEntry.tbrData!!.durationInMinutes == 0) { + pumpSync.invalidateTemporaryBasal(dbEntry.temporaryId) // TODO fix + } + } + + // + } + } + + + // private fun processTBREntries_Old(entryList: MutableList) { + // Collections.reverse(entryList) + // val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? + // var readOldItem = false + // if (tbr!!.isCancelTBR) { + // val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) + // if (oneMoreEntryFromHistory != null) { + // entryList.add(0, oneMoreEntryFromHistory) + // readOldItem = true + // } else { + // entryList.removeAt(0) + // } + // } + // val oldestTimestamp = getOldestTimestamp(entryList) + // val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.TBR) + // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.description + " List (before filter): %s, FromDb=%s", gson.toJson(entryList), + // gson.toJson(entriesFromHistory))) + // var processDTO: TempBasalProcessDTO? = null + // val processList: MutableList = ArrayList() + // for (treatment in entryList) { + // val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair? + // if (tbr2!!.isCancelTBR) { + // if (processDTO != null) { + // processDTO.itemTwo = treatment + // if (readOldItem) { + // processDTO.processOperation = TempBasalProcessDTO.Operation.Edit + // readOldItem = false + // } + // } else { + // aapsLogger.error("processDTO was null - shouldn't happen. ItemTwo=$treatment") + // } + // } else { + // if (processDTO != null) { + // processList.add(processDTO) + // } + // processDTO = TempBasalProcessDTO() + // processDTO.itemOne = treatment + // processDTO.processOperation = TempBasalProcessDTO.Operation.Add + // } + // } + // if (processDTO != null) { + // processList.add(processDTO) + // } + // if (isCollectionNotEmpty(processList)) { + // for (tempBasalProcessDTO in processList) { + // if (tempBasalProcessDTO.processOperation === TempBasalProcessDTO.Operation.Edit) { + // // edit + // val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) + // if (tempBasal != null) { + // tempBasal.durationInMinutes = tempBasalProcessDTO.duration + // // pumpSync - createOrUpdate(tempBasal) + // databaseHelper.createOrUpdate(tempBasal) + // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Edit " + ProcessHistoryRecord.TBR.description + " - (entryFromDb=%s) ", tempBasal)) + // } else { + // aapsLogger.error(LTag.PUMP, "TempBasal not found. Item: " + tempBasalProcessDTO.itemOne) + // } + // } else { + // // add + // val treatment = tempBasalProcessDTO.itemOne + // val tbr2 = treatment!!.decodedData!!["Object"] as TempBasalPair? + // tbr2!!.durationMinutes = tempBasalProcessDTO.duration + // val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) + // if (tempBasal == null) { + // val treatmentDb = findDbEntry_Old(treatment, entriesFromHistory) + // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add " + ProcessHistoryRecord.TBR.description + " %s - (entryFromDb=%s) ", treatment, treatmentDb)) + // addTBR(treatment, treatmentDb as TemporaryBasal?) + // } else { + // // this shouldn't happen + // if (tempBasal.durationInMinutes != tempBasalProcessDTO.duration) { + // aapsLogger.debug(LTag.PUMP, "Found entry with wrong duration (shouldn't happen)... updating") + // tempBasal.durationInMinutes = tempBasalProcessDTO.duration + // } + // } + // } // if + // } // for + // } // collection + // } + private fun findTempBasalWithPumpId(pumpId: Long, entriesFromHistory: List): TemporaryBasal? { for (dbObjectBase in entriesFromHistory) { val tbr = dbObjectBase as TemporaryBasal diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt index a7705f8c2f..52e6152b38 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt @@ -4,9 +4,17 @@ 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 + var itemOne: PumpHistoryEntry? = null + var itemTwo: PumpHistoryEntry? = null + var processOperation = Operation.None + var cancelPresent: Boolean = false + + val atechDateTime: Long + get() = if (itemOne==null) 0L else itemOne!!.atechDateTime!! + + val pumpId: Long + get() = if (itemOne==null) 0L else itemOne!!.pumpId!! + val duration: Int get() = if (itemTwo == null) { val tbr = itemOne!!.getDecodedDataEntry("Object") as TempBasalPair? From 7738520a2d323530975a7c46848d303b199ed23e Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 5 May 2021 16:58:37 +0100 Subject: [PATCH 15/39] - dropbox dep --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index ce044fe703..fa64aff5fa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -197,7 +197,7 @@ dependencies { /* Dagger2 - We are going to use dagger.android which includes * support for Activity and fragment injection so we need to include * the following dependencies */ - + implementation 'com.dropbox.core:dropbox-core-sdk:2.1.1' annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version" From f285b59b441f6d8e09a39524d264b7947eb3690e Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Thu, 6 May 2021 20:30:18 +0100 Subject: [PATCH 16/39] - finished implementation of TBR and Bolus, needs more testing - missing 35 minutes --- .../plugins/pump/common/sync/PumpDbEntry.kt | 3 +- .../plugins/pump/common/PumpPluginAbstract.kt | 16 +- .../plugins/pump/common/data/PumpStatus.kt | 1 + .../pump/medtronic/MedtronicPumpPlugin.kt | 32 +++- .../comm/history/pump/PumpHistoryEntry.kt | 2 +- .../medtronic/data/MedtronicHistoryData.kt | 163 +++++++++++------- .../medtronic/driver/MedtronicPumpStatus.kt | 2 + 7 files changed, 138 insertions(+), 81 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt index 65bd3d0728..c84312cebc 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt @@ -10,7 +10,8 @@ data class PumpDbEntry constructor(var temporaryId: Long, var pumpType: PumpType, var serialNumber: String, var bolusData: PumpDbEntryBolus? = null, - var tbrData: PumpDbEntryTBR? = null ) { + var tbrData: PumpDbEntryTBR? = null, + var pumpId: Long? = null) { constructor(temporaryId: Long, date: Long, diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index bd32f2f509..5bfc2150bf 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -78,7 +78,7 @@ abstract class PumpPluginAbstract protected constructor( get() = field set(value) { field = value - pumpDescription.setPumpDescription(value) + pumpDescription.fillFor(value) } @@ -90,19 +90,19 @@ abstract class PumpPluginAbstract protected constructor( super.onStart() initPumpStatusData() val intent = Intent(context, serviceClass) - context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) + context.bindService(intent, serviceConnection!!, Context.BIND_AUTO_CREATE) serviceRunning = true disposable.add(rxBus .toObservable(EventAppExit::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ event: EventAppExit? -> context.unbindService(serviceConnection) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } + .subscribe({ event: EventAppExit? -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } ) onStartCustomActions() } override fun onStop() { aapsLogger.debug(LTag.PUMP, deviceID() + " onStop()") - context.unbindService(serviceConnection) + context.unbindService(serviceConnection!!) serviceRunning = false disposable.clear() super.onStop() @@ -250,7 +250,7 @@ abstract class PumpPluginAbstract protected constructor( val extended = JSONObject() try { battery.put("percent", pumpStatusData.batteryRemaining) - status.put("status", if (pumpStatusData.pumpStatusType != null) pumpStatusData.pumpStatusType.status else "normal") + status.put("status", pumpStatusData.pumpStatusType.status) extended.put("Version", version) try { extended.put("ActiveProfile", profileName) @@ -386,12 +386,8 @@ abstract class PumpPluginAbstract protected constructor( } - init { - pumpDescription.setPumpDescription(pumpType) + pumpDescription.fillFor(pumpType) this.pumpType = pumpType - this.dateUtil = dateUtil - this.aapsSchedulers = aapsSchedulers - //this.pumpSync = pumpSync } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt index 42bc97f6ee..8c467ef234 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt @@ -2,6 +2,7 @@ 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 info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry import java.util.* /** diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 2fe0482bd1..12eb731d35 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -48,6 +48,7 @@ import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile.Companion.getProfilesByHourToString import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfileEntry import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalProcessDTO import info.nightscout.androidaps.plugins.pump.medtronic.defs.* import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType.Companion.getSettings import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus @@ -1011,9 +1012,36 @@ class MedtronicPumpPlugin @Inject constructor( // activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) // TODO need to find solution for this !? - val tempData = PumpDbEntryTBR(0.0, true, 0, TemporaryBasalType.NORMAL) + //val tempData = PumpDbEntryTBR(0.0, true, 0, TemporaryBasalType.NORMAL) - pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) + val runningTBR = medtronicPumpStatus.runningTBR + + if (runningTBR!=null) { + if (medtronicHistoryData.isTBRActive(runningTBR)) { + + val differenceTime = System.currentTimeMillis() - runningTBR.date + val tbrData = runningTBR.tbrData!! + + val result = pumpSync.syncTemporaryBasalWithPumpId( + runningTBR.date, + tbrData.rate, + differenceTime, + tbrData.isAbsolute, + tbrData.tbrType, + runningTBR.pumpId!!, + runningTBR.pumpType, + runningTBR.serialNumber) + + val differenceTimeMin = Math.floor(differenceTime/(60.0*1000.0)) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "canceling running TBR - syncTemporaryBasalWithPumpId [date=%d, pumpId=%d, rate=%.2f U, duration=%d, pumpSerial=%s] - Result: %b", + runningTBR.date, runningTBR.pumpId!!, + tbrData.rate, differenceTimeMin.toInt(), + medtronicPumpStatus.serialNumber!!, result)) + } + } + + //pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index b8f37cf379..a38ec2647e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -72,7 +72,7 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is PumpHistoryEntry) return false - val that = other as PumpHistoryEntry + val that = other //as PumpHistoryEntry return this.pumpId === that.pumpId // return entryType == that.entryType && // // atechDateTime === that.atechDateTime // && // diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 22068001b2..9acae80415 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -62,6 +62,7 @@ class MedtronicHistoryData @Inject constructor( ) { val allHistory: MutableList = mutableListOf() + private var allPumpIds: MutableSet = mutableSetOf() private var newHistory: MutableList = mutableListOf() private var isInit = false @@ -80,7 +81,7 @@ class MedtronicHistoryData @Inject constructor( val validEntries: List = result.validEntries val newEntries: MutableList = mutableListOf() for (validEntry in validEntries) { - if (!allHistory.contains(validEntry)) { + if (!allPumpIds.contains(validEntry.pumpId)) { newEntries.add(validEntry) } else { val entryByPumpId = getEntryByPumpId(validEntry.pumpId!!) @@ -137,7 +138,7 @@ class MedtronicHistoryData @Inject constructor( //aapsLogger.debug(LTag.PUMP, "Filter new entries: Before {}", newHistory); if (!isCollectionEmpty(newHistory)) { for (pumpHistoryEntry in newHistory) { - if (!allHistory.contains(pumpHistoryEntry)) { + if (!allPumpIds.contains(pumpHistoryEntry.pumpId)) { val type = pumpHistoryEntry.entryType if (type === PumpHistoryEntryType.TempBasalRate || type === PumpHistoryEntryType.TempBasalDuration) { tbrs.add(pumpHistoryEntry) @@ -160,7 +161,16 @@ class MedtronicHistoryData @Inject constructor( extendBolusRecords(bolusEstimates, newHistory2) } newHistory2.addAll(tbrs) - newHistory = newHistory2 + + val newHistory3: MutableList = mutableListOf() + + for (pumpHistoryEntry in newHistory2) { + if (!allPumpIds.contains(pumpHistoryEntry.pumpId)) { + newHistory3.add(pumpHistoryEntry) + } + } + + newHistory = newHistory3 sort(newHistory) } aapsLogger.debug(LTag.PUMP, "New History entries found: " + newHistory.size) @@ -192,10 +202,11 @@ class MedtronicHistoryData @Inject constructor( // add new entries newHistory.reverse() for (pumpHistoryEntry in newHistory) { - if (!allHistory.contains(pumpHistoryEntry)) { + if (!allPumpIds.contains(pumpHistoryEntry.pumpId)) { lastIdUsed++ pumpHistoryEntry.id = lastIdUsed allHistory.add(pumpHistoryEntry) + allPumpIds.add(pumpHistoryEntry.pumpId!!) } } // if (pheLast == null) // if we don't have any valid record we don't do the filtering and setting @@ -215,6 +226,7 @@ class MedtronicHistoryData @Inject constructor( for (pumpHistoryEntry in allHistory) { if (!pumpHistoryEntry.isAfter(dtRemove)) { removeList.add(pumpHistoryEntry) + allPumpIds.remove(pumpHistoryEntry.pumpId!!) } } allHistory.removeAll(removeList) @@ -262,33 +274,34 @@ class MedtronicHistoryData @Inject constructor( } else false } + private fun getDataForPumpSuspends(): MutableList { - val newAndAll: MutableList = mutableListOf() - if (isCollectionNotEmpty(allHistory)) { - newAndAll.addAll(allHistory) - } - if (isCollectionNotEmpty(newHistory)) { - for (pumpHistoryEntry in newHistory) { - if (!newAndAll.contains(pumpHistoryEntry)) { - newAndAll.add(pumpHistoryEntry) - } + val newAndAll: MutableList = mutableListOf() + if (isCollectionNotEmpty(allHistory)) { + newAndAll.addAll(allHistory) + } + if (isCollectionNotEmpty(newHistory)) { + for (pumpHistoryEntry in newHistory) { + if (!newAndAll.contains(pumpHistoryEntry)) { + newAndAll.add(pumpHistoryEntry) } } - if (newAndAll.isEmpty()) return newAndAll - this.sort(newAndAll) - var newAndAll2: MutableList = getFilteredItems(newAndAll, // - setOf(PumpHistoryEntryType.Bolus, // - PumpHistoryEntryType.TempBasalCombined, // - PumpHistoryEntryType.Prime, // - PumpHistoryEntryType.SuspendPump, // - PumpHistoryEntryType.ResumePump, // - PumpHistoryEntryType.Rewind, // - PumpHistoryEntryType.NoDeliveryAlarm, // - PumpHistoryEntryType.BatteryChange, // - PumpHistoryEntryType.BasalProfileStart)) - newAndAll2 = filterPumpSuspend(newAndAll2, 10) - return newAndAll2 } + if (newAndAll.isEmpty()) return newAndAll + this.sort(newAndAll) + var newAndAll2: MutableList = getFilteredItems(newAndAll, // + setOf(PumpHistoryEntryType.Bolus, // + PumpHistoryEntryType.TempBasalCombined, // + PumpHistoryEntryType.Prime, // + PumpHistoryEntryType.SuspendPump, // + PumpHistoryEntryType.ResumePump, // + PumpHistoryEntryType.Rewind, // + PumpHistoryEntryType.NoDeliveryAlarm, // + PumpHistoryEntryType.BatteryChange, // + PumpHistoryEntryType.BasalProfileStart)) + newAndAll2 = filterPumpSuspend(newAndAll2, 10) + return newAndAll2 + } private fun filterPumpSuspend(newAndAll: MutableList, filterCount: Int): MutableList { if (newAndAll.size <= filterCount) { @@ -389,7 +402,8 @@ class MedtronicHistoryData @Inject constructor( private fun processPrime(primeRecords: List) { val maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(GregorianCalendar(), -30) - var lastPrimeRecord = 0L + var lastPrimeRecordTime = 0L + var lastPrimeRecord: PumpHistoryEntry? = null for (primeRecord in primeRecords) { val fixedAmount = primeRecord!!.getDecodedDataEntry("FixedAmount") if (fixedAmount != null && fixedAmount as Float == 0.0f) { @@ -399,44 +413,58 @@ class MedtronicHistoryData @Inject constructor( continue } if (primeRecord.atechDateTime!! > maxAllowedTimeInPast) { - if (lastPrimeRecord < primeRecord.atechDateTime!!) { - lastPrimeRecord = primeRecord.atechDateTime!! + if (lastPrimeRecordTime < primeRecord.atechDateTime!!) { + lastPrimeRecordTime = primeRecord.atechDateTime!! + lastPrimeRecord = primeRecord } } } - if (lastPrimeRecord != 0L) { - val lastPrimeFromAAPS = sp.getLong(MedtronicConst.Statistics.LastPrime, 0L) - if (lastPrimeRecord != lastPrimeFromAAPS) { - uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastPrimeRecord), DetailedBolusInfo.EventType.CANNULA_CHANGE) - sp.putLong(MedtronicConst.Statistics.LastPrime, lastPrimeRecord) - } + if (lastPrimeRecord != null) { + uploadCareportalEventIfFoundInHistory(lastPrimeRecord, + MedtronicConst.Statistics.LastPrime, + DetailedBolusInfo.EventType.CANNULA_CHANGE) } } private fun processRewind(rewindRecords: List) { val maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(GregorianCalendar(), -30) - var lastRewindRecord = 0L + var lastRewindRecordTime = 0L + var lastRewindRecord: PumpHistoryEntry? = null for (rewindRecord in rewindRecords) { if (rewindRecord!!.atechDateTime!! > maxAllowedTimeInPast) { - if (lastRewindRecord < rewindRecord.atechDateTime!!) { - lastRewindRecord = rewindRecord.atechDateTime!! + if (lastRewindRecordTime < rewindRecord.atechDateTime!!) { + lastRewindRecordTime = rewindRecord.atechDateTime!! + lastRewindRecord = rewindRecord } } } - if (lastRewindRecord != 0L) { - val lastRewindFromAAPS = sp.getLong(MedtronicConst.Statistics.LastRewind, 0L) - if (lastRewindRecord != lastRewindFromAAPS) { - uploadCareportalEvent(DateTimeUtil.toMillisFromATD(lastRewindRecord), DetailedBolusInfo.EventType.INSULIN_CHANGE) - sp.putLong(MedtronicConst.Statistics.LastRewind, lastRewindRecord) - } + if (lastRewindRecord != null) { + uploadCareportalEventIfFoundInHistory(lastRewindRecord, + MedtronicConst.Statistics.LastRewind, + DetailedBolusInfo.EventType.INSULIN_CHANGE) } } - private fun uploadCareportalEvent(date: Long, event: DetailedBolusInfo.EventType) { - pumpSync.insertTherapyEventIfNewWithTimestamp(date, event, null, null, - medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) + + private fun uploadCareportalEventIfFoundInHistory(historyRecord: PumpHistoryEntry, eventSP: String, eventType: DetailedBolusInfo.EventType) { + val lastPrimeFromAAPS = sp.getLong(eventSP, 0L) + if (historyRecord.atechDateTime != lastPrimeFromAAPS) { + var result = pumpSync.insertTherapyEventIfNewWithTimestamp( + DateTimeUtil.toMillisFromATD(historyRecord.atechDateTime!!), + eventType, null, + historyRecord.pumpId, + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!) + + aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "insertTherapyEventIfNewWithTimestamp [date=%d, eventType=%d, pumpId=%d, pumpSerial=%s] - Result: %b", + historyRecord.atechDateTime!!, eventType, historyRecord.pumpId, + medtronicPumpStatus.serialNumber!!, result)) + + sp.putLong(eventSP, historyRecord.atechDateTime!!) + } } + private fun processTDDs(tddsIn: MutableList) { val tdds = filterTDDs(tddsIn) @@ -616,7 +644,7 @@ class MedtronicHistoryData @Inject constructor( val tbrEntry = tempBasalProcessDTO.itemOne!!.getDecodedDataEntry("Object") as TempBasalPair - removeCancelTBRTemporaryRecord(tempBasalProcessDTO, tbrRecords) // TODO + //removeCancelTBRTemporaryRecord(tempBasalProcessDTO, tbrRecords) if (entryWithTempId!=null) { val result = pumpSync.syncTemporaryBasalWithTempId( @@ -636,6 +664,14 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.serialNumber!!, result)) pumpSyncStorage.removeTemporaryBasalWithTemporaryId(entryWithTempId.temporaryId) + tbrRecords.remove(entryWithTempId) + + entryWithTempId.pumpId = tempBasalProcessDTO.pumpId + entryWithTempId.date = tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime) + + if (isTBRActive(entryWithTempId)) { + medtronicPumpStatus.runningTBR = entryWithTempId + } } else { val result = pumpSync.syncTemporaryBasalWithPumpId( @@ -659,24 +695,29 @@ class MedtronicHistoryData @Inject constructor( private fun removeCancelTBRTemporaryRecord(tempBasalProcessDTO: TempBasalProcessDTO, tbrRecords: MutableList) { - //fun syncTemporaryBasalWithPumpId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, type: PumpSync.TemporaryBasalType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean if (tempBasalProcessDTO.cancelPresent) { //val dateTime : Long = DateTimeUtil.getMillisFromATDWithAddedMinutes(tempBasalProcessDTO.atechDateTime, tempBasalProcessDTO.duration) - val dbEntry = findDbEntry(tempBasalProcessDTO.itemTwo!!, tbrRecords) if (dbEntry!=null) { if (dbEntry.tbrData!!.durationInMinutes == 0) { - pumpSync.invalidateTemporaryBasal(dbEntry.temporaryId) // TODO fix + pumpSync.invalidateTemporaryBasalWithTempId(dbEntry.temporaryId) + pumpSyncStorage.removeTemporaryBasalWithTemporaryId(dbEntry.temporaryId) + tbrRecords.remove(dbEntry) } } - - // } } + fun isTBRActive(dbEntry: PumpDbEntry) : Boolean { + val endDate = dbEntry.date + (dbEntry.tbrData!!.durationInMinutes * 60 * 1000) + + return (endDate > System.currentTimeMillis()) + } + + // private fun processTBREntries_Old(entryList: MutableList) { // Collections.reverse(entryList) // val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? @@ -777,8 +818,8 @@ class MedtronicHistoryData @Inject constructor( */ private fun findDbEntry_Old(treatment: PumpHistoryEntry?, entriesFromHistory: List): DbObjectBase? { val proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) - //proposedTime += (this.pumpTime.timeDifference * 1000); + if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s", treatment, gson.toJson(entriesFromHistory))) if (entriesFromHistory.size == 0) { if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=null", treatment)) @@ -1268,16 +1309,4 @@ class MedtronicHistoryData @Inject constructor( const val doubleBolusDebug = false } - init { - //allHistory = ArrayList() - //this.injector = injector - //this.aapsLogger = aapsLogger - // this.sp = sp - // this.activePlugin = activePlugin - // this.medtronicUtil = medtronicUtil - // this.medtronicPumpHistoryDecoder = medtronicPumpHistoryDecoder - // this.medtronicPumpStatus = medtronicPumpStatus - // databaseHelper = databaseHelperInterface - //this.pumpSync = pumpSync - } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index c54bbcf90d..1ebad72414 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -8,6 +8,7 @@ import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDevic 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.common.sync.PumpDbEntry 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 @@ -33,6 +34,7 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour var pumpFrequency: String? = null var maxBolus: Double? = null var maxBasal: Double? = null + var runningTBR: PumpDbEntry? = null // statuses var pumpDeviceState = PumpDeviceState.NeverContacted From 2b43ee186f530b4b12f42c0222c8ff3bc8777745 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 8 May 2021 15:43:19 +0100 Subject: [PATCH 17/39] - final changes to pumpSync integration - removed commented code that is not used --- .../pump/common/sync/PumpSyncStorage.kt | 8 +- .../plugins/pump/common/PumpPluginAbstract.kt | 4 +- .../pump/medtronic/MedtronicPumpPlugin.kt | 11 - .../medtronic/data/MedtronicHistoryData.kt | 269 +++--------------- 4 files changed, 37 insertions(+), 255 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt index 83d4a85745..f89103cb35 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -4,11 +4,9 @@ import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.reflect.TypeToken import info.nightscout.androidaps.data.DetailedBolusInfo -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.utils.sharedPreferences.SP import java.lang.reflect.Type import java.util.* @@ -84,6 +82,7 @@ class PumpSyncStorage @Inject constructor( return pumpSyncStorage[BOLUS]!!; } + fun getTBRs() : MutableList { return pumpSyncStorage[TBR]!!; } @@ -130,7 +129,7 @@ class PumpSyncStorage @Inject constructor( carbsDto.date, carbsDto.carbs, carbsDto.serialNumber, result)) } - // TODO + fun addTemporaryBasalRateWithTempId(temporaryBasal: PumpDbEntryTBR, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator) : Boolean { val timenow : Long = System.currentTimeMillis() val temporaryId = creator.generateTempId(timenow) @@ -157,19 +156,20 @@ class PumpSyncStorage @Inject constructor( } - fun removeBolusWithTemporaryId(temporaryId: Long) { val bolusList = removeTemporaryId(temporaryId, pumpSyncStorage[BOLUS]!!) pumpSyncStorage[BOLUS] = bolusList saveStorage() } + fun removeTemporaryBasalWithTemporaryId(temporaryId: Long) { val tbrList = removeTemporaryId(temporaryId, pumpSyncStorage[TBR]!!) pumpSyncStorage[TBR] = tbrList saveStorage() } + private fun removeTemporaryId(temporaryId: Long, list: MutableList): MutableList { var dbEntry: PumpDbEntry? = null diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index 5bfc2150bf..b2462ade1f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -9,7 +9,6 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.core.R import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.events.EventAppExit import info.nightscout.androidaps.events.EventCustomActionsChanged import info.nightscout.androidaps.extensions.convertedToAbsolute @@ -28,7 +27,6 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage -import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal @@ -39,7 +37,7 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable import org.json.JSONException import org.json.JSONObject -import java.util.* + /** * Created by andy on 23.04.18. diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 12eb731d35..281f315614 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -11,7 +11,6 @@ import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAl import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.db.Source -import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType @@ -828,7 +827,6 @@ class MedtronicPumpPlugin @Inject constructor( } medtronicHistoryData.processNewHistoryData() medtronicHistoryData.finalizeNewHistoryRecords() - // this.medtronicHistoryData.setLastHistoryRecordTime(this.lastPumpHistoryEntry.atechDateTime); } private fun readPumpHistoryLogic() { @@ -1004,15 +1002,6 @@ class MedtronicPumpPlugin @Inject constructor( finishAction("TBR") return if (response!!) { aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR successful.") - // val tempBasal = TemporaryBasal(injector) // - // .date(System.currentTimeMillis()) // - // .duration(0) // - // .source(Source.USER) - // - // activePlugin.activeTreatments.addToHistoryTempBasal(tempBasal) - - // TODO need to find solution for this !? - //val tempData = PumpDbEntryTBR(0.0, true, 0, TemporaryBasalType.NORMAL) val runningTBR = medtronicPumpStatus.runningTBR diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 9acae80415..1c67eb3b92 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -12,7 +12,9 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryBolus import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil @@ -644,8 +646,6 @@ class MedtronicHistoryData @Inject constructor( val tbrEntry = tempBasalProcessDTO.itemOne!!.getDecodedDataEntry("Object") as TempBasalPair - //removeCancelTBRTemporaryRecord(tempBasalProcessDTO, tbrRecords) - if (entryWithTempId!=null) { val result = pumpSync.syncTemporaryBasalWithTempId( tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), @@ -688,124 +688,43 @@ class MedtronicHistoryData @Inject constructor( tempBasalProcessDTO.atechDateTime, tempBasalProcessDTO.pumpId, tbrEntry.insulinRate, (if (tbrEntry.isPercent) "%" else "U"), tempBasalProcessDTO.duration, medtronicPumpStatus.serialNumber!!, result)) + + if (medtronicPumpStatus.runningTBR!=null) { + if (!isTBRActive(medtronicPumpStatus.runningTBR!!)) { + medtronicPumpStatus.runningTBR = null + } + } + + if (isTBRActive(tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), tempBasalProcessDTO.duration)) { + if (medtronicPumpStatus.runningTBR == null) { + medtronicPumpStatus.runningTBR = PumpDbEntry(0L, + tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), + medtronicPumpStatus.pumpType, + medtronicPumpStatus.serialNumber!!, + null, + PumpDbEntryTBR(tbrEntry.insulinRate, !tbrEntry.isPercent, tempBasalProcessDTO.duration, PumpSync.TemporaryBasalType.NORMAL), + tempBasalProcessDTO.pumpId) + } + } } } // for } // collection } - private fun removeCancelTBRTemporaryRecord(tempBasalProcessDTO: TempBasalProcessDTO, tbrRecords: MutableList) { - if (tempBasalProcessDTO.cancelPresent) { - - //val dateTime : Long = DateTimeUtil.getMillisFromATDWithAddedMinutes(tempBasalProcessDTO.atechDateTime, tempBasalProcessDTO.duration) - val dbEntry = findDbEntry(tempBasalProcessDTO.itemTwo!!, tbrRecords) - - if (dbEntry!=null) { - if (dbEntry.tbrData!!.durationInMinutes == 0) { - pumpSync.invalidateTemporaryBasalWithTempId(dbEntry.temporaryId) - pumpSyncStorage.removeTemporaryBasalWithTemporaryId(dbEntry.temporaryId) - tbrRecords.remove(dbEntry) - } - } - } + fun isTBRActive(dbEntry: PumpDbEntry) : Boolean { + return isTBRActive(dbEntry.date, dbEntry.tbrData!!.durationInMinutes) } - fun isTBRActive(dbEntry: PumpDbEntry) : Boolean { - val endDate = dbEntry.date + (dbEntry.tbrData!!.durationInMinutes * 60 * 1000) + fun isTBRActive(startTimestamp: Long, durationMin: Int) : Boolean { + val endDate = startTimestamp + (durationMin * 60 * 1000) return (endDate > System.currentTimeMillis()) } - // private fun processTBREntries_Old(entryList: MutableList) { - // Collections.reverse(entryList) - // val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? - // var readOldItem = false - // if (tbr!!.isCancelTBR) { - // val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) - // if (oneMoreEntryFromHistory != null) { - // entryList.add(0, oneMoreEntryFromHistory) - // readOldItem = true - // } else { - // entryList.removeAt(0) - // } - // } - // val oldestTimestamp = getOldestTimestamp(entryList) - // val entriesFromHistory = getDatabaseEntriesByLastTimestamp(oldestTimestamp, ProcessHistoryRecord.TBR) - // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.description + " List (before filter): %s, FromDb=%s", gson.toJson(entryList), - // gson.toJson(entriesFromHistory))) - // var processDTO: TempBasalProcessDTO? = null - // val processList: MutableList = ArrayList() - // for (treatment in entryList) { - // val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair? - // if (tbr2!!.isCancelTBR) { - // if (processDTO != null) { - // processDTO.itemTwo = treatment - // if (readOldItem) { - // processDTO.processOperation = TempBasalProcessDTO.Operation.Edit - // readOldItem = false - // } - // } else { - // aapsLogger.error("processDTO was null - shouldn't happen. ItemTwo=$treatment") - // } - // } else { - // if (processDTO != null) { - // processList.add(processDTO) - // } - // processDTO = TempBasalProcessDTO() - // processDTO.itemOne = treatment - // processDTO.processOperation = TempBasalProcessDTO.Operation.Add - // } - // } - // if (processDTO != null) { - // processList.add(processDTO) - // } - // if (isCollectionNotEmpty(processList)) { - // for (tempBasalProcessDTO in processList) { - // if (tempBasalProcessDTO.processOperation === TempBasalProcessDTO.Operation.Edit) { - // // edit - // val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) - // if (tempBasal != null) { - // tempBasal.durationInMinutes = tempBasalProcessDTO.duration - // // pumpSync - createOrUpdate(tempBasal) - // databaseHelper.createOrUpdate(tempBasal) - // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Edit " + ProcessHistoryRecord.TBR.description + " - (entryFromDb=%s) ", tempBasal)) - // } else { - // aapsLogger.error(LTag.PUMP, "TempBasal not found. Item: " + tempBasalProcessDTO.itemOne) - // } - // } else { - // // add - // val treatment = tempBasalProcessDTO.itemOne - // val tbr2 = treatment!!.decodedData!!["Object"] as TempBasalPair? - // tbr2!!.durationMinutes = tempBasalProcessDTO.duration - // val tempBasal = findTempBasalWithPumpId(tempBasalProcessDTO.itemOne!!.pumpId!!, entriesFromHistory) - // if (tempBasal == null) { - // val treatmentDb = findDbEntry_Old(treatment, entriesFromHistory) - // aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Add " + ProcessHistoryRecord.TBR.description + " %s - (entryFromDb=%s) ", treatment, treatmentDb)) - // addTBR(treatment, treatmentDb as TemporaryBasal?) - // } else { - // // this shouldn't happen - // if (tempBasal.durationInMinutes != tempBasalProcessDTO.duration) { - // aapsLogger.debug(LTag.PUMP, "Found entry with wrong duration (shouldn't happen)... updating") - // tempBasal.durationInMinutes = tempBasalProcessDTO.duration - // } - // } - // } // if - // } // for - // } // collection - // } - private fun findTempBasalWithPumpId(pumpId: Long, entriesFromHistory: List): TemporaryBasal? { - for (dbObjectBase in entriesFromHistory) { - val tbr = dbObjectBase as TemporaryBasal - if (tbr.pumpId == pumpId) { - return tbr - } - } - // TODO pumpSync - findTempBasalByPumpId - return databaseHelper.findTempBasalByPumpId(pumpId) - } /** * findDbEntry - finds Db entries in database, while theoretically this should have same dateTime they @@ -816,56 +735,6 @@ class MedtronicHistoryData @Inject constructor( * @param entriesFromHistory entries from history * @return DbObject from AAPS (if found) */ - private fun findDbEntry_Old(treatment: PumpHistoryEntry?, entriesFromHistory: List): DbObjectBase? { - val proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) - //proposedTime += (this.pumpTime.timeDifference * 1000); - - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s", treatment, gson.toJson(entriesFromHistory))) - if (entriesFromHistory.size == 0) { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=null", treatment)) - return null - } else if (entriesFromHistory.size == 1) { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment=%s, FromDb=%s. Type=SingleEntry", treatment, entriesFromHistory[0])) - - // if difference is bigger than 2 minutes we discard entry - val maxMillisAllowed = DateTimeUtil.getMillisFromATDWithAddedMinutes(treatment.atechDateTime!!, 2) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry maxMillisAllowed=%d, AtechDateTime=%d (add 2 minutes). ", maxMillisAllowed, treatment.atechDateTime)) - if (entriesFromHistory[0].getDate() > maxMillisAllowed) { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, "DoubleBolusDebug: findDbEntry entry filtered out, returning null. ") - return null - } - return entriesFromHistory[0] - } - var min = 0 - while (min < 2) { - var sec = 0 - while (sec <= 50) { - if (min == 1 && sec == 50) { - sec = 59 - } - val diff = sec * 1000 - val outList: MutableList = ArrayList() - for (treatment1 in entriesFromHistory) { - if (treatment1.getDate() > proposedTime - diff && treatment1.getDate() < proposedTime + diff) { - outList.add(treatment1) - } - } - if (outList.size == 1) { - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Treatment={}, FromDb={}. Type=EntrySelected, AtTimeMin={}, AtTimeSec={}", treatment, entriesFromHistory[0], min, sec)) - return outList[0] - } - if (min == 0 && sec == 10 && outList.size > 1) { - aapsLogger.error(String.format(Locale.ENGLISH, "Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", - min, sec, outList.size, gson.toJson(outList))) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: findDbEntry Error - Too many entries (with too small diff): (timeDiff=[min=%d,sec=%d],count=%d,list=%s)", - min, sec, outList.size, gson.toJson(outList))) - } - sec += 10 - } - min += 1 - } - return null - } /** * Looks at all boluses that have temporaryId and find one that is correct for us (if such entry exists) @@ -926,54 +795,6 @@ class MedtronicHistoryData @Inject constructor( } - private fun getDatabaseEntriesByLastTimestamp(startTimestamp: Long, processHistoryRecord: ProcessHistoryRecord): MutableList { - var outList: MutableList = mutableListOf() - - if (processHistoryRecord == ProcessHistoryRecord.Bolus) { - outList.addAll(activePlugin.activeTreatments.getTreatmentsFromHistoryAfterTimestamp(startTimestamp)) - } else { - // TODO pumpSync - databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true) - outList.addAll(databaseHelper.getTemporaryBasalsDataFromTime(startTimestamp, true)) - } - - return outList - } - - - private fun addCarbsFromEstimate(detailedBolusInfo: DetailedBolusInfo, bolus: PumpHistoryEntry?) { - if (bolus!!.containsDecodedData("Estimate")) { - val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO? - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: addCarbsFromEstimate: Bolus=%s, BolusWizardDTO=%s", bolus, bolusWizard)) - detailedBolusInfo.carbs = bolusWizard!!.carbs.toDouble() - } - } - - private fun addTBR(treatment: PumpHistoryEntry?, temporaryBasalDbInput: TemporaryBasal?) { - val tbr = treatment!!.decodedData!!["Object"] as TempBasalPair? - var temporaryBasalDb = temporaryBasalDbInput - var operation = "editTBR" - if (temporaryBasalDb == null) { - temporaryBasalDb = TemporaryBasal(injector) - temporaryBasalDb.date = tryToGetByLocalTime(treatment.atechDateTime!!) - operation = "addTBR" - } - temporaryBasalDb.source = Source.PUMP - temporaryBasalDb.pumpId = treatment.pumpId!! - temporaryBasalDb.durationInMinutes = tbr!!.durationMinutes - temporaryBasalDb.absoluteRate = tbr.insulinRate - temporaryBasalDb.isAbsolute = !tbr.isPercent - treatment.linkedObject = temporaryBasalDb - // TODO pumpSync - databaseHelper.createOrUpdate(tbr) - databaseHelper.createOrUpdate(temporaryBasalDb) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "$operation - [date=%d,pumpId=%d, rate=%s %s, duration=%d]", // - temporaryBasalDb.getDate(), // - temporaryBasalDb.getPumpId(), // - if (temporaryBasalDb.isAbsolute) String.format(Locale.ENGLISH, "%.2f", temporaryBasalDb.absoluteRate) else String.format(Locale.ENGLISH, "%d", temporaryBasalDb.percentRate), // - if (temporaryBasalDb.isAbsolute) "U/h" else "%", // - temporaryBasalDb.durationInMinutes)) - } - - private fun processSuspends(tempBasalProcessList: List) { for (tempBasalProcess in tempBasalProcessList) { @@ -1148,27 +969,6 @@ class MedtronicHistoryData @Inject constructor( return DateTimeUtil.toMillisFromATD(atechDateTime) } - private fun getOldestTimestamp(treatments: List): Long { - var dt = Long.MAX_VALUE - var currentTreatment: PumpHistoryEntry? = null - for (treatment in treatments) { - if (treatment!!.atechDateTime!! < dt) { - dt = treatment.atechDateTime!! - currentTreatment = treatment - } - } - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. Oldest entry found: time=%d, object=%s", dt, currentTreatment)) - return try { - val oldestEntryTime = DateTimeUtil.toGregorianCalendar(dt) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. oldestEntryTime: %s", DateTimeUtil.toString(oldestEntryTime))) - oldestEntryTime.add(Calendar.MINUTE, -2) - if (doubleBolusDebug) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "DoubleBolusDebug: getOldestTimestamp. oldestEntryTime (-2m): %s, timeInMillis=%d", DateTimeUtil.toString(oldestEntryTime), oldestEntryTime.timeInMillis)) - oldestEntryTime.timeInMillis - } catch (ex: Exception) { - aapsLogger.error("Problem decoding date from last record: $currentTreatment") - 8 // default return of 6 minutes - } - } private fun getTDDType(): PumpHistoryEntryType { return if (medtronicUtil.medtronicPumpModel == null) { @@ -1187,12 +987,14 @@ class MedtronicHistoryData @Inject constructor( } } + fun hasBasalProfileChanged(): Boolean { val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) aapsLogger.debug(LTag.PUMP, "hasBasalProfileChanged. Items: " + gson.toJson(filteredItems)) return filteredItems.size > 0 } + fun processLastBasalProfileChange(pumpType: PumpType?, mdtPumpStatus: MedtronicPumpStatus) { val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. Items: $filteredItems") @@ -1271,33 +1073,26 @@ class MedtronicHistoryData @Inject constructor( } private fun getFilteredItems(inList: MutableList?, entryTypes: Set?): MutableList { - - // aapsLogger.debug(LTag.PUMP, "InList: " + inList.size()); val outList: MutableList = mutableListOf() - if (inList != null && inList.size > 0) { + if (!inList.isNullOrEmpty()) { for (pumpHistoryEntry in inList) { - if (!isEmpty(entryTypes)) { - if (entryTypes!!.contains(pumpHistoryEntry.entryType)) { + if (entryTypes.isNullOrEmpty()) { + outList.add(pumpHistoryEntry) + } else { + if (entryTypes.contains(pumpHistoryEntry.entryType)) { outList.add(pumpHistoryEntry) } - } else { - outList.add(pumpHistoryEntry) } } } - - // aapsLogger.debug(LTag.PUMP, "OutList: " + outList.size()); return outList } - private fun isEmpty(entryTypes: Set?): Boolean { - return entryTypes.isNullOrEmpty() - //return entryTypes == null || entryTypes.size == 1 && entryTypes[0] == null - } private val logPrefix: String get() = "MedtronicHistoryData::" + companion object { /** * Double bolus debug. We seem to have small problem with double Boluses (or sometimes also missing boluses From 14b7895f201d10331f08a53237d965a3b3e5daea Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Thu, 13 May 2021 13:33:25 +0100 Subject: [PATCH 18/39] - final changes on Bolus (checking if bolus entry was changed in last 35 minutes) - added class for Dropbox support (not yet implemented) --- .../general/maintenance/DropboxUploader.kt | 8 ++++++++ .../comm/history/pump/PumpHistoryEntry.kt | 15 +++++++++++++-- .../pump/medtronic/data/MedtronicHistoryData.kt | 4 ++-- .../plugins/pump/medtronic/data/dto/BolusDTO.kt | 4 ++-- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt new file mode 100644 index 0000000000..cc7b28bc06 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt @@ -0,0 +1,8 @@ +package info.nightscout.androidaps.plugins.general.maintenance + +class DropboxUploader { + + + + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index a38ec2647e..83fbd2677d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -5,6 +5,7 @@ import com.google.gson.annotations.Expose import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryEntry +import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType import java.util.* @@ -113,8 +114,18 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { super.pumpId = pumpId } - fun hasBolusOrTBRDataChanged(entry: PumpHistoryEntry) : Boolean { - if (entryType!=null && (entryType!! == PumpHistoryEntryType.Bolus || entryType!! == PumpHistoryEntryType.TempBasalCombined)) { + fun hasBolusChanged(entry: PumpHistoryEntry) : Boolean { + if (entryType!=null && entryType == PumpHistoryEntryType.Bolus) { + val thisOne: BolusDTO? = this.decodedData!!["Object"]!! as BolusDTO? + val otherOne: BolusDTO? = entry.decodedData!!["Object"]!! as BolusDTO? + + if (thisOne==null || otherOne==null) { + return false; + } + + + + return false // TODO needs to be implemented } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 1c67eb3b92..587d70e461 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -88,10 +88,10 @@ class MedtronicHistoryData @Inject constructor( } else { val entryByPumpId = getEntryByPumpId(validEntry.pumpId!!) - // TODO not implemented - if (entryByPumpId!=null && entryByPumpId.hasBolusOrTBRDataChanged(validEntry)) { + if (entryByPumpId!=null && entryByPumpId.hasBolusChanged(validEntry)) { newEntries.add(validEntry) allHistory.remove(entryByPumpId) + allPumpIds.remove(validEntry.pumpId!!); } } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt index 671aae39a5..6e205248fe 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt @@ -57,7 +57,7 @@ class BolusDTO : PumpTimeStampedRecord() { return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2) } - val value: String? + val value: String get() = if (bolusType === PumpBolusType.Normal || bolusType === PumpBolusType.Audio) { getFormattedDecimal(deliveredAmount!!) } else if (bolusType === PumpBolusType.Extended) { @@ -77,7 +77,7 @@ class BolusDTO : PumpTimeStampedRecord() { return value } - override fun getFormattedDecimal(value: Double): String? { + override fun getFormattedDecimal(value: Double): String { return StringUtil.getFormatedValueUS(value, 2) } From a4be23d5ad9ecd62cb0390af79df9a909c49bd4d Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 15 May 2021 15:13:37 +0100 Subject: [PATCH 19/39] - added 2 loggings so that we can determine, what is the problem... --- .../plugins/pump/medtronic/data/MedtronicHistoryData.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 587d70e461..770b6b1b70 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -522,6 +522,8 @@ class MedtronicHistoryData @Inject constructor( if (!multiwave) { val entryWithTempId = findDbEntry(bolus, boluses) + aapsLogger.debug(LTag.PUMP, String.format("DD: entryWithTempId=%s", gson.toJson(entryWithTempId))) + if (entryWithTempId != null) { temporaryId = entryWithTempId.temporaryId pumpSyncStorage.removeBolusWithTemporaryId(temporaryId) @@ -647,6 +649,10 @@ class MedtronicHistoryData @Inject constructor( val tbrEntry = tempBasalProcessDTO.itemOne!!.getDecodedDataEntry("Object") as TempBasalPair if (entryWithTempId!=null) { + + aapsLogger.debug(LTag.PUMP, String.format("DD: tempIdEntry=%s, tbrEntry=%s, tempBasalProcessDTO=%s, pumpType=%s, serial=%s", + gson.toJson(entryWithTempId), gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!)) + val result = pumpSync.syncTemporaryBasalWithTempId( tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), tbrEntry.insulinRate, From f37b954ae604e8b6024f44cf0e9c278abad129c1 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 15 May 2021 20:24:23 +0100 Subject: [PATCH 20/39] - fixed events from history - added some additional logging for TBR handling - changed PumpSyncStorage to use xstream instead json --- core/build.gradle | 4 ++++ .../plugins/pump/common/sync/PumpSyncStorage.kt | 15 ++++++--------- .../pump/medtronic/data/MedtronicHistoryData.kt | 6 +++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 9b2d54be1e..94176e85dc 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -18,5 +18,9 @@ android { dependencies { implementation project(':database') + + implementation ('com.thoughtworks.xstream:xstream:1.4.7') { + exclude group: 'xmlpull', module: 'xmlpull' + } } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt index f89103cb35..99903e73cb 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.pump.common.sync import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.reflect.TypeToken +import com.thoughtworks.xstream.XStream import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger @@ -23,12 +24,13 @@ class PumpSyncStorage @Inject constructor( val aapsLogger: AAPSLogger ) { - val pumpSyncStorageKey: String = "pump_sync_storage" + val pumpSyncStorageKey: String = "pump_sync_storage_xstream" var pumpSyncStorage: MutableMap> = mutableMapOf() var TBR: String = "TBR" var BOLUS: String = "BOLUS" var storageInitialized: Boolean = false var gson: Gson = GsonBuilder().create() + var xstream: XStream = XStream() init { @@ -43,15 +45,10 @@ class PumpSyncStorage @Inject constructor( var loaded = false if (sp.contains(pumpSyncStorageKey)) { - val jsonData: String = sp.getString("pump_sync_storage", ""); + val jsonData: String = sp.getString(pumpSyncStorageKey, ""); if (!jsonData.isBlank()) { - - val pumpSyncStorageType: Type = object : TypeToken>>() {}.getType() - - val baseMap: MutableMap> = gson.fromJson(jsonData, pumpSyncStorageType) //as MutableMap> - - pumpSyncStorage = baseMap + pumpSyncStorage = xstream.fromXML(jsonData, MutableMap::class.java) as MutableMap> aapsLogger.debug(String.format("Loading Pump Sync Storage: boluses=%d, tbrs=%d.", pumpSyncStorage[BOLUS]!!.size, pumpSyncStorage[TBR]!!.size)) loaded = true @@ -67,7 +64,7 @@ class PumpSyncStorage @Inject constructor( fun saveStorage() { if (!isStorageEmpty()) { - sp.putString(pumpSyncStorageKey, gson.toJson(pumpSyncStorage)) + sp.putString(pumpSyncStorageKey, xstream.toXML(pumpSyncStorage)) aapsLogger.debug(String.format("Saving Pump Sync Storage: boluses=%d, tbrs=%d.", pumpSyncStorage[BOLUS]!!.size, pumpSyncStorage[TBR]!!.size)) } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 770b6b1b70..0affa3fe03 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -458,7 +458,7 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "insertTherapyEventIfNewWithTimestamp [date=%d, eventType=%d, pumpId=%d, pumpSerial=%s] - Result: %b", + aapsLogger.debug(LTag.PUMP, String.format(Locale.ROOT, "insertTherapyEventIfNewWithTimestamp [date=%d, eventType=%s, pumpId=%d, pumpSerial=%s] - Result: %b", historyRecord.atechDateTime!!, eventType, historyRecord.pumpId, medtronicPumpStatus.serialNumber!!, result)) @@ -646,8 +646,12 @@ class MedtronicHistoryData @Inject constructor( val entryWithTempId = findDbEntry(tempBasalProcessDTO.itemOne, tbrRecords) + aapsLogger.debug(LTag.PUMP, "DD: entryWithTempId: " + (if (entryWithTempId==null) "null" else entryWithTempId.toString())) + val tbrEntry = tempBasalProcessDTO.itemOne!!.getDecodedDataEntry("Object") as TempBasalPair + aapsLogger.debug(LTag.PUMP, String.format("DD: tbrEntry=%s, tempBasalProcessDTO=%s", gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO))) + if (entryWithTempId!=null) { aapsLogger.debug(LTag.PUMP, String.format("DD: tempIdEntry=%s, tbrEntry=%s, tempBasalProcessDTO=%s, pumpType=%s, serial=%s", From 7c32e2d3189355fd4b7d2ab5fc239c28c5809d87 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Mon, 17 May 2021 00:18:19 +0100 Subject: [PATCH 21/39] test deps --- gradle/test_dependencies.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle/test_dependencies.gradle b/gradle/test_dependencies.gradle index 3a484c419c..059f92d2a7 100644 --- a/gradle/test_dependencies.gradle +++ b/gradle/test_dependencies.gradle @@ -18,6 +18,7 @@ dependencies { androidTestImplementation "androidx.test:rules:$androidx_rules" androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' + testImplementation 'org.mockito:mockito-inline:2.8.47' } android { From cae5dab2851f0bece1a6f2b248224a701d63933c Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Mon, 17 May 2021 01:13:53 +0100 Subject: [PATCH 22/39] - restoring some files from medtronic -> core and from rileylink -> core (pump.common) --- .../androidaps/plugins/pump/common/PumpPluginAbstract.kt | 0 .../androidaps/plugins/pump/common/data/PumpStatus.kt | 0 .../androidaps/plugins/pump/common/defs/PumpDeviceState.kt | 0 .../androidaps/plugins/pump/common/defs/PumpDriverState.kt | 0 .../plugins/pump/common/defs/PumpHistoryEntryGroup.kt | 0 .../androidaps/plugins/pump/common/defs/PumpStatusType.kt | 0 .../androidaps/plugins/pump/common/defs/TempBasalPair.kt | 0 .../androidaps/plugins/pump/common/utils/ByteUtil.java | 0 .../androidaps/plugins/pump/common/utils/ProfileUtil.java | 0 .../androidaps/plugins/pump/common/utils/StringUtil.java | 0 .../androidaps/plugins/pump/common/utils/ThreadUtil.java | 0 .../androidaps/plugins/pump/medtronic/MedtronicFragment.kt | 1 - .../androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt | 3 --- .../plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt | 3 --- 14 files changed, 7 deletions(-) rename {medtronic => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt (100%) rename {medtronic => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt (100%) rename {medtronic => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt (100%) rename {medtronic => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java (100%) rename {rileylink => core}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java (100%) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt similarity index 100% rename from medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt similarity index 100% rename from medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt similarity index 100% rename from medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt similarity index 100% rename from medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java similarity index 100% rename from rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java rename to core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index c9d4009bf7..6e1130f3d8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -12,7 +12,6 @@ import dagger.android.support.DaggerFragment import info.nightscout.androidaps.events.EventExtendedBolusChange import info.nightscout.androidaps.events.EventPumpStatusChanged import info.nightscout.androidaps.events.EventTempBasalChange -import info.nightscout.androidaps.extensions.toStringFull import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.CommandQueueProvider import info.nightscout.androidaps.interfaces.PumpSync diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 281f315614..e97ca2d329 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -10,7 +10,6 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAlarm import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult -import info.nightscout.androidaps.db.Source import info.nightscout.androidaps.events.EventRefreshOverview import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.interfaces.PumpSync.TemporaryBasalType @@ -35,7 +34,6 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask -import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil @@ -47,7 +45,6 @@ import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile.Companion.getProfilesByHourToString import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfileEntry import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair -import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalProcessDTO import info.nightscout.androidaps.plugins.pump.medtronic.defs.* import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType.Companion.getSettings import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt index c1e08c7f18..ca5add4bbc 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt @@ -12,13 +12,10 @@ import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.DaggerActivity -import dagger.android.DispatchingAndroidInjector import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup -import info.nightscout.androidaps.plugins.pump.common.defs.PumpHistoryEntryGroup.Companion.getTranslatedList import info.nightscout.androidaps.plugins.pump.medtronic.R import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData -import info.nightscout.androidaps.plugins.pump.medtronic.databinding.MedtronicHistoryActivityBinding import info.nightscout.androidaps.utils.resources.ResourceHelper import java.util.* import javax.inject.Inject From 369c8a51802087bd28190bcfff8533963a144d0b Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Thu, 20 May 2021 11:43:05 +0100 Subject: [PATCH 23/39] - fixed NPE in case that we don't have any time from pump (shouldn't happen) --- .../plugins/pump/medtronic/data/MedtronicHistoryData.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 0affa3fe03..81662f3ce5 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -756,7 +756,11 @@ class MedtronicHistoryData @Inject constructor( } var proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) - proposedTime += (this.pumpTime!!.timeDifference * 1000) + + // pumpTime should never be null, but it can theoretically happen if reading of time from pump fails + if (this.pumpTime!=null) { + proposedTime += (this.pumpTime!!.timeDifference * 1000) + } val proposedTimeDiff : LongArray = longArrayOf(proposedTime-(2*60*1000), proposedTime+(2L*60L*1000L)) val tempEntriesList: MutableList = mutableListOf() From 76e6537b0f8e0f54f0ff502ade68b7e1b8053178 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Thu, 20 May 2021 13:09:51 +0100 Subject: [PATCH 24/39] - replaced null check with elvis op --- .../plugins/pump/medtronic/data/MedtronicHistoryData.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 81662f3ce5..b12cc3ed1c 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -758,9 +758,7 @@ class MedtronicHistoryData @Inject constructor( var proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) // pumpTime should never be null, but it can theoretically happen if reading of time from pump fails - if (this.pumpTime!=null) { - proposedTime += (this.pumpTime!!.timeDifference * 1000) - } + this.pumpTime?.let { proposedTime += (it.timeDifference * 1000) } val proposedTimeDiff : LongArray = longArrayOf(proposedTime-(2*60*1000), proposedTime+(2L*60L*1000L)) val tempEntriesList: MutableList = mutableListOf() From 4dcc8dc46f50ca080b991d58d9ccc458f9e9da53 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 10:26:32 +0100 Subject: [PATCH 25/39] - removed dropbox files --- app/build.gradle | 2 - .../general/maintenance/DropboxUploader.kt | 8 -- .../maintenance/dropbox/UploadFileTask.java | 72 ----------- .../maintenance/dropbox/UriHelpers.java | 119 ------------------ 4 files changed, 201 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java diff --git a/app/build.gradle b/app/build.gradle index fa64aff5fa..77277e2666 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -197,8 +197,6 @@ dependencies { /* Dagger2 - We are going to use dagger.android which includes * support for Activity and fragment injection so we need to include * the following dependencies */ - implementation 'com.dropbox.core:dropbox-core-sdk:2.1.1' - annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version" kapt "com.google.dagger:dagger-android-processor:$dagger_version" diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt deleted file mode 100644 index cc7b28bc06..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/DropboxUploader.kt +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.plugins.general.maintenance - -class DropboxUploader { - - - - -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java deleted file mode 100644 index 0bedd145a8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UploadFileTask.java +++ /dev/null @@ -1,72 +0,0 @@ -package info.nightscout.androidaps.plugins.general.maintenance.dropbox; - -import android.content.Context; -import android.net.Uri; -import android.os.AsyncTask; - -import com.dropbox.core.DbxException; -import com.dropbox.core.v2.DbxClientV2; -import com.dropbox.core.v2.files.FileMetadata; -import com.dropbox.core.v2.files.WriteMode; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -public class UploadFileTask extends AsyncTask { - - private final Context mContext; - private final DbxClientV2 mDbxClient; - private final Callback mCallback; - private Exception mException; - - public interface Callback { - void onUploadComplete(FileMetadata result); - void onError(Exception e); - } - - UploadFileTask(Context context, DbxClientV2 dbxClient, Callback callback) { - mContext = context; - mDbxClient = dbxClient; - mCallback = callback; - } - - @Override - protected void onPostExecute(FileMetadata result) { - super.onPostExecute(result); - if (mException != null) { - mCallback.onError(mException); - } else if (result == null) { - mCallback.onError(null); - } else { - mCallback.onUploadComplete(result); - } - } - - @Override - protected FileMetadata doInBackground(String... params) { - String localUri = params[0]; - File localFile = UriHelpers.getFileForUri(mContext, Uri.parse(localUri)); - - if (localFile != null) { - String remoteFolderPath = params[1]; - - // Note - this is not ensuring the name is a valid dropbox file name - String remoteFileName = localFile.getName(); - - try (InputStream inputStream = new FileInputStream(localFile)) { - return mDbxClient.files().uploadBuilder(remoteFolderPath + "/" + remoteFileName) - .withMode(WriteMode.OVERWRITE) - .uploadAndFinish(inputStream); - } catch (DbxException | IOException e) { - mException = e; - } - } - - return null; - } - - - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java deleted file mode 100644 index 67a1d9c0dd..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/dropbox/UriHelpers.java +++ /dev/null @@ -1,119 +0,0 @@ -package info.nightscout.androidaps.plugins.general.maintenance.dropbox; - -import android.content.ContentUris; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; - -import java.io.File; - -public class UriHelpers { - - private UriHelpers() {} - - /** - * Get the file path for a uri. This is a convoluted way to get the path for an Uri created using the - * StorageAccessFramework. This in no way is the official way to do this but there does not seem to be a better - * way to do this at this point. It is taken from https://github.com/iPaulPro/aFileChooser. - * - * @param context The context of the application - * @param uri The uri of the saved file - * @return The file with path pointing to the saved file. It can return null if we can't resolve the uri properly. - */ - public static File getFileForUri(final Context context, final Uri uri) { - String path = null; - // DocumentProvider - if (DocumentsContract.isDocumentUri(context, uri)) { - // ExternalStorageProvider - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - path = Environment.getExternalStorageDirectory() + "/" + split[1]; - } - } else if (isDownloadsDocument(uri)) { - // DownloadsProvider - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris - .withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - - path = getDataColumn(context, contentUri, null, null); - } else if (isMediaDocument(uri)) { - // MediaProvider - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[] { - split[1] - }; - - path = getDataColumn(context, contentUri, selection, selectionArgs); - } - } else if ("content".equalsIgnoreCase(uri.getScheme())) { - // MediaStore (and general) - path = getDataColumn(context, uri, null, null); - } else if ("file".equalsIgnoreCase(uri.getScheme())) { - // File - path = uri.getPath(); - } - - if (path != null) { - return new File(path); - } - return null; - } - - private static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, - null); - if (cursor != null && cursor.moveToFirst()) { - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } finally { - if (cursor != null) { - cursor.close(); - } - } - return null; - } - - - private static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - private static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - private static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } - -} From 561d255c3416252fb0a51ca9647b056d441e1fed Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 10:46:13 +0100 Subject: [PATCH 26/39] - removed mdt tag from branch --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 77277e2666..ccf044fa41 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,7 +111,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "2.8.2.1-meallink-mdt" + version "2.8.2.1" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' From d50ef68d33bb6c25d25ed2480161a68fea976fac Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 10:56:01 +0100 Subject: [PATCH 27/39] - removed some comments from MedtronicHistoryData --- .../medtronic/data/MedtronicHistoryData.kt | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index b12cc3ed1c..2fcc1a7499 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -12,7 +12,6 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry -import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryBolus import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage @@ -44,10 +43,6 @@ import javax.inject.Singleton // all times that time changed (TZ, DST, etc.). Data needs to be returned in batches (time_changed batches, so that we can // handle it. It would help to assign sort_ids to items (from oldest (1) to newest (x) // -// TODO New Database changes: -// + we need to read 35 minutes from history on each read -// - compare all read items if they have the same amounts, if not send them back to database changes. -// - we need to remove and invalidate TBRs that are cancels from PumpSyncStorage @Suppress("DEPRECATION") @Singleton class MedtronicHistoryData @Inject constructor( @@ -105,13 +100,6 @@ class MedtronicHistoryData @Inject constructor( .findFirst() return if (findFirst.isPresent()) findFirst.get() else null - // - // for (pumpHistoryEntry in allHistory) { - // if (pumpHistoryEntry.pumpId == pumpId) { - // return pumpHistoryEntry - // } - // } - // return null } private fun showLogs(header: String?, data: String) { @@ -127,10 +115,6 @@ class MedtronicHistoryData @Inject constructor( } } - // fun getAllHistory(): List { - // return allHistory - // } - fun filterNewEntries() { val newHistory2: MutableList = mutableListOf() var tbrs: MutableList = mutableListOf() @@ -211,9 +195,7 @@ class MedtronicHistoryData @Inject constructor( allPumpIds.add(pumpHistoryEntry.pumpId!!) } } - // if (pheLast == null) // if we don't have any valid record we don't do the filtering and setting - // return - //setLastHistoryRecordTime(pheLast.atechDateTime) + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.atechDateTime!!) var dt: LocalDateTime? = null try { @@ -986,8 +968,10 @@ class MedtronicHistoryData @Inject constructor( return if (medtronicUtil.medtronicPumpModel == null) { PumpHistoryEntryType.EndResultTotals } else when (medtronicUtil.medtronicPumpModel) { - MedtronicDeviceType.Medtronic_515, MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 - MedtronicDeviceType.Medtronic_522, MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 + MedtronicDeviceType.Medtronic_515, + MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 + MedtronicDeviceType.Medtronic_522, + MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 MedtronicDeviceType.Medtronic_523_Revel, MedtronicDeviceType.Medtronic_723_Revel, MedtronicDeviceType.Medtronic_554_Veo, From 59a3bf88834a8433676a78e893ee5694166f0949 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 13:03:33 +0100 Subject: [PATCH 28/39] - minor kotlin refactorings removed some !! and refactored some code to that effect - removed non aapsLogger --- .../pump/medtronic/MedtronicPumpPlugin.kt | 7 +- .../MedtronicHistoryDecoderInterface.kt | 2 +- .../comm/history/MedtronicHistoryEntry.kt | 31 +++-- .../comm/history/cgms/CGMSHistoryEntry.kt | 2 +- .../cgms/MedtronicCGMSHistoryDecoder.kt | 19 ++-- .../pump/MedtronicPumpHistoryDecoder.kt | 39 ++++--- .../comm/history/pump/PumpHistoryEntry.kt | 30 +++-- .../medtronic/data/MedtronicHistoryData.kt | 107 +++++++++--------- .../medtronic/data/dto/TempBasalProcessDTO.kt | 17 ++- 9 files changed, 119 insertions(+), 135 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index e97ca2d329..2f46965223 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -869,7 +869,7 @@ class MedtronicPumpPlugin @Inject constructor( if (latestEntry == null) // no new history to read return lastPumpHistoryEntry = latestEntry - sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.atechDateTime!!) + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, latestEntry.atechDateTime) if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: History: valid=" + historyResult.validEntries.size + ", unprocessed=" + historyResult.unprocessedEntries.size) medtronicHistoryData.addNewHistory(historyResult) medtronicHistoryData.filterNewEntries() @@ -1153,13 +1153,10 @@ class MedtronicPumpPlugin @Inject constructor( MedtronicCustomActionType.ResetRileyLinkConfiguration -> { serviceTaskExecutor.startTask(ResetRileyLinkConfigurationTask(injector)) } - - else -> { - } } } - override fun timezoneOrDSTChanged(changeType: TimeChangeType) { + override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) { aapsLogger.warn(LTag.PUMP, logPrefix + "Time or TimeZone changed. ") hasTimeDateOrTimeZoneChanged = true } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt index 8b2ee5d2b0..fa45bf1400 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoderInterface.kt @@ -6,5 +6,5 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history interface MedtronicHistoryDecoderInterface { fun decodeRecord(record: T): RecordDecodeStatus? - fun createRecords(dataClear: MutableList): MutableList + fun createRecords(dataClearInput: MutableList): MutableList } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index e8b69a46ff..3910bab135 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -37,14 +37,15 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { get() = field @Expose - var atechDateTime: Long? = null + var atechDateTime: Long = 0L get() = field set(value) { field = value + DT = DateTimeUtil.toString(value) } @Expose - var decodedData: MutableMap? = null + var decodedData: MutableMap = mutableMapOf() get() = field /** @@ -112,10 +113,10 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { get() = if (DT == null) "Unknown" else DT!! val decodedDataAsString: String - get() = if (decodedData == null) if (isNoDataEntry) "No data" else "" else decodedData.toString() + get() = if (decodedData.size == 0) if (isNoDataEntry) "No data" else "" else decodedData.toString() fun hasData(): Boolean { - return decodedData != null || isNoDataEntry || entryTypeName == "UnabsorbedInsulin" + return decodedData.size == 0 || isNoDataEntry || entryTypeName == "UnabsorbedInsulin" } val isNoDataEntry: Boolean @@ -126,11 +127,11 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { // } fun getDecodedDataEntry(key: String?): Any? { - return if (decodedData != null) decodedData!![key] else null + return if (decodedData.containsKey(key)) decodedData[key] else null } fun hasDecodedDataEntry(key: String?): Boolean { - return decodedData!!.containsKey(key) + return decodedData.containsKey(key) } fun showRaw(): Boolean { @@ -148,9 +149,9 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { override fun toString(): String { val sb = StringBuilder() - if (DT == null) { - Log.e("", "DT is null. RawData=" + ByteUtil.getHex(rawData)) - } + // if (DT == null) { + // Log.e("", "DT is null. RawData=" + ByteUtil.getHex(rawData)) + // } sb.append(toStringStart) sb.append(", DT: " + if (DT == null) "null" else StringUtil.getStringInLength(DT, 19)) sb.append(", length=") @@ -208,14 +209,8 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { return ByteUtil.convertUnsignedByteToInt(rawData!![index]) } - fun setAtechDateTime(dt: Long) { - atechDateTime = dt - DT = DateTimeUtil.toString(atechDateTime!!) - } - - fun addDecodedData(key: String, value: Any?) { - if (decodedData == null) decodedData = HashMap() - decodedData!![key] = value + fun addDecodedData(key: String, value: Any) { + decodedData.put(key, value) } fun toShortString(): String { @@ -227,7 +222,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { } fun containsDecodedData(key: String?): Boolean { - return if (decodedData == null) false else decodedData!!.containsKey(key) + return decodedData.containsKey(key) } // if we extend to CGMS this need to be changed back // public abstract PumpHistoryEntryType getEntryType(); } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt index 670a17ee91..f35a65d4f5 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt @@ -50,6 +50,6 @@ class CGMSHistoryEntry : MedtronicHistoryEntry() { + StringUtils.leftPad("" + opCode, 3) + ", 0x" + ByteUtil.getCorrectHexValue(opCode!!) + "]") fun setDateTime(timeStamp: LocalDateTime, getIndex: Int) { - setAtechDateTime(DateTimeUtil.toATechDate(timeStamp.plusMinutes(getIndex * 5))) + atechDateTime = (DateTimeUtil.toATechDate(timeStamp.plusMinutes(getIndex * 5))) } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index 7ce380ca4b..424c269986 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -27,7 +27,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() return try { decodeRecordInternal(record) } catch (ex: Exception) { - LOG.error(" Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) + aapsLogger.error(LTag.PUMPCOMM," Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) RecordDecodeStatus.Error } } @@ -81,7 +81,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() entryType = getByCode(opCode) if (entryType === CGMSHistoryEntryType.None) { unknownOpCodes!![opCode] = opCode - LOG.warn("GlucoseHistoryEntry with unknown code: $opCode") + aapsLogger.warn(LTag.PUMPCOMM, "GlucoseHistoryEntry with unknown code: $opCode") val pe = CGMSHistoryEntry() pe.setEntryType(CGMSHistoryEntryType.None) pe.opCode = opCode.toByte() @@ -112,14 +112,14 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() } while (counter < dataClear.size) outList.reverse() val reversedOutList = outList // reverseList(outList, CGMSHistoryEntry::class.java) - var timeStamp: Long? = null + //var timeStamp: Long? = null var dateTime: LocalDateTime? = null var getIndex = 0 for (entry in reversedOutList) { decodeRecord(entry) if (entry.hasTimeStamp()) { - timeStamp = entry.atechDateTime - dateTime = DateTimeUtil.toLocalDateTime(timeStamp!!) + //timeStamp = entry.atechDateTime + dateTime = DateTimeUtil.toLocalDateTime(entry.atechDateTime) getIndex = 0 } else if (entry.entryType == CGMSHistoryEntryType.GlucoseSensorData) { getIndex++ @@ -127,7 +127,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() } else { if (dateTime != null) entry.setDateTime(dateTime, getIndex) } - LOG.debug("Record: {}", entry) + aapsLogger.debug(LTag.PUMPCOMM,"Record: {}", entry) } return reversedOutList } @@ -168,10 +168,10 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() return if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.MinuteSpecific) { val atechDateTime = DateTimeUtil.toATechDate(parseYear(data!![3].toInt()), parseMonths(data[0].toInt(), data[1].toInt()), parseDay(data[2].toInt()), parseHours(data[0].toInt()), parseMinutes(data[1].toInt()), 0) - entry.setAtechDateTime(atechDateTime) + entry.atechDateTime = atechDateTime atechDateTime } else if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.SecondSpecific) { - LOG.warn("parseDate for SecondSpecific type is not implemented.") + aapsLogger.warn(LTag.PUMPCOMM,"parseDate for SecondSpecific type is not implemented.") throw RuntimeException() // return null; } else null @@ -268,7 +268,4 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() showStatistics() } - companion object { - private val LOG: Logger = getLogger1("MedtronicCGMSHistoryDecoder") - } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index 452faa705d..932127f5c9 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -6,7 +6,6 @@ import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntryType.Companion.getByCode import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BasalProfile import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.BolusDTO @@ -34,22 +33,22 @@ class MedtronicPumpHistoryDecoder @Inject constructor( medtronicUtil: MedtronicUtil ) : MedtronicHistoryDecoder() { - private var tbrPreviousRecord: PumpHistoryEntry? = null + //private var tbrPreviousRecord: PumpHistoryEntry? = null private var changeTimeRecord: PumpHistoryEntry? = null - override fun createRecords(dataClear: MutableList): MutableList { + override fun createRecords(dataClearInput: MutableList): MutableList { prepareStatistics() var counter = 0 var record = 0 var incompletePacket: Boolean val outList: MutableList = mutableListOf() var skipped: String? = null - if (dataClear.size == 0) { + if (dataClearInput.size == 0) { aapsLogger.error(LTag.PUMPBTCOMM, "Empty page.") return outList } do { - val opCode: Int = dataClear[counter].toInt() + val opCode: Int = dataClearInput[counter].toInt() var special = false incompletePacket = false var skippedRecords = false @@ -79,13 +78,13 @@ class MedtronicPumpHistoryDecoder @Inject constructor( listRawData.add(opCode.toByte()) if (entryType === PumpHistoryEntryType.UnabsorbedInsulin || entryType === PumpHistoryEntryType.UnabsorbedInsulin512) { - val elements: Int = dataClear[counter].toInt() + val elements: Int = dataClearInput[counter].toInt() listRawData.add(elements.toByte()) counter++ val els = getUnsignedInt(elements) for (k in 0 until els - 2) { if (counter < 1022) { - listRawData.add(dataClear[counter]) + listRawData.add(dataClearInput[counter]) counter++ } } @@ -93,7 +92,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } else { for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel!!) - 1) { try { - listRawData.add(dataClear[counter]) + listRawData.add(dataClearInput[counter]) counter++ } catch (ex: Exception) { aapsLogger.error(LTag.PUMPBTCOMM, "OpCode: " + ByteUtil.shortHexString(opCode.toByte()) + ", Invalid package: " @@ -126,7 +125,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( outList.add(pe) } } - } while (counter < dataClear.size) + } while (counter < dataClearInput.size) return outList } @@ -272,9 +271,9 @@ class MedtronicPumpHistoryDecoder @Inject constructor( dto.bolusTotal = ((body[12].toInt() shl 8) + body[13]) / bolusStrokes } else { dto.bloodGlucose = (body.get(1) and 0x0F).toInt() shl 8 or entry.head!!.get(0).toInt() - dto.carbs = body.get(0).toInt() - dto.carbRatio = body.get(2).toFloat() - dto.insulinSensitivity = body.get(3).toFloat() + dto.carbs = body[0].toInt() + dto.carbRatio = body[2].toFloat() + dto.insulinSensitivity = body[3].toFloat() dto.bgTargetLow = body.get(4).toInt() dto.bgTargetHigh = body.get(12).toInt() dto.bolusTotal = body.get(11) / bolusStrokes @@ -283,10 +282,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( dto.bolusTotal = body.get(11) / bolusStrokes dto.correctionEstimate = (body.get(7) + (body.get(5) and 0x0F)) / bolusStrokes } - if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { + if (dto.bloodGlucose < 0) { dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.toByte()) } - dto.atechDateTime = entry.atechDateTime!! + dto.atechDateTime = entry.atechDateTime entry.addDecodedData("Object", dto) entry.displayableValue = dto.displayableValue return RecordDecodeStatus.OK @@ -306,10 +305,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( dto.unabsorbedInsulin = body.get(9) / bolusStrokes dto.bolusTotal = body.get(11) / bolusStrokes dto.bgTargetHigh = dto.bgTargetLow - if (dto.bloodGlucose != null && dto.bloodGlucose < 0) { + if (dto.bloodGlucose < 0) { dto.bloodGlucose = ByteUtil.convertUnsignedByteToInt(dto.bloodGlucose.toByte()) } - dto.atechDateTime = entry.atechDateTime!! + dto.atechDateTime = entry.atechDateTime entry.addDecodedData("Object", dto) entry.displayableValue = dto.displayableValue return RecordDecodeStatus.OK @@ -371,7 +370,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( bolus.duration = ByteUtil.asUINT8(data.get(2)) * 30 } bolus.bolusType = if (bolus.duration != null && bolus.duration!! > 0) PumpBolusType.Extended else PumpBolusType.Normal - bolus.atechDateTime = entry.atechDateTime!! + bolus.atechDateTime = entry.atechDateTime entry.addDecodedData("Object", bolus) entry.displayableValue = bolus.displayableValue } @@ -431,9 +430,9 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val dayOfMonth: Int = (dt.get(3) and 0x1F).toInt() val year = fix2DigitYear((dt.get(4) and 0x3F.toByte()).toInt()) // Assuming this is correct, need to verify. Otherwise this will be // a problem in 2016. - entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)) + entry.atechDateTime = DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds) } else if (entry.dateTimeLength == 2) { - val low = ByteUtil.asUINT8(dt.get(0)) and 0x1F + //val low = ByteUtil.asUINT8(dt.get(0)) and 0x1F val mhigh = ByteUtil.asUINT8(dt.get(0)) and 0xE0 shr 4 val mlow = ByteUtil.asUINT8(dt.get(1)) and 0x80 shr 7 val month = mhigh + mlow @@ -454,7 +453,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( minutes = 59 seconds = 59 } - entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds)) + entry.atechDateTime = DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds) } else { aapsLogger.warn(LTag.PUMPBTCOMM, "Unknown datetime format: " + entry.dateTimeLength) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index 83fbd2677d..83c1ab2f10 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -41,11 +41,11 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { sizes[0] = entryType.getHeadLength(medtronicDeviceType) sizes[1] = entryType.dateLength sizes[2] = entryType.getBodyLength(medtronicDeviceType) - if (this.entryType != null && atechDateTime != null) generatePumpId() + if (this.entryType != null && atechDateTime != 0L) generatePumpId() } private fun generatePumpId() : Long { - return entryType!!.code + atechDateTime!! * 1000L + return entryType!!.code + atechDateTime * 1000L } override val toStringStart: String @@ -91,16 +91,16 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { // return this.dateTime.isAfter(dateTimeIn); // } fun isAfter(atechDateTime: Long): Boolean { - if (this.atechDateTime == null) { - Log.e("PumpHistoryEntry", "Date is null. Show object: " + toString()) + if (this.atechDateTime == 0L) { + // Log.e("PumpHistoryEntry", "Date is null. Show object: " + toString()) return false // FIXME shouldn't happen } - return atechDateTime < this.atechDateTime!! + return atechDateTime < this.atechDateTime } class Comparator : java.util.Comparator { override fun compare(o1: PumpHistoryEntry, o2: PumpHistoryEntry): Int { - val data = (o2.atechDateTime!! - o1.atechDateTime!!).toInt() + val data = (o2.atechDateTime - o1.atechDateTime).toInt() return if (data != 0) data else o2.entryType!!.code - o1.entryType!!.code } } @@ -116,17 +116,13 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { fun hasBolusChanged(entry: PumpHistoryEntry) : Boolean { if (entryType!=null && entryType == PumpHistoryEntryType.Bolus) { - val thisOne: BolusDTO? = this.decodedData!!["Object"]!! as BolusDTO? - val otherOne: BolusDTO? = entry.decodedData!!["Object"]!! as BolusDTO? - - if (thisOne==null || otherOne==null) { - return false; - } - - - - - return false // TODO needs to be implemented + val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO + + if (entry.entryType!=null && entry.entryType == PumpHistoryEntryType.Bolus) { + val otherOne: BolusDTO = entry.decodedData["Object"] as BolusDTO + return (thisOne.value.equals(otherOne.value)) + } else + return false } return false diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 2fcc1a7499..cb34b8962b 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -133,7 +133,7 @@ class MedtronicHistoryData @Inject constructor( newHistory2.add(pumpHistoryEntry) } else { if (type === PumpHistoryEntryType.EndResultTotals) { - if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.atechDateTime!!)) { + if (!DateTimeUtil.isSameDay(atechDate, pumpHistoryEntry.atechDateTime)) { newHistory2.add(pumpHistoryEntry) } } else { @@ -168,7 +168,7 @@ class MedtronicHistoryData @Inject constructor( for (bolusEstimate in bolusEstimates) { for (bolus in boluses) { if (bolusEstimate.atechDateTime == bolus.atechDateTime) { - bolus.addDecodedData("Estimate", bolusEstimate.decodedData!!["Object"]) + bolus.addDecodedData("Estimate", bolusEstimate.decodedData["Object"]!!) } } } @@ -180,7 +180,7 @@ class MedtronicHistoryData @Inject constructor( // find last entry for (pumpHistoryEntry in newHistory) { - if (pumpHistoryEntry.atechDateTime != null && pumpHistoryEntry.isAfter(pheLast.atechDateTime!!)) { + if (pumpHistoryEntry.atechDateTime != 0L && pumpHistoryEntry.isAfter(pheLast.atechDateTime)) { pheLast = pumpHistoryEntry } } @@ -196,10 +196,10 @@ class MedtronicHistoryData @Inject constructor( } } - sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.atechDateTime!!) + sp.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry, pheLast.atechDateTime) var dt: LocalDateTime? = null try { - dt = DateTimeUtil.toLocalDateTime(pheLast.atechDateTime!!) + dt = DateTimeUtil.toLocalDateTime(pheLast.atechDateTime) } catch (ex: Exception) { aapsLogger.error("Problem decoding date from last record: $pheLast") } @@ -396,9 +396,9 @@ class MedtronicHistoryData @Inject constructor( // so skip the prime entry if it was not a fixed prime continue } - if (primeRecord.atechDateTime!! > maxAllowedTimeInPast) { - if (lastPrimeRecordTime < primeRecord.atechDateTime!!) { - lastPrimeRecordTime = primeRecord.atechDateTime!! + if (primeRecord.atechDateTime > maxAllowedTimeInPast) { + if (lastPrimeRecordTime!=0L && lastPrimeRecordTime < primeRecord.atechDateTime) { + lastPrimeRecordTime = primeRecord.atechDateTime lastPrimeRecord = primeRecord } } @@ -410,14 +410,14 @@ class MedtronicHistoryData @Inject constructor( } } - private fun processRewind(rewindRecords: List) { + private fun processRewind(rewindRecords: List) { val maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(GregorianCalendar(), -30) var lastRewindRecordTime = 0L var lastRewindRecord: PumpHistoryEntry? = null for (rewindRecord in rewindRecords) { - if (rewindRecord!!.atechDateTime!! > maxAllowedTimeInPast) { - if (lastRewindRecordTime < rewindRecord.atechDateTime!!) { - lastRewindRecordTime = rewindRecord.atechDateTime!! + if (rewindRecord.atechDateTime > maxAllowedTimeInPast) { + if (lastRewindRecordTime < rewindRecord.atechDateTime) { + lastRewindRecordTime = rewindRecord.atechDateTime lastRewindRecord = rewindRecord } } @@ -434,17 +434,17 @@ class MedtronicHistoryData @Inject constructor( val lastPrimeFromAAPS = sp.getLong(eventSP, 0L) if (historyRecord.atechDateTime != lastPrimeFromAAPS) { var result = pumpSync.insertTherapyEventIfNewWithTimestamp( - DateTimeUtil.toMillisFromATD(historyRecord.atechDateTime!!), + DateTimeUtil.toMillisFromATD(historyRecord.atechDateTime), eventType, null, historyRecord.pumpId, medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ROOT, "insertTherapyEventIfNewWithTimestamp [date=%d, eventType=%s, pumpId=%d, pumpSerial=%s] - Result: %b", - historyRecord.atechDateTime!!, eventType, historyRecord.pumpId, + historyRecord.atechDateTime, eventType, historyRecord.pumpId, medtronicPumpStatus.serialNumber!!, result)) - sp.putLong(eventSP, historyRecord.atechDateTime!!) + sp.putLong(eventSP, historyRecord.atechDateTime) } } @@ -456,10 +456,10 @@ class MedtronicHistoryData @Inject constructor( tdds.size, gson.toJson(tdds))) for (tdd in tdds) { - val totalsDTO = tdd.decodedData!!["Object"] as DailyTotalsDTO + val totalsDTO = tdd.decodedData["Object"] as DailyTotalsDTO pumpSync.createOrUpdateTotalDailyDose( - DateTimeUtil.toMillisFromATD(tdd.atechDateTime!!), + DateTimeUtil.toMillisFromATD(tdd.atechDateTime), totalsDTO.insulinBolus, totalsDTO.insulinBasal!!, totalsDTO.insulinTotal, @@ -484,7 +484,7 @@ class MedtronicHistoryData @Inject constructor( for (bolus in entryList) { - val bolusDTO = bolus.decodedData!!["Object"]!! as BolusDTO + val bolusDTO = bolus.decodedData["Object"] as BolusDTO var type: DetailedBolusInfo.BolusType = DetailedBolusInfo.BolusType.NORMAL var multiwave = false @@ -516,7 +516,7 @@ class MedtronicHistoryData @Inject constructor( if (temporaryId!=null) { val result = pumpSync.syncBolusWithTempId( - tryToGetByLocalTime(bolus.atechDateTime!!), + tryToGetByLocalTime(bolus.atechDateTime), deliveredAmount, temporaryId, type, @@ -525,11 +525,11 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithTempId [date=%d, temporaryId=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", - bolus.atechDateTime!!, temporaryId, bolus.pumpId, deliveredAmount, + bolus.atechDateTime, temporaryId, bolus.pumpId, deliveredAmount, medtronicPumpStatus.serialNumber!!, result)) } else { val result = pumpSync.syncBolusWithPumpId( - tryToGetByLocalTime(bolus.atechDateTime!!), + tryToGetByLocalTime(bolus.atechDateTime), deliveredAmount, type, bolus.pumpId!!, @@ -537,7 +537,7 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithPumpId [date=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", - bolus.atechDateTime!!, bolus.pumpId, deliveredAmount, + bolus.atechDateTime, bolus.pumpId, deliveredAmount, medtronicPumpStatus.serialNumber!!, result)) } @@ -550,7 +550,7 @@ class MedtronicHistoryData @Inject constructor( val durationMs : Long = bolusDTO.duration!! * 60L * 1000L val result = pumpSync.syncExtendedBolusWithPumpId( - tryToGetByLocalTime(bolus.atechDateTime!!), + tryToGetByLocalTime(bolus.atechDateTime), bolusDTO.deliveredAmount!!, durationMs, false, @@ -559,17 +559,17 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncExtendedBolusWithPumpId [date=%d, amount=%.2f, duration=%d, pumpId=%d, pumpSerial=%s, multiwave=%b] - Result: %b", - bolus.atechDateTime!!, bolusDTO.deliveredAmount!!, bolusDTO.duration, bolus.pumpId, + bolus.atechDateTime, bolusDTO.deliveredAmount!!, bolusDTO.duration, bolus.pumpId, medtronicPumpStatus.serialNumber!!, isMultiwave, result)) } private fun addCarbs(bolus: PumpHistoryEntry) { if (bolus.containsDecodedData("Estimate")) { - val bolusWizard = bolus.decodedData!!["Estimate"] as BolusWizardDTO + val bolusWizard = bolus.decodedData["Estimate"] as BolusWizardDTO pumpSyncStorage.addCarbs(PumpDbEntryCarbs( - tryToGetByLocalTime(bolus.atechDateTime!!), + tryToGetByLocalTime(bolus.atechDateTime), bolusWizard.carbs.toDouble(), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!, @@ -615,9 +615,9 @@ class MedtronicHistoryData @Inject constructor( if (processDTO != null) { processList.add(processDTO) } - processDTO = TempBasalProcessDTO() - processDTO.itemOne = treatment - processDTO.processOperation = TempBasalProcessDTO.Operation.Add + processDTO = TempBasalProcessDTO( + itemOne= treatment, + processOperation = TempBasalProcessDTO.Operation.Add) } } if (processDTO != null) { @@ -630,7 +630,7 @@ class MedtronicHistoryData @Inject constructor( aapsLogger.debug(LTag.PUMP, "DD: entryWithTempId: " + (if (entryWithTempId==null) "null" else entryWithTempId.toString())) - val tbrEntry = tempBasalProcessDTO.itemOne!!.getDecodedDataEntry("Object") as TempBasalPair + val tbrEntry = tempBasalProcessDTO.itemOne.getDecodedDataEntry("Object") as TempBasalPair aapsLogger.debug(LTag.PUMP, String.format("DD: tbrEntry=%s, tempBasalProcessDTO=%s", gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO))) @@ -737,7 +737,7 @@ class MedtronicHistoryData @Inject constructor( return null } - var proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime!!) + var proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime) // pumpTime should never be null, but it can theoretically happen if reading of time from pump fails this.pumpTime?.let { proposedTime += (it.timeDifference * 1000) } @@ -793,18 +793,19 @@ class MedtronicHistoryData @Inject constructor( for (tempBasalProcess in tempBasalProcessList) { val result = pumpSync.syncTemporaryBasalWithPumpId( - tryToGetByLocalTime(tempBasalProcess.itemOne!!.atechDateTime!!), + tryToGetByLocalTime(tempBasalProcess.itemOne.atechDateTime), 0.0, tempBasalProcess.duration * 60 * 1000L, true, PumpSync.TemporaryBasalType.PUMP_SUSPEND, - tempBasalProcess.itemOne!!.pumpId!!, + tempBasalProcess.itemOne.pumpId!!, medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "processSuspends::syncTemporaryBasalWithPumpId [date=%d, rate=%.2f, duration=%d, pumpId=%d, pumpSerial=%s] - Result: %b", - tempBasalProcess.itemOne!!.atechDateTime!!, 0.0, tempBasalProcess.duration, tempBasalProcess.itemOne!!.pumpId!!, + tempBasalProcess.itemOne.atechDateTime, 0.0, tempBasalProcess.duration, tempBasalProcess.itemOne.pumpId!!, medtronicPumpStatus.serialNumber!!, result)) + } } @@ -862,11 +863,11 @@ class MedtronicHistoryData @Inject constructor( Collections.reverse(filtered2Items) var i = 0 while (i < filtered2Items.size) { - val dto = TempBasalProcessDTO() - dto.itemOne = filtered2Items[i] - dto.itemTwo = filtered2Items[i + 1] - dto.processOperation = TempBasalProcessDTO.Operation.Add - outList.add(dto) + outList.add(TempBasalProcessDTO( + itemOne= filtered2Items[i], + itemTwo= filtered2Items[i + 1], + processOperation = TempBasalProcessDTO.Operation.Add)) + i += 2 } } @@ -925,20 +926,20 @@ class MedtronicHistoryData @Inject constructor( } showLogs("NoDeliveryRewindPrimeRecords: Records to evaluate: ", gson.toJson(tempData)) var items: MutableList = getFilteredItems(tempData, PumpHistoryEntryType.Prime) - val processDTO = TempBasalProcessDTO() - processDTO.itemTwo = items[0] + var itemTwo = items[0] items = getFilteredItems(tempData, PumpHistoryEntryType.NoDeliveryAlarm) if (items.size > 0) { - processDTO.itemOne = items[items.size - 1] - processDTO.processOperation = TempBasalProcessDTO.Operation.Add - outList.add(processDTO) + outList.add(TempBasalProcessDTO( + itemOne=items[items.size - 1], + itemTwo= itemTwo, + processOperation=TempBasalProcessDTO.Operation.Add)) return outList } items = getFilteredItems(tempData, PumpHistoryEntryType.Rewind) if (items.size > 0) { - processDTO.itemOne = items[0] - processDTO.processOperation = TempBasalProcessDTO.Operation.Add - outList.add(processDTO) + outList.add(TempBasalProcessDTO( + itemOne=items[0], + processOperation=TempBasalProcessDTO.Operation.Add)) return outList } return outList @@ -991,8 +992,8 @@ class MedtronicHistoryData @Inject constructor( } - fun processLastBasalProfileChange(pumpType: PumpType?, mdtPumpStatus: MedtronicPumpStatus) { - val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) + fun processLastBasalProfileChange(pumpType: PumpType, mdtPumpStatus: MedtronicPumpStatus) { + val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. Items: $filteredItems") var newProfile: PumpHistoryEntry? = null var lastDate: Long? = null @@ -1000,16 +1001,16 @@ class MedtronicHistoryData @Inject constructor( newProfile = filteredItems[0] } else if (filteredItems.size > 1) { for (filteredItem in filteredItems) { - if (lastDate == null || lastDate < filteredItem!!.atechDateTime!!) { + if (lastDate == null || lastDate < filteredItem.atechDateTime) { newProfile = filteredItem - lastDate = newProfile!!.atechDateTime + lastDate = newProfile.atechDateTime } } } if (newProfile != null) { aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. item found, setting new basalProfileLocally: $newProfile") - val basalProfile = newProfile.decodedData!!["Object"] as BasalProfile? - mdtPumpStatus.basalsByHour = basalProfile!!.getProfilesByHour(pumpType!!) + val basalProfile = newProfile.decodedData["Object"] as BasalProfile + mdtPumpStatus.basalsByHour = basalProfile.getProfilesByHour(pumpType) } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt index 52e6152b38..7fc26b2355 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt @@ -3,24 +3,23 @@ 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 { - var itemOne: PumpHistoryEntry? = null - var itemTwo: PumpHistoryEntry? = null - var processOperation = Operation.None +class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry, + var itemTwo: PumpHistoryEntry? = null, + var processOperation: Operation = Operation.None) { var cancelPresent: Boolean = false val atechDateTime: Long - get() = if (itemOne==null) 0L else itemOne!!.atechDateTime!! + get() = itemOne.atechDateTime val pumpId: Long - get() = if (itemOne==null) 0L else itemOne!!.pumpId!! + get() = itemOne.pumpId!! val duration: Int get() = if (itemTwo == null) { - val tbr = itemOne!!.getDecodedDataEntry("Object") as TempBasalPair? - tbr!!.durationMinutes + val tbr = itemOne.getDecodedDataEntry("Object") as TempBasalPair + tbr.durationMinutes } else { - DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne!!.atechDateTime, itemTwo!!.atechDateTime) + DateTimeUtil.getATechDateDiferenceAsMinutes(itemOne.atechDateTime, itemTwo!!.atechDateTime) } enum class Operation { From 921302bdbf22e44d3e11604671d35ba919b9d9c3 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 16:16:05 +0100 Subject: [PATCH 29/39] - kotlin !! refactorings --- .../nightscout/androidaps/db/DbObjectBase.kt | 1 + .../pump/medtronic/MedtronicFragment.kt | 10 +- .../pump/medtronic/MedtronicPumpPlugin.kt | 10 +- .../comm/MedtronicCommunicationManager.kt | 30 ++-- .../comm/history/MedtronicHistoryDecoder.kt | 16 +- .../comm/history/MedtronicHistoryEntry.kt | 8 +- .../comm/history/cgms/CGMSHistoryEntry.kt | 11 ++ .../cgms/MedtronicCGMSHistoryDecoder.kt | 23 +-- .../pump/MedtronicPumpHistoryDecoder.kt | 168 +++++++++++------- .../comm/history/pump/PumpHistoryEntry.kt | 38 ++-- .../comm/history/pump/PumpHistoryResult.kt | 11 +- .../GetHistoryPageCarelinkMessageBody.kt | 8 +- .../comm/ui/MedtronicUIPostprocessor.kt | 60 ++++--- .../pump/medtronic/comm/ui/MedtronicUITask.kt | 2 +- .../medtronic/data/MedtronicHistoryData.kt | 115 +++++------- .../pump/medtronic/data/dto/BasalProfile.kt | 19 +- .../pump/medtronic/data/dto/BolusDTO.kt | 39 ++-- .../pump/medtronic/data/dto/ClockDTO.kt | 7 +- .../data/dto/PumpTimeStampedRecord.kt | 4 +- .../medtronic/data/dto/TempBasalProcessDTO.kt | 2 +- .../dialog/MedtronicHistoryActivity.kt | 4 +- .../service/RileyLinkMedtronicService.kt | 12 +- 22 files changed, 337 insertions(+), 261 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt b/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt index e8e4be360f..85869e9bae 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt +++ b/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt @@ -1,5 +1,6 @@ package info.nightscout.androidaps.db +@Deprecated("This class is not needed for new database anymore") interface DbObjectBase { fun getDate(): Long diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index 6e1130f3d8..58d328bd69 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -296,13 +296,13 @@ class MedtronicFragment : DaggerFragment() { val bolus = medtronicPumpStatus.lastBolusAmount val bolusTime = medtronicPumpStatus.lastBolusTime if (bolus != null && bolusTime != null) { - val agoMsc = System.currentTimeMillis() - medtronicPumpStatus.lastBolusTime!!.time + val agoMsc = System.currentTimeMillis() - bolusTime.time val bolusMinAgo = agoMsc.toDouble() / 60.0 / 1000.0 val unit = resourceHelper.gs(R.string.insulin_unit_shortname) val ago = when { agoMsc < 60 * 1000 -> resourceHelper.gs(R.string.medtronic_pump_connected_now) - bolusMinAgo < 60 -> dateUtil.minAgo(resourceHelper, medtronicPumpStatus.lastBolusTime!!.time) - else -> dateUtil.hourAgo(medtronicPumpStatus.lastBolusTime!!.time, resourceHelper) + bolusMinAgo < 60 -> dateUtil.minAgo(resourceHelper, bolusTime.time) + else -> dateUtil.hourAgo(bolusTime.time, resourceHelper) } binding.lastBolus.text = resourceHelper.gs(R.string.mdt_last_bolus, bolus, unit, ago) } else { @@ -315,9 +315,9 @@ class MedtronicFragment : DaggerFragment() { // TBR var tbrStr = "" - var tbrRemainingTime: Int? = medtronicPumpStatus.tbrRemainingTime + val tbrRemainingTime: Int? = medtronicPumpStatus.tbrRemainingTime - if (tbrRemainingTime!=null) { + if (tbrRemainingTime != null) { tbrStr = resourceHelper.gs(R.string.mdt_tbr_remaining, medtronicPumpStatus.tempBasalAmount, tbrRemainingTime); } binding.tempBasal.text = tbrStr diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 2f46965223..d67f05f4a4 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -303,7 +303,7 @@ class MedtronicPumpPlugin @Inject constructor( override fun getPumpStatus(reason: String) { var needRefresh = true if (firstRun) { - needRefresh = initializePump(!isRefresh) + needRefresh = initializePump() /*!isRefresh*/ } else { refreshAnyStatusThatNeedsToBeRefreshed() } @@ -401,7 +401,7 @@ class MedtronicPumpPlugin @Inject constructor( rxBus.send(EventRefreshButtonState(enabled)) } - private fun initializePump(realInit: Boolean): Boolean { + private fun initializePump(): Boolean { if (rileyLinkMedtronicService == null) return false aapsLogger.info(LTag.PUMP, logPrefix + "initializePump - start") rileyLinkMedtronicService!!.deviceCommunicationManager.setDoWakeUpBeforeCommand(false) @@ -562,7 +562,7 @@ class MedtronicPumpPlugin @Inject constructor( if (clock == null) return val timeDiff = Math.abs(clock.timeDifference) if (timeDiff > 20) { - if (clock.localDeviceTime!!.year <= 2015 || timeDiff <= 24 * 60 * 60) { + if (clock.localDeviceTime.year <= 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)) rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock) if (clock.timeDifference == 0) { @@ -570,7 +570,7 @@ class MedtronicPumpPlugin @Inject constructor( rxBus.send(EventNewNotification(notification)) } } else { - if (clock.localDeviceTime!!.year > 2015) { + if (clock.localDeviceTime.year > 2015) { aapsLogger.error(String.format(Locale.ENGLISH, "MedtronicPumpPlugin::checkTimeAndOptionallySetTime - Time difference over 24h requested [diff=%d s]. Doing nothing.", timeDiff)) medtronicUtil.sendNotification(MedtronicNotificationType.TimeChangeOver24h, resourceHelper, rxBus) } @@ -855,7 +855,7 @@ class MedtronicPumpPlugin @Inject constructor( if (debugHistory) aapsLogger.debug(LTag.PUMP, logPrefix + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - " + medtronicUtil.gsonInstance.toJson(lastPumpHistoryEntry)) medtronicHistoryData.setIsInInit(false) // we need to read 35 minutes in the past so that we can repair any TBR or Bolus values if neeeded - targetDate = LocalDateTime(DateTimeUtil.getMillisFromATDWithAddedMinutes(lastPumpHistoryEntry!!.atechDateTime!!, -35)) + targetDate = LocalDateTime(DateTimeUtil.getMillisFromATDWithAddedMinutes(lastPumpHistoryEntry!!.atechDateTime, -35)) } //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index acdbcc2e10..c5db70ccd0 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -35,7 +35,6 @@ import org.joda.time.LocalDateTime import java.util.* import javax.inject.Inject import javax.inject.Singleton -import kotlin.jvm.Throws /** * Original file created by geoff on 5/30/16. @@ -54,11 +53,11 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth @Inject lateinit var medtronicConverter: MedtronicConverter @Inject lateinit var medtronicUtil: MedtronicUtil @Inject lateinit var medtronicPumpHistoryDecoder: MedtronicPumpHistoryDecoder - + private val MAX_COMMAND_TRIES = 3 private val DEFAULT_TIMEOUT = 2000 private val RILEYLINK_TIMEOUT: Long = 15 * 60 * 1000 // 15 min - + var errorResponse: String? = null private set private val debugSetCommands = false @@ -266,8 +265,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth while (!done) { // examine current response for problems. val frameData = currentResponse.frameData - if (frameData != null && frameData.size > 0 - && currentResponse.frameNumber == expectedFrameNum) { + if (frameData.size > 0 && currentResponse.frameNumber == expectedFrameNum) { // success! got a frame. if (frameData.size != 64) { aapsLogger.warn(LTag.PUMPCOMM, "Expected frame of length 64, got frame of length " + frameData.size) @@ -287,7 +285,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth done = true // successful completion } } else { - if (frameData == null) { + if (frameData.size == 0) { aapsLogger.error(LTag.PUMPCOMM, "null frame data, retrying") } else if (currentResponse.frameNumber != expectedFrameNum) { aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Expected frame number %d, received %d (retrying)", expectedFrameNum, @@ -335,7 +333,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth rawHistoryPage.dumpToDebug() val medtronicHistoryEntries = medtronicPumpHistoryDecoder.processPageAndCreateRecords(rawHistoryPage) aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Found %d history entries.", medtronicHistoryEntries.size)) - pumpTotalResult.addHistoryEntries(medtronicHistoryEntries, pageNumber) + pumpTotalResult.addHistoryEntries(medtronicHistoryEntries) //, pageNumber) aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "getPumpHistory: Search status: Search finished: %b", pumpTotalResult.isSearchFinished)) if (pumpTotalResult.isSearchFinished) { medtronicPumpStatus.pumpDeviceState = PumpDeviceState.Sleeping @@ -350,7 +348,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth return when (type) { RLMessageType.PowerOn -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.RFPowerOn, byteArrayOf(2, 1, receiverDeviceAwakeForMinutes.toByte())) RLMessageType.ReadSimpleData -> medtronicUtil.buildCommandPayload(rileyLinkServiceData, MedtronicCommandType.PumpModel, null) - else -> ByteArray(0) + else -> ByteArray(0) } } @@ -507,8 +505,6 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } } - - fun getBasalProfile(): BasalProfile? { // wakeUp @@ -552,7 +548,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } - aapsLogger.debug(LTag.PUMPCOMM,"End Response: {}", ByteUtil.getHex(data)) + aapsLogger.debug(LTag.PUMPCOMM, "End Response: {}", ByteUtil.getHex(data)) var basalProfile: BasalProfile? = medtronicConverter.decodeBasalProfile(medtronicPumpPlugin.pumpDescription.pumpType, data) // checkResponseRawContent(data, commandType) { @@ -593,26 +589,26 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } fun getPumpTime(): ClockDTO? { - val clockDTO = ClockDTO() - clockDTO.localDeviceTime = LocalDateTime() + val localTime = LocalDateTime() val responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetRealTimeClock) { _, _, rawContent -> medtronicConverter.decodeTime(rawContent) } if (responseObject != null) { - clockDTO.pumpTime = responseObject - return clockDTO + return ClockDTO(localDeviceTime = localTime, pumpTime = responseObject) } return null } fun getTemporaryBasal(): TempBasalPair? { return sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal) { _, _, rawContent -> - TempBasalPair(aapsLogger, rawContent!!) } + TempBasalPair(aapsLogger, rawContent!!) + } } fun getPumpSettings(): Map? { return sendAndGetResponseWithCheck(getSettings(medtronicUtil.medtronicPumpModel)) { _, _, rawContent -> - medtronicConverter.decodeSettingsLoop(rawContent) } + medtronicConverter.decodeSettingsLoop(rawContent) + } } fun setBolus(units: Double): Boolean { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 65b03e70cb..58e807f38d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -7,8 +7,6 @@ import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil import org.apache.commons.lang3.StringUtils import java.util.* -import javax.inject.Inject -import kotlin.jvm.Throws /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes @@ -19,9 +17,17 @@ import kotlin.jvm.Throws */ abstract class MedtronicHistoryDecoder : MedtronicHistoryDecoderInterface { - @Inject lateinit var aapsLogger: AAPSLogger - @Inject lateinit var medtronicUtil: MedtronicUtil - @Inject lateinit var bitUtils: ByteUtil + constructor(aapsLogger: AAPSLogger, + medtronicUtil: MedtronicUtil, + bitUtils: ByteUtil) { + this.aapsLogger = aapsLogger + this.medtronicUtil = medtronicUtil + this.bitUtils = bitUtils + } + + var aapsLogger: AAPSLogger + var medtronicUtil: MedtronicUtil + var bitUtils: ByteUtil // STATISTICS (remove at later time or not) protected var statisticsEnabled = true diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index 3910bab135..3c88716f09 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -5,6 +5,7 @@ import com.google.gson.annotations.Expose 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.PumpHistoryEntryType import java.util.* /** @@ -42,6 +43,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { set(value) { field = value DT = DateTimeUtil.toString(value) + if (isEntryTypeSet() && value != 0L) pumpId = generatePumpId() } @Expose @@ -51,7 +53,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { /** * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) */ - open var pumpId: Long? = null + open var pumpId: Long = 0L /** * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's @@ -75,6 +77,10 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { // this.linkedObject = linkedObject // } + abstract fun generatePumpId(): Long + + abstract fun isEntryTypeSet(): Boolean + override fun setData(listRawData: List, doNotProcess: Boolean) { rawData = listRawData diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt index f35a65d4f5..3815815c4e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt @@ -30,6 +30,17 @@ class CGMSHistoryEntry : MedtronicHistoryEntry() { override val entryTypeName: String get() = entryType!!.name + override fun generatePumpId(): Long { + return if (entryType==null) + atechDateTime * 1000L + else + entryType!!.code + atechDateTime * 1000L + } + + override fun isEntryTypeSet(): Boolean { + return entryType!=null + } + override fun setData(listRawData: List, doNotProcess: Boolean) { if (entryType!!.schemaSet) { super.setData(listRawData, doNotProcess) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index 424c269986..b629369f70 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -1,18 +1,17 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms +import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.logging.StacktraceLoggerWrapper.Companion.getLogger +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSHistoryEntryType import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSHistoryEntryType.Companion.getByCode +import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil import okhttp3.internal.and import org.joda.time.LocalDateTime -import org.slf4j.Logger -import org.slf4j.LoggerFactory import java.util.* -import org.slf4j.LoggerFactory.getLogger as getLogger1 /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes @@ -21,13 +20,17 @@ import org.slf4j.LoggerFactory.getLogger as getLogger1 * * Author: Andy {andy.rozman@gmail.com} */ -class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() { +class MedtronicCGMSHistoryDecoder constructor( + aapsLogger: AAPSLogger, + medtronicUtil: MedtronicUtil, + bitUtils: ByteUtil +) : MedtronicHistoryDecoder(aapsLogger, medtronicUtil, bitUtils) { override fun decodeRecord(record: CGMSHistoryEntry): RecordDecodeStatus? { return try { decodeRecordInternal(record) } catch (ex: Exception) { - aapsLogger.error(LTag.PUMPCOMM," Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) + aapsLogger.error(LTag.PUMPCOMM, " Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) RecordDecodeStatus.Error } } @@ -111,7 +114,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() } } while (counter < dataClear.size) outList.reverse() - val reversedOutList = outList // reverseList(outList, CGMSHistoryEntry::class.java) + val reversedOutList = outList // reverseList(outList, CGMSHistoryEntry::class.java) //var timeStamp: Long? = null var dateTime: LocalDateTime? = null var getIndex = 0 @@ -127,7 +130,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() } else { if (dateTime != null) entry.setDateTime(dateTime, getIndex) } - aapsLogger.debug(LTag.PUMPCOMM,"Record: {}", entry) + aapsLogger.debug(LTag.PUMPCOMM, "Record: {}", entry) } return reversedOutList } @@ -171,7 +174,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() entry.atechDateTime = atechDateTime atechDateTime } else if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.SecondSpecific) { - aapsLogger.warn(LTag.PUMPCOMM,"parseDate for SecondSpecific type is not implemented.") + aapsLogger.warn(LTag.PUMPCOMM, "parseDate for SecondSpecific type is not implemented.") throw RuntimeException() // return null; } else null @@ -246,7 +249,7 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder() val packetType: String packetType = when (entry.getRawDataByIndex(1)) { 0x02.toByte() -> "init" - else -> "unknown" + else -> "unknown" } entry.addDecodedData("packetType", packetType) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index 932127f5c9..0a96a561f8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -30,8 +30,9 @@ import kotlin.experimental.and @Singleton class MedtronicPumpHistoryDecoder @Inject constructor( aapsLogger: AAPSLogger, - medtronicUtil: MedtronicUtil -) : MedtronicHistoryDecoder() { + medtronicUtil: MedtronicUtil, + bitUtils: ByteUtil +) : MedtronicHistoryDecoder(aapsLogger, medtronicUtil, bitUtils) { //private var tbrPreviousRecord: PumpHistoryEntry? = null private var changeTimeRecord: PumpHistoryEntry? = null @@ -133,7 +134,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( return try { decodeRecordInternal(record) } catch (ex: Exception) { - aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.entryType!!.name, ex.message, ex)) + aapsLogger.error(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, " Error decoding: type=%s, ex=%s", record.entryType.name, ex.message, ex)) //ex.printStackTrace() RecordDecodeStatus.Error } @@ -144,62 +145,125 @@ class MedtronicPumpHistoryDecoder @Inject constructor( decodeDateTime(entry) } return when (entry.entryType) { - PumpHistoryEntryType.ChangeBasalPattern, PumpHistoryEntryType.CalBGForPH, PumpHistoryEntryType.ChangeRemoteId, PumpHistoryEntryType.ClearAlarm, PumpHistoryEntryType.ChangeAlarmNotifyMode, PumpHistoryEntryType.EnableDisableRemote, PumpHistoryEntryType.BGReceived, PumpHistoryEntryType.SensorAlert, PumpHistoryEntryType.ChangeTimeFormat, PumpHistoryEntryType.ChangeReservoirWarningTime, PumpHistoryEntryType.ChangeBolusReminderEnable, PumpHistoryEntryType.SetBolusReminderTime, PumpHistoryEntryType.ChangeChildBlockEnable, PumpHistoryEntryType.BolusWizardEnabled, PumpHistoryEntryType.ChangeBGReminderOffset, PumpHistoryEntryType.ChangeAlarmClockTime, PumpHistoryEntryType.ChangeMeterId, PumpHistoryEntryType.ChangeParadigmID, PumpHistoryEntryType.JournalEntryMealMarker, PumpHistoryEntryType.JournalEntryExerciseMarker, PumpHistoryEntryType.DeleteBolusReminderTime, PumpHistoryEntryType.SetAutoOff, PumpHistoryEntryType.SelfTest, PumpHistoryEntryType.JournalEntryInsulinMarker, PumpHistoryEntryType.JournalEntryOtherMarker, PumpHistoryEntryType.BolusWizardSetup512, PumpHistoryEntryType.ChangeSensorSetup2, PumpHistoryEntryType.ChangeSensorAlarmSilenceConfig, PumpHistoryEntryType.ChangeSensorRateOfChangeAlertSetup, PumpHistoryEntryType.ChangeBolusScrollStepSize, PumpHistoryEntryType.BolusWizardSetup, PumpHistoryEntryType.ChangeVariableBolus, PumpHistoryEntryType.ChangeAudioBolus, PumpHistoryEntryType.ChangeBGReminderEnable, PumpHistoryEntryType.ChangeAlarmClockEnable, PumpHistoryEntryType.BolusReminder, PumpHistoryEntryType.DeleteAlarmClockTime, PumpHistoryEntryType.ChangeCarbUnits, PumpHistoryEntryType.ChangeWatchdogEnable, PumpHistoryEntryType.ChangeOtherDeviceID, PumpHistoryEntryType.ReadOtherDevicesIDs, PumpHistoryEntryType.BGReceived512, PumpHistoryEntryType.SensorStatus, PumpHistoryEntryType.ReadCaptureEventEnabled, PumpHistoryEntryType.ChangeCaptureEventEnable, PumpHistoryEntryType.ReadOtherDevicesStatus -> RecordDecodeStatus.OK + PumpHistoryEntryType.ChangeBasalPattern, + PumpHistoryEntryType.CalBGForPH, + PumpHistoryEntryType.ChangeRemoteId, + PumpHistoryEntryType.ClearAlarm, + PumpHistoryEntryType.ChangeAlarmNotifyMode, + PumpHistoryEntryType.EnableDisableRemote, + PumpHistoryEntryType.BGReceived, + PumpHistoryEntryType.SensorAlert, + PumpHistoryEntryType.ChangeTimeFormat, + PumpHistoryEntryType.ChangeReservoirWarningTime, + PumpHistoryEntryType.ChangeBolusReminderEnable, + PumpHistoryEntryType.SetBolusReminderTime, + PumpHistoryEntryType.ChangeChildBlockEnable, + PumpHistoryEntryType.BolusWizardEnabled, + PumpHistoryEntryType.ChangeBGReminderOffset, + PumpHistoryEntryType.ChangeAlarmClockTime, + PumpHistoryEntryType.ChangeMeterId, + PumpHistoryEntryType.ChangeParadigmID, + PumpHistoryEntryType.JournalEntryMealMarker, + PumpHistoryEntryType.JournalEntryExerciseMarker, + PumpHistoryEntryType.DeleteBolusReminderTime, + PumpHistoryEntryType.SetAutoOff, + PumpHistoryEntryType.SelfTest, + PumpHistoryEntryType.JournalEntryInsulinMarker, + PumpHistoryEntryType.JournalEntryOtherMarker, + PumpHistoryEntryType.BolusWizardSetup512, + PumpHistoryEntryType.ChangeSensorSetup2, + PumpHistoryEntryType.ChangeSensorAlarmSilenceConfig, + PumpHistoryEntryType.ChangeSensorRateOfChangeAlertSetup, + PumpHistoryEntryType.ChangeBolusScrollStepSize, + PumpHistoryEntryType.BolusWizardSetup, + PumpHistoryEntryType.ChangeVariableBolus, + PumpHistoryEntryType.ChangeAudioBolus, + PumpHistoryEntryType.ChangeBGReminderEnable, + PumpHistoryEntryType.ChangeAlarmClockEnable, + PumpHistoryEntryType.BolusReminder, + PumpHistoryEntryType.DeleteAlarmClockTime, + PumpHistoryEntryType.ChangeCarbUnits, + PumpHistoryEntryType.ChangeWatchdogEnable, + PumpHistoryEntryType.ChangeOtherDeviceID, + PumpHistoryEntryType.ReadOtherDevicesIDs, + PumpHistoryEntryType.BGReceived512, + PumpHistoryEntryType.SensorStatus, + PumpHistoryEntryType.ReadCaptureEventEnabled, + PumpHistoryEntryType.ChangeCaptureEventEnable, + PumpHistoryEntryType.ReadOtherDevicesStatus -> RecordDecodeStatus.OK - PumpHistoryEntryType.Sensor_0x54, PumpHistoryEntryType.Sensor_0x55, PumpHistoryEntryType.Sensor_0x51, PumpHistoryEntryType.Sensor_0x52, PumpHistoryEntryType.EventUnknown_MM512_0x2e -> { + PumpHistoryEntryType.Sensor_0x54, + PumpHistoryEntryType.Sensor_0x55, + PumpHistoryEntryType.Sensor_0x51, + PumpHistoryEntryType.Sensor_0x52, + PumpHistoryEntryType.EventUnknown_MM512_0x2e -> { aapsLogger.debug(LTag.PUMPBTCOMM, " -- ignored Unknown Pump Entry: $entry") RecordDecodeStatus.Ignored } - PumpHistoryEntryType.UnabsorbedInsulin, PumpHistoryEntryType.UnabsorbedInsulin512 -> RecordDecodeStatus.Ignored - PumpHistoryEntryType.DailyTotals522, PumpHistoryEntryType.DailyTotals523, PumpHistoryEntryType.DailyTotals515, PumpHistoryEntryType.EndResultTotals -> decodeDailyTotals(entry) - PumpHistoryEntryType.ChangeBasalProfile_OldProfile, PumpHistoryEntryType.ChangeBasalProfile_NewProfile -> decodeBasalProfile(entry) - PumpHistoryEntryType.BasalProfileStart -> decodeBasalProfileStart(entry) + PumpHistoryEntryType.UnabsorbedInsulin, + PumpHistoryEntryType.UnabsorbedInsulin512 -> RecordDecodeStatus.Ignored + PumpHistoryEntryType.DailyTotals522, + PumpHistoryEntryType.DailyTotals523, + PumpHistoryEntryType.DailyTotals515, + PumpHistoryEntryType.EndResultTotals -> decodeDailyTotals(entry) + PumpHistoryEntryType.ChangeBasalProfile_OldProfile, + PumpHistoryEntryType.ChangeBasalProfile_NewProfile -> decodeBasalProfile(entry) + PumpHistoryEntryType.BasalProfileStart -> decodeBasalProfileStart(entry) - PumpHistoryEntryType.ChangeTime -> { + PumpHistoryEntryType.ChangeTime -> { changeTimeRecord = entry RecordDecodeStatus.OK } - PumpHistoryEntryType.NewTimeSet -> { + PumpHistoryEntryType.NewTimeSet -> { decodeChangeTime(entry) RecordDecodeStatus.OK } - PumpHistoryEntryType.TempBasalDuration -> // decodeTempBasal(entry); + PumpHistoryEntryType.TempBasalDuration -> // decodeTempBasal(entry); RecordDecodeStatus.OK - PumpHistoryEntryType.TempBasalRate -> // decodeTempBasal(entry); + PumpHistoryEntryType.TempBasalRate -> // decodeTempBasal(entry); RecordDecodeStatus.OK - PumpHistoryEntryType.Bolus -> { + PumpHistoryEntryType.Bolus -> { decodeBolus(entry) RecordDecodeStatus.OK } - PumpHistoryEntryType.BatteryChange -> { + PumpHistoryEntryType.BatteryChange -> { decodeBatteryActivity(entry) RecordDecodeStatus.OK } - PumpHistoryEntryType.LowReservoir -> { + PumpHistoryEntryType.LowReservoir -> { decodeLowReservoir(entry) RecordDecodeStatus.OK } - PumpHistoryEntryType.LowBattery, PumpHistoryEntryType.SuspendPump, PumpHistoryEntryType.ResumePump, PumpHistoryEntryType.Rewind, PumpHistoryEntryType.NoDeliveryAlarm, PumpHistoryEntryType.ChangeTempBasalType, PumpHistoryEntryType.ChangeMaxBolus, PumpHistoryEntryType.ChangeMaxBasal, PumpHistoryEntryType.ClearSettings, PumpHistoryEntryType.SaveSettings -> RecordDecodeStatus.OK - PumpHistoryEntryType.BolusWizard -> decodeBolusWizard(entry) - PumpHistoryEntryType.BolusWizard512 -> decodeBolusWizard512(entry) + PumpHistoryEntryType.LowBattery, + PumpHistoryEntryType.SuspendPump, + PumpHistoryEntryType.ResumePump, + PumpHistoryEntryType.Rewind, + PumpHistoryEntryType.NoDeliveryAlarm, + PumpHistoryEntryType.ChangeTempBasalType, + PumpHistoryEntryType.ChangeMaxBolus, + PumpHistoryEntryType.ChangeMaxBasal, + PumpHistoryEntryType.ClearSettings, + PumpHistoryEntryType.SaveSettings -> RecordDecodeStatus.OK + PumpHistoryEntryType.BolusWizard -> decodeBolusWizard(entry) + PumpHistoryEntryType.BolusWizard512 -> decodeBolusWizard512(entry) - PumpHistoryEntryType.Prime -> { + PumpHistoryEntryType.Prime -> { decodePrime(entry) RecordDecodeStatus.OK } - PumpHistoryEntryType.TempBasalCombined -> RecordDecodeStatus.Ignored - PumpHistoryEntryType.None, PumpHistoryEntryType.UnknownBasePacket -> RecordDecodeStatus.Error + PumpHistoryEntryType.TempBasalCombined -> RecordDecodeStatus.Ignored + PumpHistoryEntryType.None, PumpHistoryEntryType.UnknownBasePacket -> RecordDecodeStatus.Error - else -> { + else -> { aapsLogger.debug(LTag.PUMPBTCOMM, "Not supported: " + entry.entryType) RecordDecodeStatus.NotSupported } @@ -345,10 +409,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( entry.addDecodedData("amount", (ByteUtil.asUINT8(entry.getRawDataByIndex(5)) and 0x80 shl 1) + ByteUtil.asUINT8(entry.getRawDataByIndex(0))) // index moved from 1 -> 0 } - private fun decodeNoDeliveryAlarm(entry: PumpHistoryEntry) { - //rawtype = asUINT8(data[1]); - // not sure if this is actually NoDelivery Alarm? - } + // private fun decodeNoDeliveryAlarm(entry: PumpHistoryEntry) { + // //rawtype = asUINT8(data[1]); + // // not sure if this is actually NoDelivery Alarm? + // } override fun postProcess() {} @@ -357,34 +421,25 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBolus(entry: PumpHistoryEntry) { - val bolus = BolusDTO() + var bolus: BolusDTO? val data = entry.head!! if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) { - 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 = BolusDTO(atechDateTime = entry.atechDateTime, + requestedAmount = ByteUtil.toInt(data.get(0), data.get(1)) / 40.0, + deliveredAmount = ByteUtil.toInt(data.get(2), data.get(3)) / 40.0, + duration = data.get(6) * 30) bolus.insulinOnBoard = ByteUtil.toInt(data.get(4), data.get(5)) / 40.0 - bolus.duration = data.get(6) * 30 } else { - bolus.requestedAmount = ByteUtil.asUINT8(data.get(0)) / 10.0 - bolus.deliveredAmount = ByteUtil.asUINT8(data.get(1)) / 10.0 - bolus.duration = ByteUtil.asUINT8(data.get(2)) * 30 + bolus = BolusDTO(atechDateTime = entry.atechDateTime, + requestedAmount = ByteUtil.asUINT8(data.get(0)) / 10.0, + deliveredAmount = ByteUtil.asUINT8(data.get(1)) / 10.0, + duration = ByteUtil.asUINT8(data.get(2)) * 30) } - bolus.bolusType = if (bolus.duration != null && bolus.duration!! > 0) PumpBolusType.Extended else PumpBolusType.Normal - bolus.atechDateTime = entry.atechDateTime + bolus.bolusType = if (bolus.duration > 0) PumpBolusType.Extended else PumpBolusType.Normal entry.addDecodedData("Object", bolus) entry.displayableValue = bolus.displayableValue } - // private fun decodeTempBasal(entry: PumpHistoryEntry) { - // if (tbrPreviousRecord == null) { - // // LOG.debug(this.tbrPreviousRecord.toString()); - // tbrPreviousRecord = entry - // return - // } - // decodeTempBasal(tbrPreviousRecord, entry) - // tbrPreviousRecord = null - // } - fun decodeTempBasal(tbrPreviousRecord: PumpHistoryEntry, entry: PumpHistoryEntry) { var tbrRate: PumpHistoryEntry? = null var tbrDuration: PumpHistoryEntry? = null @@ -399,25 +454,18 @@ class MedtronicPumpHistoryDecoder @Inject constructor( tbrRate = tbrPreviousRecord } -// TempBasalPair tbr = new TempBasalPair( -// tbrRate.getHead()[0], -// tbrDuration.getHead()[0], -// (ByteUtil.asUINT8(tbrRate.getDatetime()[4]) >> 3) == 0); val tbr = TempBasalPair( tbrRate.head!!.get(0), tbrRate.body!!.get(0), tbrDuration!!.head!!.get(0).toInt(), ByteUtil.asUINT8(tbrRate.datetime!!.get(4)) shr 3 == 0) - // System.out.println("TBR: amount=" + tbr.getInsulinRate() + ", duration=" + tbr.getDurationMinutes() - // // + " min. Packed: " + tbr.getValue() - // ); entry.addDecodedData("Object", tbr) entry.displayableValue = tbr.description } private fun decodeDateTime(entry: PumpHistoryEntry) { - if (entry.datetime==null) { + if (entry.datetime == null) { aapsLogger.warn(LTag.PUMPBTCOMM, "DateTime not set.") } val dt = entry.datetime!! @@ -445,7 +493,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( //LOG.debug("DT: {} {} {}", year, month, dayOfMonth); if (dayOfMonth == 32) { - aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Entry: Day 32 %s = [%s] %s", entry.entryType!!.name, + aapsLogger.warn(LTag.PUMPBTCOMM, String.format(Locale.ENGLISH, "Entry: Day 32 %s = [%s] %s", entry.entryType.name, ByteUtil.getHex(entry.rawData), entry)) } if (isEndResults(entry.entryType)) { @@ -460,7 +508,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun isEndResults(entryType: PumpHistoryEntryType?): Boolean { - return entryType === PumpHistoryEntryType.EndResultTotals || entryType === PumpHistoryEntryType.DailyTotals515 || entryType === PumpHistoryEntryType.DailyTotals522 || entryType === PumpHistoryEntryType.DailyTotals523 + return entryType === PumpHistoryEntryType.EndResultTotals || + entryType === PumpHistoryEntryType.DailyTotals515 || + entryType === PumpHistoryEntryType.DailyTotals522 || + entryType === PumpHistoryEntryType.DailyTotals523 } private fun fix2DigitYear(year: Int): Int { @@ -474,13 +525,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } companion object { + private fun getFormattedValue(value: Float, decimals: Int): String { return String.format(Locale.ENGLISH, "%." + decimals + "f", value) } } - init { - super.aapsLogger = aapsLogger - this.medtronicUtil = medtronicUtil - } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index 83c1ab2f10..45766ec6d8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -19,12 +19,12 @@ import java.util.* class PumpHistoryEntry : MedtronicHistoryEntry() { @Expose - var entryType: PumpHistoryEntryType? = null + var entryType: PumpHistoryEntryType = PumpHistoryEntryType.None private set override var opCode: Byte? = null // this is set only when we have unknown entry... - get() = if (field == null) entryType!!.code else field + get() = if (field == null) entryType.code else field set(value) { field = value } @@ -41,15 +41,19 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { sizes[0] = entryType.getHeadLength(medtronicDeviceType) sizes[1] = entryType.dateLength sizes[2] = entryType.getBodyLength(medtronicDeviceType) - if (this.entryType != null && atechDateTime != 0L) generatePumpId() + if (isEntryTypeSet() && atechDateTime != 0L) pumpId = generatePumpId() } - private fun generatePumpId() : Long { - return entryType!!.code + atechDateTime * 1000L + override fun generatePumpId() : Long { + return entryType.code + atechDateTime * 1000L + } + + override fun isEntryTypeSet(): Boolean { + return this.entryType != PumpHistoryEntryType.None } override val toStringStart: String - get() = ("PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType!!.name, 20) + " [" + get() = ("PumpHistoryEntry [type=" + StringUtil.getStringInLength(entryType.name, 20) + " [" + StringUtil.getStringInLength("" + opCode, 3) + ", 0x" + ByteUtil.shortHexString(opCode!!) + "]") @@ -65,16 +69,16 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { } override val entryTypeName: String - get() = entryType!!.name + get() = entryType.name override val dateLength: Int - get() = entryType!!.dateLength + get() = entryType.dateLength override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is PumpHistoryEntry) return false val that = other //as PumpHistoryEntry - return this.pumpId === that.pumpId + return this.pumpId == that.pumpId // return entryType == that.entryType && // // atechDateTime === that.atechDateTime // && // // Objects.equals(this.decodedData, that.decodedData); @@ -101,24 +105,26 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { class Comparator : java.util.Comparator { override fun compare(o1: PumpHistoryEntry, o2: PumpHistoryEntry): Int { val data = (o2.atechDateTime - o1.atechDateTime).toInt() - return if (data != 0) data else o2.entryType!!.code - o1.entryType!!.code + return if (data != 0) data else o2.entryType.code - o1.entryType.code } } - override var pumpId: Long? = null + override var pumpId: Long = 0L get() { - field = generatePumpId() + if (field==0L) { + field = generatePumpId() + } return field } set(pumpId) { - super.pumpId = pumpId + field = pumpId } fun hasBolusChanged(entry: PumpHistoryEntry) : Boolean { - if (entryType!=null && entryType == PumpHistoryEntryType.Bolus) { + if (entryType == PumpHistoryEntryType.Bolus) { val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO - - if (entry.entryType!=null && entry.entryType == PumpHistoryEntryType.Bolus) { + + if (entry.entryType == PumpHistoryEntryType.Bolus) { val otherOne: BolusDTO = entry.decodedData["Object"] as BolusDTO return (thisOne.value.equals(otherOne.value)) } else diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt index 5fd484628d..7bdc42d1ef 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryResult.kt @@ -22,8 +22,7 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis var unprocessedEntries: List = ArrayList() var validEntries: MutableList = ArrayList() - - fun addHistoryEntries(entries: List, page: Int) { + fun addHistoryEntries(entries: List /*, page: Int*/) { unprocessedEntries = entries //aapsLogger.debug(LTag.PUMPCOMM,"PumpHistoryResult. Unprocessed entries: {}", MedtronicUtil.getGsonInstance().toJson(entries)); processEntries() @@ -42,7 +41,7 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis //Collections.sort(this.unprocessedEntries, new PumpHistoryEntry.Comparator()); aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: " + searchEntry!!.atechDateTime) - val date = searchEntry.atechDateTime + //val date = searchEntry.atechDateTime for (unprocessedEntry in unprocessedEntries) { if (unprocessedEntry.equals(searchEntry)) { //aapsLogger.debug(LTag.PUMPCOMM,"PE. Item found {}.", unprocessedEntry); @@ -60,7 +59,7 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis SearchType.Date -> { aapsLogger.debug(LTag.PUMPCOMM, "PE. Date search: Search date: " + searchDate) for (unprocessedEntry in unprocessedEntries) { - if (unprocessedEntry.atechDateTime == null || unprocessedEntry.atechDateTime == 0L) { + if (unprocessedEntry.atechDateTime == 0L) { aapsLogger.debug(LTag.PUMPCOMM, "PE. PumpHistoryResult. Search entry date: Entry with no date: $unprocessedEntry") continue } @@ -83,7 +82,7 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis } override fun toString(): String { - return "PumpHistoryResult [unprocessed=" + unprocessedEntries.size + // + return "PumpHistoryResult [unprocessed=" + unprocessedEntries.size + // ", valid=" + validEntries.size + // ", searchEntry=" + searchEntry + // ", searchDate=" + searchDate + // @@ -99,11 +98,9 @@ class PumpHistoryResult(private val aapsLogger: AAPSLogger, searchEntry: PumpHis val latestEntry: PumpHistoryEntry? get() = if (validEntries.size == 0) null else validEntries[0] - // val isSearchRequired: Boolean // get() = searchType != SearchType.None - internal enum class SearchType { None, // LastEntry, // diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt index b2836d4f77..1f86c1446a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/GetHistoryPageCarelinkMessageBody.kt @@ -41,5 +41,11 @@ class GetHistoryPageCarelinkMessageBody : CarelinkLongMessageBody { } val frameData: ByteArray - get() = ByteUtil.substring(data!!, 1, data!!.size - 1) + get() { + return if (data == null) { + byteArrayOf() + } else { + ByteUtil.substring(data!!, 1, data!!.size - 1) + } + } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index f4398bee62..11dbc9bb46 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -1,6 +1,5 @@ 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 @@ -38,7 +37,7 @@ class MedtronicUIPostprocessor @Inject constructor( // where responses won't be directly used fun postProcessData(uiTask: MedtronicUITask) { when (uiTask.commandType) { - MedtronicCommandType.SetBasalProfileSTD -> { + MedtronicCommandType.SetBasalProfileSTD -> { val response = uiTask.result as Boolean? if (response!!) { val basalProfile = uiTask.getParameter(0) as BasalProfile @@ -50,21 +49,22 @@ class MedtronicUIPostprocessor @Inject constructor( } } - MedtronicCommandType.GetBasalProfileSTD -> { + MedtronicCommandType.GetBasalProfileSTD -> { val basalProfile = uiTask.result as BasalProfile? //aapsLogger.debug("D: basal profile on read: " + basalProfile); try { - // TODO need to refactor - 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())) + if (basalProfile != null) { + val profilesByHour = basalProfile.getProfilesByHour(medtronicPumpPlugin.pumpDescription.pumpType) + if (!BasalProfile.isBasalProfileByHourUndefined(profilesByHour)) { + 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())) @@ -73,26 +73,26 @@ class MedtronicUIPostprocessor @Inject constructor( } } - MedtronicCommandType.SetBolus -> { + MedtronicCommandType.SetBolus -> { medtronicPumpStatus.lastBolusAmount = uiTask.getDoubleFromParameters(0) medtronicPumpStatus.lastBolusTime = Date() } - MedtronicCommandType.GetRemainingInsulin -> { + MedtronicCommandType.GetRemainingInsulin -> { medtronicPumpStatus.reservoirRemainingUnits = uiTask.result as Double } - MedtronicCommandType.CancelTBR -> { + MedtronicCommandType.CancelTBR -> { medtronicPumpStatus.tempBasalStart = null medtronicPumpStatus.tempBasalAmount = null medtronicPumpStatus.tempBasalLength = null } - MedtronicCommandType.GetRealTimeClock -> { + MedtronicCommandType.GetRealTimeClock -> { processTime(uiTask) } - MedtronicCommandType.SetRealTimeClock -> { + 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) { @@ -100,7 +100,7 @@ class MedtronicUIPostprocessor @Inject constructor( } } - MedtronicCommandType.GetBatteryStatus -> { + MedtronicCommandType.GetBatteryStatus -> { val batteryStatusDTO = uiTask.result as BatteryStatusDTO? medtronicPumpStatus.batteryRemaining = batteryStatusDTO!!.getCalculatedPercent(medtronicPumpStatus.batteryType) if (batteryStatusDTO.voltage != null) { @@ -109,7 +109,7 @@ class MedtronicUIPostprocessor @Inject constructor( aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "BatteryStatus: %s", batteryStatusDTO.toString())) } - MedtronicCommandType.PumpModel -> { + MedtronicCommandType.PumpModel -> { if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) { aapsLogger.warn(LTag.PUMP, "Configured pump is different then pump detected !") medtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame, resourceHelper, rxBus) @@ -117,23 +117,27 @@ class MedtronicUIPostprocessor @Inject constructor( } MedtronicCommandType.Settings_512, - MedtronicCommandType.Settings -> { + MedtronicCommandType.Settings -> { postProcessSettings(uiTask) } - else -> { + 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 (clockDTO != null) { + 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") + } else { + aapsLogger.debug(LTag.PUMP, "Problem with returned data: " + medtronicUtil.gsonInstance.toJson(uiTask.result)) + } } private fun postProcessSettings(uiTask: MedtronicUITask) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt index be334adf76..3685db287c 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt @@ -66,7 +66,7 @@ class MedtronicUITask { MedtronicCommandType.GetRealTimeClock -> { result = communicationManager.getPumpTime() - medtronicUtil.pumpTime = null + //medtronicUtil.pumpTime = null } MedtronicCommandType.SetRealTimeClock -> { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index cb34b8962b..f251788366 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -68,7 +68,6 @@ class MedtronicHistoryData @Inject constructor( private var gson: Gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() private var gsonCore: Gson = GsonBuilder().create() - /** * Add New History entries * @@ -81,12 +80,12 @@ class MedtronicHistoryData @Inject constructor( if (!allPumpIds.contains(validEntry.pumpId)) { newEntries.add(validEntry) } else { - val entryByPumpId = getEntryByPumpId(validEntry.pumpId!!) + val entryByPumpId = getEntryByPumpId(validEntry.pumpId) - if (entryByPumpId!=null && entryByPumpId.hasBolusChanged(validEntry)) { + if (entryByPumpId != null && entryByPumpId.hasBolusChanged(validEntry)) { newEntries.add(validEntry) allHistory.remove(entryByPumpId) - allPumpIds.remove(validEntry.pumpId!!); + allPumpIds.remove(validEntry.pumpId); } } } @@ -96,7 +95,7 @@ class MedtronicHistoryData @Inject constructor( private fun getEntryByPumpId(pumpId: Long): PumpHistoryEntry? { val findFirst = this.allHistory.stream() - .filter { f -> f.pumpId!! == pumpId } + .filter { f -> f.pumpId == pumpId } .findFirst() return if (findFirst.isPresent()) findFirst.get() else null @@ -192,7 +191,7 @@ class MedtronicHistoryData @Inject constructor( lastIdUsed++ pumpHistoryEntry.id = lastIdUsed allHistory.add(pumpHistoryEntry) - allPumpIds.add(pumpHistoryEntry.pumpId!!) + allPumpIds.add(pumpHistoryEntry.pumpId) } } @@ -210,7 +209,7 @@ class MedtronicHistoryData @Inject constructor( for (pumpHistoryEntry in allHistory) { if (!pumpHistoryEntry.isAfter(dtRemove)) { removeList.add(pumpHistoryEntry) - allPumpIds.remove(pumpHistoryEntry.pumpId!!) + allPumpIds.remove(pumpHistoryEntry.pumpId) } } allHistory.removeAll(removeList) @@ -241,7 +240,6 @@ class MedtronicHistoryData @Inject constructor( return col != null && !col.isEmpty() } - fun isPumpSuspended(): Boolean { val items = getDataForPumpSuspends() showLogs("isPumpSuspended: ", gson.toJson(items)) @@ -258,7 +256,6 @@ class MedtronicHistoryData @Inject constructor( } else false } - private fun getDataForPumpSuspends(): MutableList { val newAndAll: MutableList = mutableListOf() if (isCollectionNotEmpty(allHistory)) { @@ -397,7 +394,7 @@ class MedtronicHistoryData @Inject constructor( continue } if (primeRecord.atechDateTime > maxAllowedTimeInPast) { - if (lastPrimeRecordTime!=0L && lastPrimeRecordTime < primeRecord.atechDateTime) { + if (lastPrimeRecordTime != 0L && lastPrimeRecordTime < primeRecord.atechDateTime) { lastPrimeRecordTime = primeRecord.atechDateTime lastPrimeRecord = primeRecord } @@ -429,7 +426,6 @@ class MedtronicHistoryData @Inject constructor( } } - private fun uploadCareportalEventIfFoundInHistory(historyRecord: PumpHistoryEntry, eventSP: String, eventType: DetailedBolusInfo.EventType) { val lastPrimeFromAAPS = sp.getLong(eventSP, 0L) if (historyRecord.atechDateTime != lastPrimeFromAAPS) { @@ -448,7 +444,6 @@ class MedtronicHistoryData @Inject constructor( } } - private fun processTDDs(tddsIn: MutableList) { val tdds = filterTDDs(tddsIn) @@ -470,14 +465,12 @@ class MedtronicHistoryData @Inject constructor( } } - private enum class ProcessHistoryRecord(val description: String) { Bolus("Bolus"), TBR("TBR"), Suspend("Suspend"); } - private fun processBolusEntries(entryList: MutableList) { val boluses = pumpSyncStorage.getBoluses() @@ -488,16 +481,16 @@ class MedtronicHistoryData @Inject constructor( var type: DetailedBolusInfo.BolusType = DetailedBolusInfo.BolusType.NORMAL var multiwave = false - if (bolusDTO.bolusType==PumpBolusType.Extended) { + if (bolusDTO.bolusType == PumpBolusType.Extended) { addExtendedBolus(bolus, bolusDTO, multiwave) continue; - } else if (bolusDTO.bolusType==PumpBolusType.Multiwave) { + } else if (bolusDTO.bolusType == PumpBolusType.Multiwave) { multiwave = true aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "Multiwave bolus from pump, extended bolus and normal bolus will be added.")) addExtendedBolus(bolus, bolusDTO, multiwave); } - val deliveredAmount: Double = if (multiwave) bolusDTO.immediateAmount!! else bolusDTO.deliveredAmount!! + val deliveredAmount: Double = if (multiwave) bolusDTO.immediateAmount!! else bolusDTO.deliveredAmount var temporaryId: Long? = null @@ -514,7 +507,7 @@ class MedtronicHistoryData @Inject constructor( } } - if (temporaryId!=null) { + if (temporaryId != null) { val result = pumpSync.syncBolusWithTempId( tryToGetByLocalTime(bolus.atechDateTime), deliveredAmount, @@ -532,7 +525,7 @@ class MedtronicHistoryData @Inject constructor( tryToGetByLocalTime(bolus.atechDateTime), deliveredAmount, type, - bolus.pumpId!!, + bolus.pumpId, medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) @@ -545,25 +538,23 @@ class MedtronicHistoryData @Inject constructor( } } - private fun addExtendedBolus(bolus: PumpHistoryEntry, bolusDTO: BolusDTO, isMultiwave: Boolean) { - val durationMs : Long = bolusDTO.duration!! * 60L * 1000L + val durationMs: Long = bolusDTO.duration * 60L * 1000L val result = pumpSync.syncExtendedBolusWithPumpId( tryToGetByLocalTime(bolus.atechDateTime), - bolusDTO.deliveredAmount!!, + bolusDTO.deliveredAmount, durationMs, false, - bolus.pumpId!!, + bolus.pumpId, medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncExtendedBolusWithPumpId [date=%d, amount=%.2f, duration=%d, pumpId=%d, pumpSerial=%s, multiwave=%b] - Result: %b", - bolus.atechDateTime, bolusDTO.deliveredAmount!!, bolusDTO.duration, bolus.pumpId, + bolus.atechDateTime, bolusDTO.deliveredAmount, bolusDTO.duration, bolus.pumpId, medtronicPumpStatus.serialNumber!!, isMultiwave, result)) } - private fun addCarbs(bolus: PumpHistoryEntry) { if (bolus.containsDecodedData("Estimate")) { val bolusWizard = bolus.decodedData["Estimate"] as BolusWizardDTO @@ -573,12 +564,11 @@ class MedtronicHistoryData @Inject constructor( bolusWizard.carbs.toDouble(), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!, - bolus.pumpId!! + bolus.pumpId )) } } - private fun processTBREntries(entryList: MutableList) { Collections.reverse(entryList) val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? @@ -609,14 +599,14 @@ class MedtronicHistoryData @Inject constructor( readOldItem = false } } else { - aapsLogger.warn(LTag.PUMP,"processDTO was null - shouldn't happen, ignoring item. ItemTwo=$treatment") + aapsLogger.warn(LTag.PUMP, "processDTO was null - shouldn't happen, ignoring item. ItemTwo=$treatment") } } else { if (processDTO != null) { processList.add(processDTO) } processDTO = TempBasalProcessDTO( - itemOne= treatment, + itemOne = treatment, processOperation = TempBasalProcessDTO.Operation.Add) } } @@ -628,13 +618,13 @@ class MedtronicHistoryData @Inject constructor( val entryWithTempId = findDbEntry(tempBasalProcessDTO.itemOne, tbrRecords) - aapsLogger.debug(LTag.PUMP, "DD: entryWithTempId: " + (if (entryWithTempId==null) "null" else entryWithTempId.toString())) + aapsLogger.debug(LTag.PUMP, "DD: entryWithTempId: " + (if (entryWithTempId == null) "null" else entryWithTempId.toString())) val tbrEntry = tempBasalProcessDTO.itemOne.getDecodedDataEntry("Object") as TempBasalPair aapsLogger.debug(LTag.PUMP, String.format("DD: tbrEntry=%s, tempBasalProcessDTO=%s", gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO))) - if (entryWithTempId!=null) { + if (entryWithTempId != null) { aapsLogger.debug(LTag.PUMP, String.format("DD: tempIdEntry=%s, tbrEntry=%s, tempBasalProcessDTO=%s, pumpType=%s, serial=%s", gson.toJson(entryWithTempId), gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!)) @@ -681,7 +671,7 @@ class MedtronicHistoryData @Inject constructor( tbrEntry.insulinRate, (if (tbrEntry.isPercent) "%" else "U"), tempBasalProcessDTO.duration, medtronicPumpStatus.serialNumber!!, result)) - if (medtronicPumpStatus.runningTBR!=null) { + if (medtronicPumpStatus.runningTBR != null) { if (!isTBRActive(medtronicPumpStatus.runningTBR!!)) { medtronicPumpStatus.runningTBR = null } @@ -703,21 +693,16 @@ class MedtronicHistoryData @Inject constructor( } // collection } - - fun isTBRActive(dbEntry: PumpDbEntry) : Boolean { + fun isTBRActive(dbEntry: PumpDbEntry): Boolean { return isTBRActive(dbEntry.date, dbEntry.tbrData!!.durationInMinutes) } - - fun isTBRActive(startTimestamp: Long, durationMin: Int) : Boolean { + fun isTBRActive(startTimestamp: Long, durationMin: Int): Boolean { val endDate = startTimestamp + (durationMin * 60 * 1000) return (endDate > System.currentTimeMillis()) } - - - /** * findDbEntry - finds Db entries in database, while theoretically this should have same dateTime they * don't. Entry on pump is few seconds before treatment in AAPS, and on manual boluses on pump there @@ -742,7 +727,7 @@ class MedtronicHistoryData @Inject constructor( // pumpTime should never be null, but it can theoretically happen if reading of time from pump fails this.pumpTime?.let { proposedTime += (it.timeDifference * 1000) } - val proposedTimeDiff : LongArray = longArrayOf(proposedTime-(2*60*1000), proposedTime+(2L*60L*1000L)) + val proposedTimeDiff: LongArray = longArrayOf(proposedTime - (2 * 60 * 1000), proposedTime + (2L * 60L * 1000L)) val tempEntriesList: MutableList = mutableListOf() for (temporaryEntry in temporaryEntries) { @@ -753,7 +738,7 @@ class MedtronicHistoryData @Inject constructor( if (tempEntriesList.isEmpty()) { return null - } else if (tempEntriesList.size==1) { + } else if (tempEntriesList.size == 1) { return tempEntriesList[0] } @@ -788,7 +773,6 @@ class MedtronicHistoryData @Inject constructor( return null } - private fun processSuspends(tempBasalProcessList: List) { for (tempBasalProcess in tempBasalProcessList) { @@ -798,21 +782,20 @@ class MedtronicHistoryData @Inject constructor( tempBasalProcess.duration * 60 * 1000L, true, PumpSync.TemporaryBasalType.PUMP_SUSPEND, - tempBasalProcess.itemOne.pumpId!!, + tempBasalProcess.itemOne.pumpId, medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "processSuspends::syncTemporaryBasalWithPumpId [date=%d, rate=%.2f, duration=%d, pumpId=%d, pumpSerial=%s] - Result: %b", - tempBasalProcess.itemOne.atechDateTime, 0.0, tempBasalProcess.duration, tempBasalProcess.itemOne.pumpId!!, + tempBasalProcess.itemOne.atechDateTime, 0.0, tempBasalProcess.duration, tempBasalProcess.itemOne.pumpId, medtronicPumpStatus.serialNumber!!, result)) } } - // suspend/resume // no_delivery/prime & rewind/prime - private fun getSuspendRecords(): MutableList { + private fun getSuspendRecords(): MutableList { val outList: MutableList = mutableListOf() // suspend/resume @@ -822,7 +805,6 @@ class MedtronicHistoryData @Inject constructor( return outList } - private fun getSuspendResumeRecordsList(): List { val filteredItems = getFilteredItems(newHistory, // setOf(PumpHistoryEntryType.SuspendPump, PumpHistoryEntryType.ResumePump)) @@ -864,8 +846,8 @@ class MedtronicHistoryData @Inject constructor( var i = 0 while (i < filtered2Items.size) { outList.add(TempBasalProcessDTO( - itemOne= filtered2Items[i], - itemTwo= filtered2Items[i + 1], + itemOne = filtered2Items[i], + itemTwo = filtered2Items[i + 1], processOperation = TempBasalProcessDTO.Operation.Add)) i += 2 @@ -875,18 +857,17 @@ class MedtronicHistoryData @Inject constructor( return outList } - - private fun getNoDeliveryRewindPrimeRecordsList(): List { + private fun getNoDeliveryRewindPrimeRecordsList(): List { val primeItems: MutableList = getFilteredItems(newHistory, // setOf(PumpHistoryEntryType.Prime)) val outList: MutableList = ArrayList() if (primeItems.size == 0) return outList val filteredItems: MutableList = getFilteredItems(newHistory, // setOf(PumpHistoryEntryType.Prime, - PumpHistoryEntryType.Rewind, - PumpHistoryEntryType.NoDeliveryAlarm, - PumpHistoryEntryType.Bolus, - PumpHistoryEntryType.TempBasalCombined) + PumpHistoryEntryType.Rewind, + PumpHistoryEntryType.NoDeliveryAlarm, + PumpHistoryEntryType.Bolus, + PumpHistoryEntryType.TempBasalCombined) ) val tempData: MutableList = mutableListOf() var startedItems = false @@ -930,16 +911,16 @@ class MedtronicHistoryData @Inject constructor( items = getFilteredItems(tempData, PumpHistoryEntryType.NoDeliveryAlarm) if (items.size > 0) { outList.add(TempBasalProcessDTO( - itemOne=items[items.size - 1], - itemTwo= itemTwo, - processOperation=TempBasalProcessDTO.Operation.Add)) + itemOne = items[items.size - 1], + itemTwo = itemTwo, + processOperation = TempBasalProcessDTO.Operation.Add)) return outList } items = getFilteredItems(tempData, PumpHistoryEntryType.Rewind) if (items.size > 0) { outList.add(TempBasalProcessDTO( - itemOne=items[0], - processOperation=TempBasalProcessDTO.Operation.Add)) + itemOne = items[0], + processOperation = TempBasalProcessDTO.Operation.Add)) return outList } return outList @@ -964,34 +945,31 @@ class MedtronicHistoryData @Inject constructor( return DateTimeUtil.toMillisFromATD(atechDateTime) } - private fun getTDDType(): PumpHistoryEntryType { return if (medtronicUtil.medtronicPumpModel == null) { PumpHistoryEntryType.EndResultTotals } else when (medtronicUtil.medtronicPumpModel) { MedtronicDeviceType.Medtronic_515, - MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 + MedtronicDeviceType.Medtronic_715 -> PumpHistoryEntryType.DailyTotals515 MedtronicDeviceType.Medtronic_522, - MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 + MedtronicDeviceType.Medtronic_722 -> PumpHistoryEntryType.DailyTotals522 MedtronicDeviceType.Medtronic_523_Revel, MedtronicDeviceType.Medtronic_723_Revel, MedtronicDeviceType.Medtronic_554_Veo, - MedtronicDeviceType.Medtronic_754_Veo -> PumpHistoryEntryType.DailyTotals523 + MedtronicDeviceType.Medtronic_754_Veo -> PumpHistoryEntryType.DailyTotals523 - else -> { + else -> { PumpHistoryEntryType.EndResultTotals } } } - fun hasBasalProfileChanged(): Boolean { val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) aapsLogger.debug(LTag.PUMP, "hasBasalProfileChanged. Items: " + gson.toJson(filteredItems)) return filteredItems.size > 0 } - fun processLastBasalProfileChange(pumpType: PumpType, mdtPumpStatus: MedtronicPumpStatus) { val filteredItems: List = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile) aapsLogger.debug(LTag.PUMP, "processLastBasalProfileChange. Items: $filteredItems") @@ -1085,12 +1063,11 @@ class MedtronicHistoryData @Inject constructor( return outList } - private val logPrefix: String get() = "MedtronicHistoryData::" - companion object { + /** * Double bolus debug. We seem to have small problem with double Boluses (or sometimes also missing boluses * from history. This flag turns on debugging for that (default is off=false)... Debugging is pretty detailed, diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt index 2dc14b7c06..a3d373c5cf 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BasalProfile.kt @@ -33,7 +33,7 @@ class BasalProfile { private val aapsLogger: AAPSLogger @Expose - lateinit var rawData : ByteArray // store as byte array to make transport (via parcel) easier + lateinit var rawData: ByteArray // store as byte array to make transport (via parcel) easier private set private var listEntries: MutableList? = null @@ -49,7 +49,7 @@ class BasalProfile { } fun init() { - rawData = byteArrayOf(0,0,0x3f) + rawData = byteArrayOf(0, 0, 0x3f) } private fun setRawData(data: ByteArray): Boolean { @@ -268,7 +268,7 @@ class BasalProfile { // if (pumpType == null) // basalByHour[j] = current.rate // else - basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate) + basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate) } } return basalByHour @@ -291,9 +291,8 @@ class BasalProfile { return true } - - companion object { + const val MAX_RAW_DATA_SIZE = 48 * 3 + 1 private const val DEBUG_BASALPROFILE = false @@ -310,5 +309,15 @@ class BasalProfile { } return stringBuilder.toString() } + + @JvmStatic + fun isBasalProfileByHourUndefined(basalByHour: DoubleArray): Boolean { + for (i in 0..23) { + if (basalByHour[i] > 0.0) { + return false; + } + } + return true + } } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt index 6e205248fe..81653e6eb6 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt @@ -30,19 +30,24 @@ import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpBolusType * * Author: Andy {andy@atech-software.com} */ -class BolusDTO : PumpTimeStampedRecord() { +class BolusDTO constructor(atechDateTime: Long, + @Expose var requestedAmount: Double, + @Expose var deliveredAmount: Double, + @Expose var duration: Int = 0 + ) + : PumpTimeStampedRecord(atechDateTime) { - @Expose - var requestedAmount: Double? = null - - @Expose - var deliveredAmount: Double? = null + // @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 duration: Int? = null @Expose var bolusType: PumpBolusType? = null @@ -51,7 +56,7 @@ class BolusDTO : PumpTimeStampedRecord() { private val durationString: String get() { - var minutes = duration!! + var minutes = duration val h = minutes / 60 minutes -= h * 60 return StringUtil.getLeadingZero(h, 2) + ":" + StringUtil.getLeadingZero(minutes, 2) @@ -59,22 +64,22 @@ class BolusDTO : PumpTimeStampedRecord() { val value: String get() = if (bolusType === PumpBolusType.Normal || bolusType === PumpBolusType.Audio) { - getFormattedDecimal(deliveredAmount!!) + getFormattedDecimal(deliveredAmount) } else if (bolusType === PumpBolusType.Extended) { - String.format("AMOUNT_SQUARE=%s;DURATION=%s", getFormattedDecimal(deliveredAmount!!), + 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) + 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 + var valueTemp = value + valueTemp = valueTemp.replace("AMOUNT_SQUARE=", "Amount Square: ") + valueTemp = valueTemp.replace("AMOUNT=", "Amount: ") + valueTemp = valueTemp.replace("DURATION=", "Duration: ") + return valueTemp } override fun getFormattedDecimal(value: Double): String { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt index 32f52281a9..be99c3b34f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/ClockDTO.kt @@ -5,8 +5,9 @@ import org.joda.time.LocalDateTime /** * Created by andy on 2/27/19. */ -class ClockDTO { - var localDeviceTime: LocalDateTime? = null - var pumpTime: LocalDateTime? = null +class ClockDTO constructor(var localDeviceTime: LocalDateTime, + var pumpTime: LocalDateTime) { + // var localDeviceTime: LocalDateTime? = null + // var pumpTime: LocalDateTime? = null var timeDifference = 0 } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt index 8d0bd646b7..1f5cf7db0a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/PumpTimeStampedRecord.kt @@ -5,10 +5,10 @@ import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil /** * Created by andy on 6/2/18. */ -open class PumpTimeStampedRecord { +open class PumpTimeStampedRecord constructor(var atechDateTime: Long = 0) { var decimalPrecission = 2 - var atechDateTime: Long = 0 + // var atechDateTime: Long = 0 open fun getFormattedDecimal(value: Double): String? { return StringUtil.getFormatedValueUS(value, decimalPrecission) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt index 7fc26b2355..02ddb39f46 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt @@ -12,7 +12,7 @@ class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry, get() = itemOne.atechDateTime val pumpId: Long - get() = itemOne.pumpId!! + get() = itemOne.pumpId val duration: Int get() = if (itemTwo == null) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt index ca5add4bbc..75a399f1eb 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt @@ -54,7 +54,7 @@ class MedtronicHistoryActivity : DaggerActivity() { filteredHistoryList.addAll(list) } else { for (pumpHistoryEntry in list) { - if (pumpHistoryEntry.entryType!!.group === group) { + if (pumpHistoryEntry.entryType.group === group) { filteredHistoryList.add(pumpHistoryEntry) } } @@ -159,7 +159,7 @@ class MedtronicHistoryActivity : DaggerActivity() { val record = historyList[position] //if (record != null) { holder.timeView.text = record.dateTimeString - holder.typeView.text = record.entryType!!.description + holder.typeView.text = record.entryType.description holder.valueView.text = record.displayableValue //} } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt index 1310b483b5..22a9bc4c7f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -39,7 +39,7 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi private val mBinder: IBinder = LocalBinder() private var serialChanged = false - private var frequencies: Array? = null + lateinit var frequencies: Array private var rileyLinkAddress: String? = null private var rileyLinkAddressChanged = false private var encodingType: RileyLinkEncodingType? = null @@ -68,9 +68,9 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi * 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) + frequencies = arrayOf() + 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")) @@ -169,12 +169,12 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_frequency_not_set) return false } else { - if (pumpFrequency != frequencies!![0] && pumpFrequency != frequencies!![1]) { + 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 isFrequencyUS = pumpFrequency == frequencies[0] val newTargetFrequency = if (isFrequencyUS) // RileyLinkTargetFrequency.Medtronic_US else RileyLinkTargetFrequency.Medtronic_WorldWide if (rileyLinkServiceData.rileyLinkTargetFrequency != newTargetFrequency) { From d0f46d67453f5080db5e69bf2c2f70e92ca7e21e Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 16:55:07 +0100 Subject: [PATCH 30/39] - kotlin refactorings - MedtronicDeviceType --- .../plugins/pump/medtronic/MedtronicFragment.kt | 14 +++++++++----- .../plugins/pump/medtronic/MedtronicPumpPlugin.kt | 12 ++++++------ .../comm/MedtronicCommunicationManager.kt | 5 +++-- .../pump/medtronic/comm/MedtronicConverter.kt | 15 +++++++-------- .../comm/history/MedtronicHistoryDecoder.kt | 2 +- .../history/pump/MedtronicPumpHistoryDecoder.kt | 14 +++++++------- .../comm/history/pump/PumpHistoryEntry.kt | 13 +++++++------ .../comm/history/pump/PumpHistoryEntryType.kt | 14 ++++++++++---- .../medtronic/comm/ui/MedtronicUIPostprocessor.kt | 12 ++++++++---- .../pump/medtronic/data/MedtronicHistoryData.kt | 4 ++-- .../pump/medtronic/driver/MedtronicPumpStatus.kt | 4 +--- .../service/RileyLinkMedtronicService.kt | 7 +++++-- .../plugins/pump/medtronic/util/MedtronicUtil.kt | 12 ++++++------ 13 files changed, 72 insertions(+), 56 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index 58d328bd69..1a2a139189 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -209,13 +209,16 @@ class MedtronicFragment : DaggerFragment() { } ?: "-" when (medtronicPumpStatus.pumpDeviceState) { - PumpDeviceState.Sleeping -> binding.pumpStatusIcon.text = "{fa-bed} " // + pumpStatus.pumpDeviceState.name()); + PumpDeviceState.Sleeping -> + binding.pumpStatusIcon.text = "{fa-bed} " // + pumpStatus.pumpDeviceState.name()); + PumpDeviceState.NeverContacted, PumpDeviceState.WakingUp, PumpDeviceState.PumpUnreachable, PumpDeviceState.ErrorWhenCommunicating, PumpDeviceState.TimeoutWhenCommunicating, - PumpDeviceState.InvalidConfiguration -> binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) + PumpDeviceState.InvalidConfiguration -> + binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) PumpDeviceState.Active -> { val cmd = medtronicUtil.getCurrentCommand() @@ -223,10 +226,10 @@ class MedtronicFragment : DaggerFragment() { binding.pumpStatusIcon.text = " " + resourceHelper.gs(medtronicPumpStatus.pumpDeviceState.resourceId) else { aapsLogger.debug(LTag.PUMP, "Command: $cmd") - val cmdResourceId = cmd.resourceId!! + val cmdResourceId = cmd.resourceId //!! if (cmd == MedtronicCommandType.GetHistoryData) { binding.pumpStatusIcon.text = medtronicUtil.frameNumber?.let { - resourceHelper.gs(cmdResourceId, medtronicUtil.pageNumber, medtronicUtil.frameNumber) + resourceHelper.gs(cmdResourceId!!, medtronicUtil.pageNumber, medtronicUtil.frameNumber) } ?: resourceHelper.gs(R.string.medtronic_cmd_desc_get_history_request, medtronicUtil.pageNumber) } else { @@ -236,7 +239,8 @@ class MedtronicFragment : DaggerFragment() { } } - else -> aapsLogger.warn(LTag.PUMP, "Unknown pump state: " + medtronicPumpStatus.pumpDeviceState) + else -> + aapsLogger.warn(LTag.PUMP, "Unknown pump state: " + medtronicPumpStatus.pumpDeviceState) } val status = commandQueue.spannedStatus() diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index d67f05f4a4..8dfc8f4531 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -36,8 +36,8 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator -import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData @@ -236,7 +236,7 @@ class MedtronicPumpPlugin @Inject constructor( override fun getPumpInfo(): RileyLinkPumpInfo { val frequency = resourceHelper.gs(if (medtronicPumpStatus.pumpFrequency == "medtronic_pump_frequency_us_ca") R.string.medtronic_pump_frequency_us_ca else R.string.medtronic_pump_frequency_worldwide) - val model = if (medtronicPumpStatus.medtronicDeviceType == null) "???" else "Medtronic " + medtronicPumpStatus.medtronicDeviceType!!.pumpModel + val model = if (!medtronicUtil.isModelSet) "???" else "Medtronic " + medtronicPumpStatus.medtronicDeviceType.pumpModel val serialNumber = medtronicPumpStatus.serialNumber return RileyLinkPumpInfo(frequency, model, serialNumber) } @@ -417,7 +417,7 @@ class MedtronicPumpPlugin @Inject constructor( } // model (once) - if (medtronicUtil.medtronicPumpModel == null) { + if (!medtronicUtil.isModelSet) { rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel) } else { if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) { @@ -534,7 +534,6 @@ class MedtronicPumpPlugin @Inject constructor( return DateTimeUtil.toATechDate(timestamp) } - private var bolusDeliveryType = BolusDeliveryType.Idle private enum class BolusDeliveryType { @@ -1002,7 +1001,7 @@ class MedtronicPumpPlugin @Inject constructor( val runningTBR = medtronicPumpStatus.runningTBR - if (runningTBR!=null) { + if (runningTBR != null) { if (medtronicHistoryData.isTBRActive(runningTBR)) { val differenceTime = System.currentTimeMillis() - runningTBR.date @@ -1018,7 +1017,7 @@ class MedtronicPumpPlugin @Inject constructor( runningTBR.pumpType, runningTBR.serialNumber) - val differenceTimeMin = Math.floor(differenceTime/(60.0*1000.0)) + val differenceTimeMin = Math.floor(differenceTime / (60.0 * 1000.0)) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "canceling running TBR - syncTemporaryBasalWithPumpId [date=%d, pumpId=%d, rate=%.2f U, duration=%d, pumpSerial=%s] - Result: %b", runningTBR.date, runningTBR.pumpId!!, @@ -1175,6 +1174,7 @@ class MedtronicPumpPlugin @Inject constructor( } companion object { + var isBusy = false } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index c5db70ccd0..529fe69b34 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -136,8 +136,9 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth val dataResponse = medtronicConverter.decodeModel(pumpResponse.rawContent) val pumpModel = dataResponse as MedtronicDeviceType? val valid = pumpModel !== MedtronicDeviceType.Unknown_Device - if (medtronicUtil.medtronicPumpModel == null && valid) { - medtronicUtil.medtronicPumpModel = pumpModel + if (!medtronicUtil.isModelSet && valid) { + medtronicUtil.medtronicPumpModel = pumpModel!! + medtronicUtil.isModelSet = true } aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "isDeviceReachable. PumpModel is %s - Valid: %b (rssi=%d)", pumpModel!!.name, valid, radioResponse.rssi)) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt index 49416f66c8..497270e83a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt @@ -8,8 +8,6 @@ import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil 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.PumpSettingDTO -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.MedtronicDeviceType import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpConfigurationGroup import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil @@ -95,6 +93,7 @@ class MedtronicConverter @Inject constructor( if (pumpModel != MedtronicDeviceType.Unknown_Device) { if (!medtronicUtil.isModelSet) { medtronicUtil.medtronicPumpModel = pumpModel + medtronicUtil.isModelSet = true } } return pumpModel @@ -129,12 +128,12 @@ class MedtronicConverter @Inject constructor( public fun decodeRemainingInsulin(rawData: ByteArray?): Double { var startIdx = 0 val pumpModel = medtronicUtil.medtronicPumpModel - val strokes = pumpModel?.bolusStrokes ?: 10 + val strokes = pumpModel.bolusStrokes //?: 10 if (strokes == 40) { startIdx = 2 } val reqLength = startIdx + 1 - val value : Double + val value: Double value = if (reqLength >= rawData!!.size) { rawData[startIdx] / (1.0 * strokes) } else { @@ -208,7 +207,7 @@ class MedtronicConverter @Inject constructor( rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map) addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h", 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, map) // LOG.debug("Insulin concentration: " + rd[9]); @@ -249,7 +248,7 @@ class MedtronicConverter @Inject constructor( addSettingToMap("PCFG_MM_SRESERVOIR_WARNING_POINT", "" + ByteUtil.asUINT8(rd[19]), 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_CAPTURE_EVENT_ENABLE", parseResultEnable(rd[22].toInt()), PumpConfigurationGroup.Other, map) addSettingToMap("PCFG_OTHER_DEVICE_ENABLE", parseResultEnable(rd[23].toInt()), PumpConfigurationGroup.Other, map) @@ -273,7 +272,7 @@ class MedtronicConverter @Inject constructor( // 512 private fun decodeInsulinActionSetting(ai: ByteArray, map: MutableMap) { - 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", PumpConfigurationGroup.Insulin, map) } else { @@ -308,7 +307,7 @@ class MedtronicConverter @Inject constructor( } private fun is523orHigher(): Boolean { - return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher) + return MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher) } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 58e807f38d..1bed8c2809 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -44,7 +44,7 @@ abstract class MedtronicHistoryDecoder : MedtronicHi private fun checkPage(page: RawHistoryPage): MutableList { //val byteList: MutableList = mutableListOf() - if (medtronicUtil.medtronicPumpModel == null) { + if (!medtronicUtil.isModelSet) { aapsLogger.error(LTag.PUMPCOMM, "Device Type is not defined.") return mutableListOf() } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index 0a96a561f8..bcad0fa4bc 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -69,7 +69,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } val entryType = getByCode(opCode.toByte()) val pe = PumpHistoryEntry() - pe.setEntryType(medtronicUtil.medtronicPumpModel!!, entryType!!) + pe.setEntryType(medtronicUtil.medtronicPumpModel, entryType, if (entryType == PumpHistoryEntryType.UnknownBasePacket) opCode.toByte() else null) pe.offset = counter counter++ if (counter >= 1022) { @@ -91,7 +91,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } special = true } else { - for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel!!) - 1) { + for (j in 0 until entryType.getTotalLength(medtronicUtil.medtronicPumpModel) - 1) { try { listRawData.add(dataClearInput[counter]) counter++ @@ -111,7 +111,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( if (pe.entryType === PumpHistoryEntryType.UnknownBasePacket) { 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, special) val decoded = decodeRecord(pe) if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { @@ -299,7 +299,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val offset = body!![0] * 1000 * 30 * 60 var rate: Float? = null 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 } @@ -318,7 +318,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( val body = entry.body!! val dto = BolusWizardDTO() 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 bolusStrokes = 40.0f dto.carbs = ((body[1] and 0x0c.toByte()).toInt() shl 6) + body[0] @@ -421,9 +421,9 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBolus(entry: PumpHistoryEntry) { - var bolus: BolusDTO? + val bolus: BolusDTO? val data = entry.head!! - if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel!!, MedtronicDeviceType.Medtronic_523andHigher)) { + if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { bolus = BolusDTO(atechDateTime = entry.atechDateTime, requestedAmount = ByteUtil.toInt(data.get(0), data.get(1)) / 40.0, deliveredAmount = ByteUtil.toInt(data.get(2), data.get(3)) / 40.0, diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index 45766ec6d8..ea6d521e74 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -1,6 +1,5 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump -import android.util.Log import com.google.gson.annotations.Expose import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil @@ -36,15 +35,16 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { field = value } - fun setEntryType(medtronicDeviceType: MedtronicDeviceType, entryType: PumpHistoryEntryType) { + fun setEntryType(medtronicDeviceType: MedtronicDeviceType, entryType: PumpHistoryEntryType, opCode: Byte? = null) { this.entryType = entryType sizes[0] = entryType.getHeadLength(medtronicDeviceType) sizes[1] = entryType.dateLength sizes[2] = entryType.getBodyLength(medtronicDeviceType) if (isEntryTypeSet() && atechDateTime != 0L) pumpId = generatePumpId() + this.opCode = opCode } - override fun generatePumpId() : Long { + override fun generatePumpId(): Long { return entryType.code + atechDateTime * 1000L } @@ -103,6 +103,7 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { } class Comparator : java.util.Comparator { + override fun compare(o1: PumpHistoryEntry, o2: PumpHistoryEntry): Int { val data = (o2.atechDateTime - o1.atechDateTime).toInt() return if (data != 0) data else o2.entryType.code - o1.entryType.code @@ -111,7 +112,7 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { override var pumpId: Long = 0L get() { - if (field==0L) { + if (field == 0L) { field = generatePumpId() } return field @@ -120,9 +121,9 @@ class PumpHistoryEntry : MedtronicHistoryEntry() { field = pumpId } - fun hasBolusChanged(entry: PumpHistoryEntry) : Boolean { + fun hasBolusChanged(entry: PumpHistoryEntry): Boolean { if (entryType == PumpHistoryEntryType.Bolus) { - val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO + val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO if (entry.entryType == PumpHistoryEntryType.Bolus) { val otherOne: BolusDTO = entry.decodedData["Object"] as BolusDTO diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt index 3151131838..09352e8e5a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt @@ -12,10 +12,11 @@ import java.util.* * Author: Andy {andy.rozman@gmail.com} */ enum class PumpHistoryEntryType // implements CodeEnum - constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int = 2, date: Int = 5, body: Int = 0) { +constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int = 2, date: Int = 5, body: Int = 0) { // all commented out are probably not the real items - None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), Bolus(0x01, "Bolus", PumpHistoryEntryGroup.Bolus, 4, 5, 0), // 523+[H=8] 9/13 + None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), + Bolus(0x01, "Bolus", PumpHistoryEntryGroup.Bolus, 4, 5, 0), // 523+[H=8] 9/13 Prime(0x03, "Prime", PumpHistoryEntryGroup.Prime, 5, 5, 0), // // /**/EventUnknown_MM522_0x05((byte) 0x05, "Unknown Event 0x05", PumpHistoryEntryGroup.Unknown, 2, 5, 28), // @@ -40,6 +41,7 @@ enum class PumpHistoryEntryType // implements CodeEnum ClearSettings(0x22, "Clear Settings", PumpHistoryEntryGroup.Configuration), // ChangeChildBlockEnable(0x23, "Change Child Block Enable", PumpHistoryEntryGroup.Configuration), // ChangeMaxBolus(0x24, "Change Max Bolus", PumpHistoryEntryGroup.Configuration), // + // /**/EventUnknown_MM522_0x25(0x25, "Unknown Event 0x25", PumpHistoryEntryGroup.Unknown), // 8? EnableDisableRemote(0x26, "Enable/Disable Remote", PumpHistoryEntryGroup.Configuration, 2, 5, 14), // 2, 5, 14 V6:2,5,14 ChangeRemoteId(0x27, "Change Remote ID", PumpHistoryEntryGroup.Configuration), // ?? @@ -54,6 +56,7 @@ enum class PumpHistoryEntryType // implements CodeEnum LowReservoir(0x34, "Low Reservoir", PumpHistoryEntryGroup.Notification), // ChangeAlarmClock(0x35, "Change Alarm Clock", PumpHistoryEntryGroup.Configuration), // ChangeMeterId(0x36, "Change Meter ID", PumpHistoryEntryGroup.Configuration), // + // /**/EventUnknown_MM512_0x37(0x37, "Unknown Event 0x37", PumpHistoryEntryGroup.Unknown), // V:MM512 // /**/EventUnknown_MM512_0x38(0x38, "Unknown Event 0x38", PumpHistoryEntryGroup.Unknown), // BGReceived512(0x39, "BG Received (512)", PumpHistoryEntryGroup.Glucose, 2, 5, 3), // @@ -69,6 +72,7 @@ enum class PumpHistoryEntryType // implements CodeEnum JournalEntryInsulinMarker(0x42, "Insulin Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 0), // V6 = body(0)/was=1 JournalEntryOtherMarker(0x43, "Other Marker", PumpHistoryEntryGroup.Bolus, 2, 5, 1), // V6 = body(1) was=0 EnableSensorAutoCal(0x44, "Enable Sensor AutoCal", PumpHistoryEntryGroup.Glucose), // + // /**/EventUnknown_MM522_0x45(0x45, "Unknown Event 0x45", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // // /**/EventUnknown_MM522_0x46(0x46, "Unknown Event 0x46", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // // /**/EventUnknown_MM522_0x47(0x47, "Unknown Event 0x47", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // @@ -110,6 +114,7 @@ enum class PumpHistoryEntryType // implements CodeEnum DailyTotals522(0x6d, "Daily Totals (522)", PumpHistoryEntryGroup.Statistic, 1, 2, 41), // DailyTotals523(0x6e, "Daily Totals (523)", PumpHistoryEntryGroup.Statistic, 1, 2, 49), // 1102014-03-17T00:00:00 ChangeCarbUnits(0x6f.toByte(), "Change Carb Units", PumpHistoryEntryGroup.Configuration), // + // /**/EventUnknown_MM522_0x70((byte) 0x70, "Unknown Event 0x70", PumpHistoryEntryGroup.Unknown, 2, 5, 1), // BasalProfileStart(0x7b, "Basal Profile Start", PumpHistoryEntryGroup.Basal, 2, 5, 3), // // 722 ChangeWatchdogEnable(0x7c, "Change Watchdog Enable", PumpHistoryEntryGroup.Configuration), // @@ -133,6 +138,7 @@ enum class PumpHistoryEntryType // implements CodeEnum UnknownBasePacket(0xff.toByte(), "Unknown Base Packet", PumpHistoryEntryGroup.Unknown); companion object { + private val opCodeMap: MutableMap = HashMap() fun setSpecialRulesForEntryTypes() { EndResultTotals.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 3)) @@ -143,9 +149,9 @@ enum class PumpHistoryEntryType // implements CodeEnum ChangeSensorSetup2.addSpecialRuleBody(SpecialRule(MedtronicDeviceType.Medtronic_523andHigher, 34)) } - fun getByCode(opCode: Byte): PumpHistoryEntryType? { + fun getByCode(opCode: Byte): PumpHistoryEntryType { return if (opCodeMap.containsKey(opCode)) { - opCodeMap[opCode] + opCodeMap[opCode]!! } else { UnknownBasePacket } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index 11dbc9bb46..7bcf1934e3 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -102,11 +102,15 @@ class MedtronicUIPostprocessor @Inject constructor( MedtronicCommandType.GetBatteryStatus -> { val batteryStatusDTO = uiTask.result as BatteryStatusDTO? - medtronicPumpStatus.batteryRemaining = batteryStatusDTO!!.getCalculatedPercent(medtronicPumpStatus.batteryType) - if (batteryStatusDTO.voltage != null) { - medtronicPumpStatus.batteryVoltage = batteryStatusDTO.voltage + if (batteryStatusDTO != null) { + 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())) + } else { + medtronicPumpStatus.batteryVoltage = null } - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "BatteryStatus: %s", batteryStatusDTO.toString())) } MedtronicCommandType.PumpModel -> { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index f251788366..4f32043e66 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -946,7 +946,7 @@ class MedtronicHistoryData @Inject constructor( } private fun getTDDType(): PumpHistoryEntryType { - return if (medtronicUtil.medtronicPumpModel == null) { + return if (!medtronicUtil.isModelSet) { PumpHistoryEntryType.EndResultTotals } else when (medtronicUtil.medtronicPumpModel) { MedtronicDeviceType.Medtronic_515, @@ -1015,7 +1015,7 @@ class MedtronicHistoryData @Inject constructor( for (pumpHistoryEntry in TBRs_Input) { if (map.containsKey(pumpHistoryEntry.DT)) { medtronicPumpHistoryDecoder.decodeTempBasal(map[pumpHistoryEntry.DT]!!, pumpHistoryEntry) - pumpHistoryEntry.setEntryType(medtronicUtil.medtronicPumpModel!!, PumpHistoryEntryType.TempBasalCombined) + pumpHistoryEntry.setEntryType(medtronicUtil.medtronicPumpModel, PumpHistoryEntryType.TempBasalCombined) TBRs.add(pumpHistoryEntry) map.remove(pumpHistoryEntry.DT) } else { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index 1ebad72414..6ac69039cb 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -44,7 +44,7 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour rxBus.send(EventRileyLinkDeviceStatusChange(pumpDeviceState)) } - var medtronicDeviceType: MedtronicDeviceType? = null + var medtronicDeviceType: MedtronicDeviceType = MedtronicDeviceType.Medtronic_522 var medtronicPumpMap: MutableMap = mutableMapOf() var medtronicDeviceTypeMap: MutableMap = mutableMapOf() var basalProfileStatus = BasalProfileStatus.NotInitialized @@ -87,7 +87,6 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour medtronicPumpMap["754"] = PumpType.MEDTRONIC_554_754_VEO } - val basalProfileForHour: Double get() { if (basalsByHour != null) { @@ -115,7 +114,6 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour override val errorInfo: String get() = if (errorDescription == null) "-" else errorDescription!! - val tbrRemainingTime: Int? get() { if (tempBasalStart == null) return null diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt index 22a9bc4c7f..ad56ff6ad9 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -17,6 +17,7 @@ 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.defs.MedtronicDeviceType 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 @@ -109,7 +110,8 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi val oldId = rileyLinkServiceData.pumpID rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes) if (oldId != null && oldId != pumpID) { - medtronicUtil.medtronicPumpModel = null // if we change pumpId, model probably changed too + medtronicUtil.medtronicPumpModel = MedtronicDeviceType.Medtronic_522 // if we change pumpId, model probably changed too + medtronicUtil.isModelSet = false } return } @@ -119,6 +121,7 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi } inner class LocalBinder : Binder() { + val serviceInstance: RileyLinkMedtronicService get() = this@RileyLinkMedtronicService } @@ -158,7 +161,7 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi return false } else { val pumpType = medtronicPumpStatus.medtronicPumpMap[pumpTypePart] - medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.medtronicDeviceTypeMap[pumpTypePart] + medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.medtronicDeviceTypeMap[pumpTypePart]!! medtronicPumpStatus.pumpType = pumpType!! medtronicPumpPlugin.pumpType = pumpType if (pumpTypePart.startsWith("7")) medtronicPumpStatus.reservoirFullUnits = 300 else medtronicPumpStatus.reservoirFullUnits = 176 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt index 72574a99b0..9d54d2941f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt @@ -48,7 +48,6 @@ class MedtronicUtil @Inject constructor( var pumpTime: ClockDTO? = null var gsonInstance = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() - fun getTimeFrom30MinInterval(interval: Int): LocalTime { return if (interval % 2 == 0) { LocalTime(interval / 2, 0) @@ -74,7 +73,7 @@ class MedtronicUtil @Inject constructor( } fun getBolusStrokes(amount: Double): ByteArray { - val strokesPerUnit = medtronicPumpStatus.medtronicDeviceType!!.bolusStrokes + val strokesPerUnit = medtronicPumpStatus.medtronicDeviceType.bolusStrokes val length: Int val scrollRate: Int if (strokesPerUnit >= 40) { @@ -217,10 +216,10 @@ class MedtronicUtil @Inject constructor( return true } - val isModelSet: Boolean - get() = medtronicPumpStatus.medtronicDeviceType != null + var isModelSet: Boolean = false + // get() = medtronicPumpStatus.medtronicDeviceType != null - var medtronicPumpModel: MedtronicDeviceType? + var medtronicPumpModel: MedtronicDeviceType get() = medtronicPumpStatus.medtronicDeviceType set(medtronicPumpModel) { medtronicPumpStatus.medtronicDeviceType = medtronicPumpModel @@ -248,6 +247,7 @@ class MedtronicUtil @Inject constructor( } companion object { + const val isLowLevelDebug = true fun getIntervalFromMinutes(minutes: Int): Int { return minutes / 30 @@ -294,7 +294,7 @@ class MedtronicUtil @Inject constructor( //var length = 1 var scrollRate = 1 if (strokesPerUnit >= 40) { - // length = 2 + // length = 2 // 40-stroke pumps scroll faster for higher unit values if (amount > 10) scrollRate = 4 else if (amount > 1) scrollRate = 2 From fb5ff409f8772c6f2e50da46e00695a9ca486777 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 22 May 2021 23:46:32 +0100 Subject: [PATCH 31/39] - kotlin refactoring !! --- .../pump/common/utils/ProfileUtil.java | 54 -------- .../plugins/pump/common/utils/ProfileUtil.kt | 81 ++++++++++++ .../pump/medtronic/MedtronicPumpPlugin.kt | 116 +++++++++--------- .../comm/MedtronicCommunicationManager.kt | 8 +- .../pump/medtronic/comm/MedtronicConverter.kt | 82 +++---------- .../comm/history/MedtronicHistoryDecoder.kt | 50 +++----- .../comm/history/MedtronicHistoryEntry.kt | 42 +++---- .../history/MedtronicHistoryEntryInterface.kt | 4 +- .../comm/history/cgms/CGMSHistoryEntry.kt | 22 ++-- .../comm/history/cgms/CGMSHistoryEntryType.kt | 19 +-- .../cgms/MedtronicCGMSHistoryDecoder.kt | 47 +++---- .../pump/MedtronicPumpHistoryDecoder.kt | 40 +++--- .../comm/history/pump/PumpHistoryEntryType.kt | 67 +++------- .../medtronic/comm/message/PumpMessage.kt | 7 +- .../comm/ui/MedtronicUIPostprocessor.kt | 61 +++++---- .../medtronic/data/MedtronicHistoryData.kt | 46 +++---- .../pump/medtronic/data/dto/BolusDTO.kt | 9 +- .../pump/medtronic/data/dto/DailyTotalsDTO.kt | 31 ++--- .../medtronic/defs/MedtronicCommandType.kt | 24 ++-- .../medtronic/driver/MedtronicPumpStatus.kt | 6 +- .../service/RileyLinkMedtronicService.kt | 13 +- .../pump/medtronic/util/MedtronicUtil.kt | 6 +- 22 files changed, 385 insertions(+), 450 deletions(-) delete mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java create mode 100644 core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java deleted file mode 100644 index badd401083..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.java +++ /dev/null @@ -1,54 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.common.utils; - -import java.util.Locale; - -import info.nightscout.androidaps.interfaces.Profile; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; - -public class ProfileUtil { - - - public static String getProfileDisplayable(Profile profile, PumpType pumpType) { - - StringBuilder stringBuilder = new StringBuilder(); - - for (Profile.ProfileValue basalValue : profile.getBasalValues()) { - - double basalValueValue = pumpType.determineCorrectBasalSize(basalValue.getValue()); - - int hour = basalValue.getTimeAsSeconds() / (60 * 60); - - stringBuilder.append((hour < 10 ? "0" : "") + hour + ":00"); - - stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)); - stringBuilder.append(", "); - } - if (stringBuilder.length() > 3) - return stringBuilder.substring(0, stringBuilder.length() - 2); - else - return stringBuilder.toString(); - } - - public static String getBasalProfilesDisplayable(Profile.ProfileValue[] profiles, PumpType pumpType) { - - StringBuilder stringBuilder = new StringBuilder(); - - for (Profile.ProfileValue basalValue : profiles) { - - double basalValueValue = pumpType.determineCorrectBasalSize(basalValue.getValue()); - - int hour = basalValue.getTimeAsSeconds() / (60 * 60); - - stringBuilder.append((hour < 10 ? "0" : "") + hour + ":00"); - - stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)); - stringBuilder.append(", "); - } - if (stringBuilder.length() > 3) - return stringBuilder.substring(0, stringBuilder.length() - 2); - else - return stringBuilder.toString(); - } - - -} diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt new file mode 100644 index 0000000000..6559d80f80 --- /dev/null +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt @@ -0,0 +1,81 @@ +package info.nightscout.androidaps.plugins.pump.common.utils + +import info.nightscout.androidaps.interfaces.Profile +import info.nightscout.androidaps.interfaces.Profile.ProfileValue +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import java.util.* + +object ProfileUtil { + + fun getProfileDisplayable(profile: Profile, pumpType: PumpType): String { + val stringBuilder = StringBuilder() + for (basalValue in profile.getBasalValues()) { + val basalValueValue = pumpType.determineCorrectBasalSize(basalValue.value) + val hour = basalValue.timeAsSeconds / (60 * 60) + stringBuilder.append((if (hour < 10) "0" else "") + hour + ":00") + stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) + stringBuilder.append(", ") + } + return if (stringBuilder.length > 3) stringBuilder.substring(0, stringBuilder.length - 2) else stringBuilder.toString() + } + + @JvmStatic + fun getBasalProfilesDisplayable(profiles: Array, pumpType: PumpType): String { + val stringBuilder = StringBuilder() + for (basalValue in profiles) { + val basalValueValue = pumpType.determineCorrectBasalSize(basalValue.value) + val hour = basalValue.timeAsSeconds / (60 * 60) + stringBuilder.append((if (hour < 10) "0" else "") + hour + ":00") + stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) + stringBuilder.append(", ") + } + return if (stringBuilder.length > 3) stringBuilder.substring(0, stringBuilder.length - 2) else stringBuilder.toString() + } + + @JvmStatic + fun getBasalProfilesDisplayableAsStringOfArray(profile: Profile, pumpType: PumpType): String? { + val stringBuilder = java.lang.StringBuilder() + // for (basalValue in profiles) { + // val basalValueValue = pumpType.determineCorrectBasalSize(basalValue.value) + // val hour = basalValue.timeAsSeconds / (60 * 60) + // stringBuilder.append((if (hour < 10) "0" else "") + hour + ":00") + // stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) + // stringBuilder.append(", ") + // } + // return if (stringBuilder.length > 3) stringBuilder.substring(0, stringBuilder.length - 2) else stringBuilder.toString() + + var entriesCopy = profile.getBasalValues() + + for (i in entriesCopy.indices) { + val current = entriesCopy[i] + // var currentTime = if (current.startTime_raw % 2 == 0) current.startTime_raw.toInt() else current.startTime_raw - 1 + // currentTime = currentTime * 30 / 60 + val currentTime = current.timeAsSeconds / (60 * 60) + + var lastHour: Int + lastHour = if (i + 1 == entriesCopy.size) { + 24 + } else { + val basalProfileEntry = entriesCopy[i + 1] + //val rawTime = if (basalProfileEntry.startTime_raw % 2 == 0) basalProfileEntry.startTime_raw.toInt() else basalProfileEntry.startTime_raw - 1 + //rawTime * 30 / 60 + basalProfileEntry.timeAsSeconds / (60 * 60) + } + + // System.out.println("Current time: " + currentTime + " Next Time: " + lastHour); + for (j in currentTime until lastHour) { + // if (pumpType == null) + // basalByHour[j] = current.rate + // else + //basalByHour[j] = pumpType.determineCorrectBasalSize(current.value) + + stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", pumpType.determineCorrectBasalSize(current.value))) + stringBuilder.append(" ") + } + } + + return stringBuilder.toString().trim() + + } + +} \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 8dfc8f4531..a77cee4a57 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -38,6 +38,7 @@ import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil +import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryResult import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData @@ -102,12 +103,12 @@ class MedtronicPumpPlugin @Inject constructor( injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage ), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator { - private var rileyLinkMedtronicService: RileyLinkMedtronicService? = null + private lateinit var rileyLinkMedtronicService: RileyLinkMedtronicService // variables for handling statuses and history private var firstRun = true private var isRefresh = false - private val statusRefreshMap: MutableMap = HashMap() + private val statusRefreshMap: MutableMap = mutableMapOf() private var isInitialized = false private var lastPumpHistoryEntry: PumpHistoryEntry? = null private val busyTimestamps: MutableList = ArrayList() @@ -119,19 +120,20 @@ class MedtronicPumpPlugin @Inject constructor( serviceConnection = object : ServiceConnection { override fun onServiceDisconnected(name: ComponentName) { aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is disconnected") - rileyLinkMedtronicService = null + //rileyLinkMedtronicService = null } override fun onServiceConnected(name: ComponentName, service: IBinder) { aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is connected") val mLocalBinder = service as RileyLinkMedtronicService.LocalBinder rileyLinkMedtronicService = mLocalBinder.serviceInstance - rileyLinkMedtronicService!!.verifyConfiguration() + isServiceSet = true + rileyLinkMedtronicService.verifyConfiguration() Thread(Runnable { for (i in 0..19) { SystemClock.sleep(5000) aapsLogger.debug(LTag.PUMP, "Starting Medtronic-RileyLink service") - if (rileyLinkMedtronicService!!.setNotInPreInit()) { + if (rileyLinkMedtronicService.setNotInPreInit()) { break } } @@ -227,10 +229,9 @@ class MedtronicPumpPlugin @Inject constructor( } // Pump Plugin - private val isServiceSet: Boolean - get() = rileyLinkMedtronicService != null + private var isServiceSet: Boolean = false - override fun getRileyLinkService(): RileyLinkMedtronicService? { + override fun getRileyLinkService(): RileyLinkMedtronicService { return rileyLinkMedtronicService } @@ -292,12 +293,12 @@ class MedtronicPumpPlugin @Inject constructor( override fun isConnected(): Boolean { if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnected") - return isServiceSet && rileyLinkMedtronicService!!.isInitialized + return isServiceSet && rileyLinkMedtronicService.isInitialized } override fun isConnecting(): Boolean { if (displayConnectionMessages) aapsLogger.debug(LTag.PUMP, "MedtronicPumpPlugin::isConnecting") - return !isServiceSet || !rileyLinkMedtronicService!!.isInitialized + return !isServiceSet || !rileyLinkMedtronicService.isInitialized } override fun getPumpStatus(reason: String) { @@ -328,7 +329,7 @@ class MedtronicPumpPlugin @Inject constructor( aapsLogger.debug(LTag.PUMP, "RileyLink unreachable.") return false } - return !rileyLinkMedtronicService!!.deviceCommunicationManager.isDeviceReachable + return !rileyLinkMedtronicService.deviceCommunicationManager.isDeviceReachable } private fun refreshAnyStatusThatNeedsToBeRefreshed() { @@ -352,9 +353,9 @@ class MedtronicPumpPlugin @Inject constructor( } // execute - val refreshTypesNeededToReschedule: MutableSet = mutableSetOf() + val refreshTypesNeededToReschedule: MutableSet = mutableSetOf() for ((key, value) in statusRefresh!!) { - if (value!! > 0 && System.currentTimeMillis() > value) { + if (value > 0 && System.currentTimeMillis() > value) { when (key) { MedtronicStatusRefreshType.PumpHistory -> { readPumpHistory() @@ -367,13 +368,13 @@ class MedtronicPumpPlugin @Inject constructor( } MedtronicStatusRefreshType.BatteryStatus, MedtronicStatusRefreshType.RemainingInsulin -> { - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) refreshTypesNeededToReschedule.add(key) resetTime = true } MedtronicStatusRefreshType.Configuration -> { - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(key.getCommandType(medtronicUtil.medtronicPumpModel)!!) resetTime = true } } @@ -388,9 +389,9 @@ class MedtronicPumpPlugin @Inject constructor( if (resetTime) medtronicPumpStatus.setLastCommunicationToNow() } - private fun doWeHaveAnyStatusNeededRefereshing(statusRefresh: Map?): Boolean { + private fun doWeHaveAnyStatusNeededRefereshing(statusRefresh: Map?): Boolean { for ((_, value) in statusRefresh!!) { - if (value!! > 0 && System.currentTimeMillis() > value) { + if (value > 0 && System.currentTimeMillis() > value) { return true } } @@ -402,9 +403,9 @@ class MedtronicPumpPlugin @Inject constructor( } private fun initializePump(): Boolean { - if (rileyLinkMedtronicService == null) return false + if (!isServiceSet) return false aapsLogger.info(LTag.PUMP, logPrefix + "initializePump - start") - rileyLinkMedtronicService!!.deviceCommunicationManager.setDoWakeUpBeforeCommand(false) + rileyLinkMedtronicService.deviceCommunicationManager.setDoWakeUpBeforeCommand(false) setRefreshButtonEnabled(false) if (isRefresh) { if (isPumpNotReachable) { @@ -418,7 +419,7 @@ class MedtronicPumpPlugin @Inject constructor( // model (once) if (!medtronicUtil.isModelSet) { - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel) } else { if (medtronicPumpStatus.medtronicDeviceType !== medtronicUtil.medtronicPumpModel) { aapsLogger.warn(LTag.PUMP, logPrefix + "Configured pump is not the same as one detected.") @@ -432,19 +433,19 @@ class MedtronicPumpPlugin @Inject constructor( readPumpHistory() // remaining insulin (>50 = 4h; 50-20 = 1h; 15m) - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin) scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10) // remaining power (1h) - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus) scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20) // configuration (once and then if history shows config changes) - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(getSettings(medtronicUtil.medtronicPumpModel)) // read profile (once, later its controlled by isThisProfileSet method) basalProfiles - val errorCount = rileyLinkMedtronicService!!.medtronicUIComm.invalidResponsesCount + val errorCount = rileyLinkMedtronicService.medtronicUIComm.invalidResponsesCount if (errorCount >= 5) { aapsLogger.error("Number of error counts was 5 or more. Starting tunning.") setRefreshButtonEnabled(true) @@ -464,9 +465,9 @@ class MedtronicPumpPlugin @Inject constructor( private val basalProfiles: Unit get() { - val medtronicUITask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + val medtronicUITask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) if (medtronicUITask.responseType === MedtronicUIResponseType.Error) { - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD) } } @@ -492,14 +493,16 @@ class MedtronicPumpPlugin @Inject constructor( // int index = 0; if (basalsByHour == null) return true // we don't want to set profile again, unless we are sure val stringBuilder = StringBuilder("Requested Basals (h): ") + stringBuilder.append(ProfileUtil.getBasalProfilesDisplayableAsStringOfArray(profile, this.pumpType)) + for (basalValue in profile.getBasalValues()) { val basalValueValue = pumpDescription.pumpType.determineCorrectBasalSize(basalValue.value) val hour = basalValue.timeAsSeconds / (60 * 60) if (!isSame(basalsByHour[hour], basalValueValue)) { invalid = true } - stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) - stringBuilder.append(" ") + // stringBuilder.append(String.format(Locale.ENGLISH, "%.3f", basalValueValue)) + // stringBuilder.append(" ") } aapsLogger.debug(LTag.PUMP, stringBuilder.toString()) if (!invalid) { @@ -552,10 +555,10 @@ class MedtronicPumpPlugin @Inject constructor( return } medtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable, rxBus) - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) var clock = medtronicUtil.pumpTime if (clock == null) { // retry - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetRealTimeClock) clock = medtronicUtil.pumpTime } if (clock == null) return @@ -563,7 +566,7 @@ class MedtronicPumpPlugin @Inject constructor( if (timeDiff > 20) { if (clock.localDeviceTime.year <= 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)) - rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock) + rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetRealTimeClock) if (clock.timeDifference == 0) { val notification = Notification(Notification.INSIGHT_DATE_TIME_UPDATED, resourceHelper.gs(R.string.pump_time_updated), Notification.INFO, 60) rxBus.send(EventNewNotification(notification)) @@ -612,7 +615,7 @@ class MedtronicPumpPlugin @Inject constructor( bolusDeliveryType = BolusDeliveryType.Delivering // LOG.debug("MedtronicPumpPlugin::deliverBolus - Start delivery"); - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, + val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, arrayListOf(detailedBolusInfo.insulin)) val response = responseTask.result as Boolean? setRefreshButtonEnabled(true) @@ -734,7 +737,7 @@ class MedtronicPumpPlugin @Inject constructor( aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - TBR running - so canceling it.") // CANCEL - val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) + val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) val response = responseTask2.result as Boolean? if (response!!) { aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") @@ -747,21 +750,18 @@ class MedtronicPumpPlugin @Inject constructor( } // now start new TBR - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal, + val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal, arrayListOf(absoluteRate, durationInMinutes)) val response = responseTask.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - setTBR. Response: " + response) - return if (response!!) { + return if (response == null || !response) { + finishAction("TBR") + PumpEnactResult(injector).success(false).enacted(false) // + .comment(R.string.medtronic_cmd_tbr_could_not_be_delivered) + } else { medtronicPumpStatus.tempBasalStart = Date() medtronicPumpStatus.tempBasalAmount = absoluteRate medtronicPumpStatus.tempBasalLength = durationInMinutes - // val tempStart = TemporaryBasal(injector) // - // .date(System.currentTimeMillis()) // - // .duration(durationInMinutes) // - // .absolute(absoluteRate) // - // .source(Source.USER) - // - // activePlugin.activeTreatments.addToHistoryTempBasal(tempStart) val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) @@ -771,10 +771,6 @@ class MedtronicPumpPlugin @Inject constructor( finishAction("TBR") PumpEnactResult(injector).success(true).enacted(true) // .absolute(absoluteRate).duration(durationInMinutes) - } else { - finishAction("TBR") - PumpEnactResult(injector).success(false).enacted(false) // - .comment(R.string.medtronic_cmd_tbr_could_not_be_delivered) } } @@ -858,7 +854,7 @@ class MedtronicPumpPlugin @Inject constructor( } //aapsLogger.debug(LTag.PUMP, "HST: Target Date: " + targetDate); - val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData, + val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.GetHistoryData, arrayListOf(/*lastPumpHistoryEntry*/ null, targetDate) as ArrayList?) if (debugHistory) aapsLogger.debug(LTag.PUMP, "HST: After task") val historyResult = responseTask2.result as PumpHistoryResult? @@ -932,10 +928,10 @@ class MedtronicPumpPlugin @Inject constructor( @Synchronized private fun workWithStatusRefresh(action: StatusRefreshAction, // statusRefreshType: MedtronicStatusRefreshType?, // - time: Long?): Map? { + time: Long?): Map? { return when (action) { StatusRefreshAction.Add -> { - statusRefreshMap[statusRefreshType] = time + statusRefreshMap[statusRefreshType!!] = time!! null } @@ -955,7 +951,7 @@ class MedtronicPumpPlugin @Inject constructor( } private fun readTBR(): TempBasalPair? { - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal) + val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal) return if (responseTask.hasData()) { val tbr = responseTask.result as TempBasalPair? @@ -993,7 +989,7 @@ class MedtronicPumpPlugin @Inject constructor( return PumpEnactResult(injector).success(false).enacted(false) .comment(R.string.medtronic_cmd_cant_read_tbr) } - val responseTask2 = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) + val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) val response = responseTask2.result as Boolean? finishAction("TBR") return if (response!!) { @@ -1020,9 +1016,9 @@ class MedtronicPumpPlugin @Inject constructor( val differenceTimeMin = Math.floor(differenceTime / (60.0 * 1000.0)) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "canceling running TBR - syncTemporaryBasalWithPumpId [date=%d, pumpId=%d, rate=%.2f U, duration=%d, pumpSerial=%s] - Result: %b", - runningTBR.date, runningTBR.pumpId!!, + runningTBR.date, runningTBR.pumpId, tbrData.rate, differenceTimeMin.toInt(), - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) } } @@ -1046,7 +1042,7 @@ class MedtronicPumpPlugin @Inject constructor( } override fun serialNumber(): String { - return medtronicPumpStatus.serialNumber!! + return medtronicPumpStatus.serialNumber } override fun setNewBasalProfile(profile: Profile): PumpEnactResult { @@ -1077,15 +1073,15 @@ class MedtronicPumpPlugin @Inject constructor( .enacted(false) // .comment(resourceHelper.gs(R.string.medtronic_cmd_set_profile_pattern_overflow, profileInvalid)) } - val responseTask = rileyLinkMedtronicService!!.medtronicUIComm.executeCommand(MedtronicCommandType.SetBasalProfileSTD, + val responseTask = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.SetBasalProfileSTD, arrayListOf(basalProfile)) val response = responseTask.result as Boolean? aapsLogger.info(LTag.PUMP, logPrefix + "Basal Profile was set: " + response) - return if (response!!) { - PumpEnactResult(injector).success(true).enacted(true) - } else { - PumpEnactResult(injector).success(response).enacted(response) // + return if (response == null || !response) { + PumpEnactResult(injector).success(false).enacted(false) // .comment(R.string.medtronic_cmd_basal_profile_could_not_be_set) + } else { + PumpEnactResult(injector).success(true).enacted(true) } } @@ -1136,7 +1132,7 @@ class MedtronicPumpPlugin @Inject constructor( val mcat = customActionType as MedtronicCustomActionType when (mcat) { MedtronicCustomActionType.WakeUpAndTune -> { - if (rileyLinkMedtronicService!!.verifyConfiguration()) { + if (rileyLinkMedtronicService.verifyConfiguration()) { serviceTaskExecutor.startTask(WakeAndTuneTask(injector)) } else { runAlarm(context, resourceHelper.gs(R.string.medtronic_error_operation_not_possible_no_configuration), resourceHelper.gs(R.string.medtronic_warning), R.raw.boluserror) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index 529fe69b34..cde2df1c2b 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -402,7 +402,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth private inline fun sendAndGetResponseWithCheck( commandType: MedtronicCommandType, bodyData: ByteArray? = null, - decode: (pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray?) -> T + decode: (pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray) -> T ): T? { aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") for (retries in 0 until MAX_COMMAND_TRIES) { @@ -526,7 +526,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth // aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent())); // aapsLogger.debug(LTag.PUMPCOMM,"1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData())); val check = checkResponseContent(response, commandType.commandDescription, 1) - var data: ByteArray? = null + var data: ByteArray = byteArrayOf() if (check == null) { data = response.rawContentOfFrame val ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, PumpAckMessageBody()) @@ -572,13 +572,13 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth return null } - private fun checkIfWeHaveMoreData(commandType: MedtronicCommandType, response: PumpMessage, data: ByteArray?): Boolean { + private fun checkIfWeHaveMoreData(commandType: MedtronicCommandType, response: PumpMessage, data: ByteArray): Boolean { if (commandType === MedtronicCommandType.GetBasalProfileSTD || // commandType === MedtronicCommandType.GetBasalProfileA || // commandType === MedtronicCommandType.GetBasalProfileB) { val responseRaw = response.rawContentOfFrame val last = responseRaw.size - 1 - aapsLogger.debug(LTag.PUMPCOMM, "Length: " + data!!.size) + aapsLogger.debug(LTag.PUMPCOMM, "Length: " + data.size) if (data.size >= BasalProfile.MAX_RAW_DATA_SIZE) { return false } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt index 497270e83a..07da3aceaa 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicConverter.kt @@ -27,63 +27,13 @@ class MedtronicConverter @Inject constructor( private val medtronicUtil: MedtronicUtil ) { - // fun convertResponse(pumpType: PumpType, commandType: MedtronicCommandType, rawContent: ByteArray?): Any? { - // if ((rawContent == null || rawContent.size < 1) && commandType != MedtronicCommandType.PumpModel) { - // aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Content is empty or too short, no data to convert (type=%s,isNull=%b,length=%s)", - // commandType.name, rawContent == null, rawContent?.size ?: "-")) - // return null - // } - // aapsLogger.debug(LTag.PUMPCOMM, "Raw response before convert: " + ByteUtil.shortHexString(rawContent)) - // return when (commandType) { - // MedtronicCommandType.PumpModel -> { - // decodeModel(rawContent) - // } - // - // MedtronicCommandType.GetRealTimeClock -> { - // decodeTime(rawContent) - // } - // - // MedtronicCommandType.GetRemainingInsulin -> { - // decodeRemainingInsulin(rawContent) - // } - // - // MedtronicCommandType.GetBatteryStatus -> { - // decodeBatteryStatus(rawContent) // 1 - // } - // - // MedtronicCommandType.GetBasalProfileSTD, MedtronicCommandType.GetBasalProfileA, MedtronicCommandType.GetBasalProfileB -> { - // decodeBasalProfile(pumpType, rawContent) - // } - // - // MedtronicCommandType.ReadTemporaryBasal -> { - // TempBasalPair(aapsLogger, rawContent!!) // 5 - // } - // - // MedtronicCommandType.Settings_512 -> { - // decodeSettingsLoop(rawContent) - // } - // - // MedtronicCommandType.Settings -> { - // decodeSettingsLoop(rawContent) - // } - // - // MedtronicCommandType.SetBolus -> { - // rawContent // 1 - // } - // - // else -> { - // throw RuntimeException("Unsupported command Type: $commandType") - // } - // } - // } - - fun decodeBasalProfile(pumpType: PumpType, rawContent: ByteArray?): BasalProfile? { - val basalProfile = BasalProfile(aapsLogger, rawContent!!) + fun decodeBasalProfile(pumpType: PumpType, rawContent: ByteArray): BasalProfile? { + val basalProfile = BasalProfile(aapsLogger, rawContent) return if (basalProfile.verify(pumpType)) basalProfile else null } - fun decodeModel(rawContent: ByteArray?): MedtronicDeviceType { - if (rawContent == null || rawContent.size < 4) { + fun decodeModel(rawContent: ByteArray): MedtronicDeviceType { + if (rawContent.size < 4) { aapsLogger.warn(LTag.PUMPCOMM, "Error reading PumpModel, returning Unknown_Device") return MedtronicDeviceType.Unknown_Device } @@ -99,10 +49,10 @@ class MedtronicConverter @Inject constructor( return pumpModel } - fun decodeBatteryStatus(rawData: ByteArray?): BatteryStatusDTO { + fun decodeBatteryStatus(rawData: ByteArray): BatteryStatusDTO { // 00 7C 00 00 val batteryStatus = BatteryStatusDTO() - val status = rawData!![0].toInt() + val status = rawData[0].toInt() if (status == 0) { batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Normal } else if (status == 1) { @@ -125,7 +75,7 @@ class MedtronicConverter @Inject constructor( return batteryStatus } - public fun decodeRemainingInsulin(rawData: ByteArray?): Double { + fun decodeRemainingInsulin(rawData: ByteArray): Double { var startIdx = 0 val pumpModel = medtronicUtil.medtronicPumpModel val strokes = pumpModel.bolusStrokes //?: 10 @@ -134,7 +84,7 @@ class MedtronicConverter @Inject constructor( } val reqLength = startIdx + 1 val value: Double - value = if (reqLength >= rawData!!.size) { + value = if (reqLength >= rawData.size) { rawData[startIdx] / (1.0 * strokes) } else { ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0 * strokes) @@ -143,8 +93,8 @@ class MedtronicConverter @Inject constructor( return value } - public fun decodeTime(rawContent: ByteArray?): LocalDateTime? { - val hours = ByteUtil.asUINT8(rawContent!![0]) + fun decodeTime(rawContent: ByteArray): LocalDateTime? { + val hours = ByteUtil.asUINT8(rawContent[0]) val minutes = ByteUtil.asUINT8(rawContent[1]) val seconds = ByteUtil.asUINT8(rawContent[2]) val year = (ByteUtil.asUINT8(rawContent[4]) and 0x3f) + 1984 @@ -159,12 +109,12 @@ class MedtronicConverter @Inject constructor( } } - public fun decodeSettingsLoop(rd: ByteArray?): Map { + public fun decodeSettingsLoop(rd: ByteArray): Map { val map: MutableMap = HashMap() addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map) addSettingToMap( "PCFG_MAX_BASAL", "" - + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd!![settingIndexMaxBasal].toInt(), + + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[settingIndexMaxBasal].toInt(), rd[settingIndexMaxBasal + 1].toInt())), PumpConfigurationGroup.Basal, map) addSettingToMap("CFG_BASE_CLOCK_MODE", if (rd[settingIndexTimeDisplayFormat].toInt() == 0) "12h" else "24h", PumpConfigurationGroup.General, map) @@ -301,9 +251,11 @@ class MedtronicConverter @Inject constructor( private val settingIndexTimeDisplayFormat: Int get() = if (is523orHigher()) 9 else 8 - private fun decodeMaxBolus(ai: ByteArray?): Double { - return if (is523orHigher()) decodeBolusInsulin(ByteUtil.toInt(ai!![5], ai[6])) else decodeBolusInsulin(ByteUtil - .asUINT8(ai!![5])) + private fun decodeMaxBolus(ai: ByteArray): Double { + return if (is523orHigher()) + decodeBolusInsulin(ByteUtil.toInt(ai[5], ai[6])) + else + decodeBolusInsulin(ByteUtil.asUINT8(ai[5])) } private fun is523orHigher(): Boolean { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 1bed8c2809..228a9ddef5 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -6,7 +6,6 @@ import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil import org.apache.commons.lang3.StringUtils -import java.util.* /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes @@ -15,35 +14,21 @@ import java.util.* * * Author: Andy {andy.rozman@gmail.com} */ -abstract class MedtronicHistoryDecoder : MedtronicHistoryDecoderInterface { - - constructor(aapsLogger: AAPSLogger, - medtronicUtil: MedtronicUtil, - bitUtils: ByteUtil) { - this.aapsLogger = aapsLogger - this.medtronicUtil = medtronicUtil - this.bitUtils = bitUtils - } - - var aapsLogger: AAPSLogger - var medtronicUtil: MedtronicUtil - var bitUtils: ByteUtil +abstract class MedtronicHistoryDecoder(var aapsLogger: AAPSLogger, + var medtronicUtil: MedtronicUtil, + var bitUtils: ByteUtil) : MedtronicHistoryDecoderInterface { // STATISTICS (remove at later time or not) protected var statisticsEnabled = true - protected var unknownOpCodes: MutableMap? = null - protected var mapStatistics: MutableMap>? = null + protected var unknownOpCodes: MutableMap = mutableMapOf() + protected var mapStatistics: MutableMap> = mutableMapOf() - // public abstract Class getHistoryEntryClass(); - // public abstract RecordDecodeStatus decodeRecord(T record); abstract fun postProcess() protected abstract fun runPostDecodeTasks() // TODO_ extend this to also use bigger pages (for now we support only 1024 pages) @Throws(RuntimeException::class) private fun checkPage(page: RawHistoryPage): MutableList { - //val byteList: MutableList = mutableListOf() - if (!medtronicUtil.isModelSet) { aapsLogger.error(LTag.PUMPCOMM, "Device Type is not defined.") return mutableListOf() @@ -69,36 +54,37 @@ abstract class MedtronicHistoryDecoder : MedtronicHi protected fun prepareStatistics() { if (!statisticsEnabled) return - unknownOpCodes = HashMap() - mapStatistics = HashMap() + // unknownOpCodes = HashMap() + // mapStatistics = HashMap() for (stat in RecordDecodeStatus.values()) { - (mapStatistics as HashMap>)[stat] = HashMap() + mapStatistics[stat] = hashMapOf() + //(mapStatistics as HashMap>)[stat] = hashMapOf() } } protected fun addToStatistics(pumpHistoryEntry: MedtronicHistoryEntryInterface, status: RecordDecodeStatus?, opCode: Int?) { if (!statisticsEnabled) return if (opCode != null) { - if (!unknownOpCodes!!.containsKey(opCode)) { - unknownOpCodes!![opCode] = opCode + if (!unknownOpCodes.containsKey(opCode)) { + unknownOpCodes[opCode] = opCode } return } - if (!mapStatistics!![status]!!.containsKey(pumpHistoryEntry.entryTypeName)) { - mapStatistics!![status]!!.put(pumpHistoryEntry.entryTypeName!!, "") + if (!mapStatistics[status]!!.containsKey(pumpHistoryEntry.entryTypeName)) { + mapStatistics[status]!!.put(pumpHistoryEntry.entryTypeName, "") } } protected fun showStatistics() { var sb = StringBuilder() - for ((key) in unknownOpCodes!!) { + for ((key) in unknownOpCodes) { StringUtil.appendToStringBuilder(sb, "" + key, ", ") } aapsLogger.info(LTag.PUMPCOMM, "STATISTICS OF PUMP DECODE") - if (unknownOpCodes!!.size > 0) { + if (unknownOpCodes.size > 0) { aapsLogger.warn(LTag.PUMPCOMM, "Unknown Op Codes: $sb") } - for ((key, value) in mapStatistics!!) { + for ((key, value) in mapStatistics) { sb = StringBuilder() if (key !== RecordDecodeStatus.OK) { if (value.size == 0) continue @@ -106,9 +92,9 @@ abstract class MedtronicHistoryDecoder : MedtronicHi StringUtil.appendToStringBuilder(sb, key1, ", ") } 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, " ${key.name}$spaces - ${value.size}. Elements: ${sb.toString()}") } else { - aapsLogger.info(LTag.PUMPCOMM, String.format(Locale.ENGLISH, " %s - %d", key.name, value.size)) + aapsLogger.info(LTag.PUMPCOMM, " ${key.name} - ${value.size}") } } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index 3c88716f09..31f3fca4ef 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -1,12 +1,9 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history -import android.util.Log import com.google.gson.annotations.Expose 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.PumpHistoryEntryType -import java.util.* /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes @@ -17,17 +14,15 @@ import java.util.* */ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { - var rawData: List? = null - get() = field + lateinit var rawData: List protected var sizes = IntArray(3) get() = field - var head: ByteArray? = null - get() = field + lateinit var head: ByteArray + lateinit var datetime: ByteArray + lateinit var body: ByteArray - var datetime: ByteArray? = null - var body: ByteArray? = null var id: Long = 0 set(value) { field = value @@ -81,7 +76,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { abstract fun isEntryTypeSet(): Boolean - override fun setData(listRawData: List, doNotProcess: Boolean) { + override fun setData(listRawData: MutableList, doNotProcess: Boolean) { rawData = listRawData // System.out.println("Head: " + sizes[0] + ", dates: " + sizes[1] + @@ -89,28 +84,31 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { if (!doNotProcess) { head = ByteArray(headLength - 1) for (i in 1 until headLength) { - head!![i - 1] = listRawData[i] + head[i - 1] = listRawData[i] } if (dateTimeLength > 0) { datetime = ByteArray(dateTimeLength) var i = headLength var j = 0 while (j < dateTimeLength) { - datetime!![j] = listRawData[i] + datetime[j] = listRawData[i] i++ j++ } - } + } else + datetime = byteArrayOf() + if (bodyLength > 0) { body = ByteArray(bodyLength) var i = headLength + dateTimeLength var j = 0 while (j < bodyLength) { - body!![j] = listRawData[i] + body[j] = listRawData[i] i++ j++ } - } + } else + body = byteArrayOf() } return } @@ -177,15 +175,15 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { sb.append("]") return sb.toString() } - if (head != null) { + if (head.size != 0) { sb.append(", head=") sb.append(ByteUtil.shortHexString(head)) } - if (datetime != null) { + if (datetime.size != 0) { sb.append(", datetime=") sb.append(ByteUtil.shortHexString(datetime)) } - if (body != null) { + if (body.size != 0) { sb.append(", body=") sb.append(ByteUtil.shortHexString(body)) } @@ -204,15 +202,15 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { abstract val toStringStart: String? fun getRawDataByIndex(index: Int): Byte { - return rawData!![index] + return rawData[index] } fun getRawDataByIndexInt(index: Int): Int { - return rawData!![index].toInt() + return rawData[index].toInt() } fun getUnsignedRawDataByIndex(index: Int): Int { - return ByteUtil.convertUnsignedByteToInt(rawData!![index]) + return ByteUtil.convertUnsignedByteToInt(rawData[index]) } fun addDecodedData(key: String, value: Any) { @@ -220,7 +218,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { } fun toShortString(): String { - return if (head == null) { + return if (head.size != 0) { "Unidentified record. " } else { "HistoryRecord: head=[" + ByteUtil.shortHexString(head) + "]" diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt index 4467f68d7e..21098edd1e 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntryInterface.kt @@ -5,7 +5,7 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history */ interface MedtronicHistoryEntryInterface { - val entryTypeName: String? - fun setData(listRawData: List, doNotProcess: Boolean) + val entryTypeName: String + fun setData(listRawData: MutableList, doNotProcess: Boolean) val dateLength: Int } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt index 3815815c4e..494b8eb683 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt @@ -14,11 +14,11 @@ import org.joda.time.LocalDateTime */ class CGMSHistoryEntry : MedtronicHistoryEntry() { - var entryType: CGMSHistoryEntryType? = null + var entryType: CGMSHistoryEntryType = CGMSHistoryEntryType.UnknownOpCode private set override var opCode: Byte? = null // this is set only when we have unknown entry... - get() = if (field == null) entryType!!.code.toByte() else field + get() = if (field == null) entryType.code.toByte() else field fun setEntryType(entryType: CGMSHistoryEntryType) { this.entryType = entryType @@ -28,21 +28,21 @@ class CGMSHistoryEntry : MedtronicHistoryEntry() { } override val entryTypeName: String - get() = entryType!!.name + get() = entryType.name override fun generatePumpId(): Long { - return if (entryType==null) + return if (entryType == null) atechDateTime * 1000L else - entryType!!.code + atechDateTime * 1000L + entryType.code + atechDateTime * 1000L } override fun isEntryTypeSet(): Boolean { - return entryType!=null + return entryType != CGMSHistoryEntryType.UnknownOpCode } - override fun setData(listRawData: List, doNotProcess: Boolean) { - if (entryType!!.schemaSet) { + override fun setData(listRawData: MutableList, doNotProcess: Boolean) { + if (entryType.schemaSet) { super.setData(listRawData, doNotProcess) } else { rawData = listRawData @@ -50,14 +50,14 @@ class CGMSHistoryEntry : MedtronicHistoryEntry() { } override val dateLength: Int - get() = entryType!!.dateLength + get() = entryType.dateLength fun hasTimeStamp(): Boolean { - return entryType!!.hasDate() + return entryType.hasDate() } override val toStringStart: String - get() = ("CGMSHistoryEntry [type=" + StringUtils.rightPad(entryType!!.name, 18) + " [" + get() = ("CGMSHistoryEntry [type=" + StringUtils.rightPad(entryType.name, 18) + " [" + StringUtils.leftPad("" + opCode, 3) + ", 0x" + ByteUtil.getCorrectHexValue(opCode!!) + "]") fun setDateTime(timeStamp: LocalDateTime, getIndex: Int) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt index a0cc7573c7..bf56899830 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntryType.kt @@ -1,7 +1,5 @@ package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms -import java.util.* - /** * This file was taken from GGC - GNU Gluco Control (ggc.sourceforge.net), application for diabetes * management and modified/extended for AAPS. @@ -22,14 +20,19 @@ enum class CGMSHistoryEntryType(val code: Int, val description: String, val head CalBGForGH(0x0e, "CalBGForGH',packet_size=5", 1, 4, 1, DateType.MinuteSpecific), // SensorCalFactor(0x0f, "SensorCalFactor", 1, 4, 2, DateType.MinuteSpecific), // Something10(0x10, "10-Something", 1, 4, 0, DateType.MinuteSpecific), // - Something19(0x13, "19-Something", 1, 0, 0, DateType.PreviousTimeStamp), GlucoseSensorData(0xFF, "GlucoseSensorData", 1, 0, 0, DateType.PreviousTimeStamp); + Something19(0x13, "19-Something", 1, 0, 0, DateType.PreviousTimeStamp), GlucoseSensorData(0xFF, "GlucoseSensorData", 1, 0, 0, DateType.PreviousTimeStamp), + UnknownOpCode(0xFF, "Unknown", 0, 0, 0, DateType.None); companion object { - private val opCodeMap: MutableMap = HashMap() - @JvmStatic fun getByCode(opCode: Int): CGMSHistoryEntryType? { - return if (opCodeMap.containsKey(opCode)) { - opCodeMap[opCode] - } else None + + private val opCodeMap: MutableMap = mutableMapOf() + + @JvmStatic + fun getByCode(opCode: Int): CGMSHistoryEntryType { + return if (opCodeMap.containsKey(opCode)) + opCodeMap[opCode]!! + else + UnknownOpCode } init { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index b629369f70..9bd0b1fa6a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -30,7 +30,7 @@ class MedtronicCGMSHistoryDecoder constructor( return try { decodeRecordInternal(record) } catch (ex: Exception) { - aapsLogger.error(LTag.PUMPCOMM, " Error decoding: type={}, ex={}", record.entryType!!.name, ex.message, ex) + aapsLogger.error(LTag.PUMPCOMM, " Error decoding: type={}, ex={}", record.entryType.name, ex.message, ex) RecordDecodeStatus.Error } } @@ -40,25 +40,30 @@ class MedtronicCGMSHistoryDecoder constructor( parseDate(entry) } when (entry.entryType) { - CGMSHistoryEntryType.SensorPacket -> decodeSensorPacket(entry) - CGMSHistoryEntryType.SensorError -> decodeSensorError(entry) - CGMSHistoryEntryType.SensorDataLow -> decodeDataHighLow(entry, 40) - CGMSHistoryEntryType.SensorDataHigh -> decodeDataHighLow(entry, 400) - CGMSHistoryEntryType.SensorTimestamp -> decodeSensorTimestamp(entry) - CGMSHistoryEntryType.SensorCal -> decodeSensorCal(entry) - CGMSHistoryEntryType.SensorCalFactor -> decodeSensorCalFactor(entry) - CGMSHistoryEntryType.SensorSync -> decodeSensorSync(entry) - CGMSHistoryEntryType.SensorStatus -> decodeSensorStatus(entry) - CGMSHistoryEntryType.CalBGForGH -> decodeCalBGForGH(entry) - CGMSHistoryEntryType.GlucoseSensorData -> decodeGlucoseSensorData(entry) + CGMSHistoryEntryType.SensorPacket -> decodeSensorPacket(entry) + CGMSHistoryEntryType.SensorError -> decodeSensorError(entry) + CGMSHistoryEntryType.SensorDataLow -> decodeDataHighLow(entry, 40) + CGMSHistoryEntryType.SensorDataHigh -> decodeDataHighLow(entry, 400) + CGMSHistoryEntryType.SensorTimestamp -> decodeSensorTimestamp(entry) + CGMSHistoryEntryType.SensorCal -> decodeSensorCal(entry) + CGMSHistoryEntryType.SensorCalFactor -> decodeSensorCalFactor(entry) + CGMSHistoryEntryType.SensorSync -> decodeSensorSync(entry) + CGMSHistoryEntryType.SensorStatus -> decodeSensorStatus(entry) + CGMSHistoryEntryType.CalBGForGH -> decodeCalBGForGH(entry) + CGMSHistoryEntryType.GlucoseSensorData -> decodeGlucoseSensorData(entry) - CGMSHistoryEntryType.BatteryChange, CGMSHistoryEntryType.Something10, CGMSHistoryEntryType.DateTimeChange -> { + CGMSHistoryEntryType.BatteryChange, + CGMSHistoryEntryType.Something10, + CGMSHistoryEntryType.DateTimeChange -> { } - CGMSHistoryEntryType.Something19, CGMSHistoryEntryType.DataEnd, CGMSHistoryEntryType.SensorWeakSignal -> { + CGMSHistoryEntryType.Something19, + CGMSHistoryEntryType.DataEnd, + CGMSHistoryEntryType.SensorWeakSignal -> { } - CGMSHistoryEntryType.None -> { + CGMSHistoryEntryType.UnknownOpCode, + CGMSHistoryEntryType.None -> { } } return RecordDecodeStatus.NotSupported @@ -83,7 +88,7 @@ class MedtronicCGMSHistoryDecoder constructor( } else if (opCode > 0 && opCode < 20) { entryType = getByCode(opCode) if (entryType === CGMSHistoryEntryType.None) { - unknownOpCodes!![opCode] = opCode + unknownOpCodes[opCode] = opCode aapsLogger.warn(LTag.PUMPCOMM, "GlucoseHistoryEntry with unknown code: $opCode") val pe = CGMSHistoryEntry() pe.setEntryType(CGMSHistoryEntryType.None) @@ -94,7 +99,7 @@ class MedtronicCGMSHistoryDecoder constructor( // System.out.println("OpCode: " + opCode); val listRawData: MutableList = ArrayList() listRawData.add(opCode.toByte()) - for (j in 0 until entryType!!.totalLength - 1) { + for (j in 0 until entryType.totalLength - 1) { listRawData.add(dataClear[counter]) counter++ } @@ -166,14 +171,14 @@ class MedtronicCGMSHistoryDecoder constructor( } private fun parseDate(entry: CGMSHistoryEntry): Long? { - if (!entry.entryType!!.hasDate()) return null + if (!entry.entryType.hasDate()) return null val data = entry.datetime - return if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.MinuteSpecific) { - val atechDateTime = DateTimeUtil.toATechDate(parseYear(data!![3].toInt()), parseMonths(data[0].toInt(), data[1].toInt()), + return if (entry.entryType.dateType === CGMSHistoryEntryType.DateType.MinuteSpecific) { + val atechDateTime = DateTimeUtil.toATechDate(parseYear(data[3].toInt()), parseMonths(data[0].toInt(), data[1].toInt()), parseDay(data[2].toInt()), parseHours(data[0].toInt()), parseMinutes(data[1].toInt()), 0) entry.atechDateTime = atechDateTime atechDateTime - } else if (entry.entryType!!.dateType === CGMSHistoryEntryType.DateType.SecondSpecific) { + } else if (entry.entryType.dateType === CGMSHistoryEntryType.DateType.SecondSpecific) { aapsLogger.warn(LTag.PUMPCOMM, "parseDate for SecondSpecific type is not implemented.") throw RuntimeException() // return null; diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index bcad0fa4bc..697e8ca417 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -75,7 +75,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( if (counter >= 1022) { break } - val listRawData: MutableList = ArrayList() + val listRawData: MutableList = ArrayList() listRawData.add(opCode.toByte()) if (entryType === PumpHistoryEntryType.UnabsorbedInsulin || entryType === PumpHistoryEntryType.UnabsorbedInsulin512) { @@ -112,7 +112,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( pe.opCode = opCode.toByte() } if (entryType.getHeadLength(medtronicUtil.medtronicPumpModel) == 0) special = true - pe.setData(listRawData as List, special) + pe.setData(listRawData, special) val decoded = decodeRecord(pe) if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { //Log.i(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); @@ -291,14 +291,14 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBatteryActivity(entry: PumpHistoryEntry) { - entry.displayableValue = if (entry.head!![0] == 0.toByte()) "Battery Removed" else "Battery Replaced" + entry.displayableValue = if (entry.head[0] == 0.toByte()) "Battery Removed" else "Battery Replaced" } private fun decodeBasalProfileStart(entry: PumpHistoryEntry): RecordDecodeStatus { val body = entry.body - val offset = body!![0] * 1000 * 30 * 60 + val offset = body[0] * 1000 * 30 * 60 var rate: Float? = null - val index = entry.head!![0].toInt() + val index = entry.head[0].toInt() if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { rate = body[1] * 0.025f } @@ -315,14 +315,14 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBolusWizard(entry: PumpHistoryEntry): RecordDecodeStatus { - val body = entry.body!! + val body = entry.body val dto = BolusWizardDTO() var bolusStrokes = 10.0f 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 bolusStrokes = 40.0f dto.carbs = ((body[1] and 0x0c.toByte()).toInt() shl 6) + body[0] - dto.bloodGlucose = ((body[1] and 0x03).toInt() shl 8) + entry.head!![0] + dto.bloodGlucose = ((body[1] and 0x03).toInt() shl 8) + entry.head[0] dto.carbRatio = body[1] / 10.0f // carb_ratio (?) = (((self.body[2] & 0x07) << 8) + self.body[3]) / // 10.0s @@ -334,7 +334,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( dto.unabsorbedInsulin = ((body[10].toInt() shl 8) + body[11]) / bolusStrokes dto.bolusTotal = ((body[12].toInt() shl 8) + body[13]) / bolusStrokes } 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[0].toInt() dto.carbRatio = body[2].toFloat() dto.insulinSensitivity = body[3].toFloat() @@ -356,10 +356,10 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeBolusWizard512(entry: PumpHistoryEntry): RecordDecodeStatus { - val body = entry.body!! + val body = entry.body val dto = BolusWizardDTO() val bolusStrokes = 10.0f - dto.bloodGlucose = (body.get(1) and 0x03).toInt() shl 8 or entry.head!!.get(0).toInt() + dto.bloodGlucose = (body.get(1) and 0x03).toInt() shl 8 or entry.head.get(0).toInt() dto.carbs = body.get(1).toInt() and 0xC shl 6 or body.get(0).toInt() // (int)body[0]; dto.carbRatio = body.get(2).toFloat() dto.insulinSensitivity = body.get(3).toFloat() @@ -379,13 +379,13 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } private fun decodeLowReservoir(entry: PumpHistoryEntry) { - val amount = getUnsignedInt(entry.head!!.get(0)) * 1.0f / 10.0f * 2 + val amount = getUnsignedInt(entry.head.get(0)) * 1.0f / 10.0f * 2 entry.displayableValue = getFormattedValue(amount, 1) } private fun decodePrime(entry: PumpHistoryEntry) { - val amount = ByteUtil.toInt(entry.head!!.get(2), entry.head!!.get(3)) / 10.0f - val fixed = ByteUtil.toInt(entry.head!!.get(0), entry.head!!.get(1)) / 10.0f + val amount = ByteUtil.toInt(entry.head.get(2), entry.head.get(3)) / 10.0f + val fixed = ByteUtil.toInt(entry.head.get(0), entry.head.get(1)) / 10.0f // amount = (double)(asUINT8(data[4]) << 2) / 40.0; // programmedAmount = (double)(asUINT8(data[2]) << 2) / 40.0; @@ -422,7 +422,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( private fun decodeBolus(entry: PumpHistoryEntry) { val bolus: BolusDTO? - val data = entry.head!! + val data = entry.head if (MedtronicDeviceType.isSameDevice(medtronicUtil.medtronicPumpModel, MedtronicDeviceType.Medtronic_523andHigher)) { bolus = BolusDTO(atechDateTime = entry.atechDateTime, requestedAmount = ByteUtil.toInt(data.get(0), data.get(1)) / 40.0, @@ -455,20 +455,20 @@ class MedtronicPumpHistoryDecoder @Inject constructor( } val tbr = TempBasalPair( - tbrRate.head!!.get(0), - tbrRate.body!!.get(0), - tbrDuration!!.head!!.get(0).toInt(), - ByteUtil.asUINT8(tbrRate.datetime!!.get(4)) shr 3 == 0) + tbrRate.head.get(0), + tbrRate.body.get(0), + tbrDuration!!.head.get(0).toInt(), + ByteUtil.asUINT8(tbrRate.datetime.get(4)) shr 3 == 0) entry.addDecodedData("Object", tbr) entry.displayableValue = tbr.description } private fun decodeDateTime(entry: PumpHistoryEntry) { - if (entry.datetime == null) { + if (entry.datetime.size == 0) { aapsLogger.warn(LTag.PUMPBTCOMM, "DateTime not set.") } - val dt = entry.datetime!! + val dt = entry.datetime if (entry.dateTimeLength == 5) { val seconds: Int = (dt.get(0) and 0x3F.toByte()).toInt() val minutes: Int = (dt.get(1) and 0x3F.toByte()).toInt() diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt index 09352e8e5a..1fc9645f18 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntryType.kt @@ -12,7 +12,12 @@ import java.util.* * Author: Andy {andy.rozman@gmail.com} */ enum class PumpHistoryEntryType // implements CodeEnum -constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int = 2, date: Int = 5, body: Int = 0) { +constructor(var code: Byte, + var description: String, + var group: PumpHistoryEntryGroup, + var headLength: Int = 2, + var dateLength: Int = 5, + var bodyLength: Int = 0) { // all commented out are probably not the real items None(0, "None", PumpHistoryEntryGroup.Unknown, 1, 0, 0), @@ -193,16 +198,6 @@ constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int } } - val code: Byte - - val description: String? - get() = field - - val headLength: Int - val dateLength: Int - - // private MinimedDeviceType deviceType; - private val bodyLength: Int private val totalLength: Int // special rules need to be put in list from highest to lowest (e.g.: @@ -212,12 +207,6 @@ constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int private var hasSpecialRules = false get() = field - val group: PumpHistoryEntryGroup - get() = field - - 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) {} - fun getTotalLength(medtronicDeviceType: MedtronicDeviceType): Int { return if (hasSpecialRules) { getHeadLength(medtronicDeviceType) + getBodyLength(medtronicDeviceType) + dateLength @@ -227,7 +216,7 @@ constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int } fun addSpecialRuleHead(rule: SpecialRule) { - if (isEmpty(specialRulesHead)) { + if (specialRulesHead.isNullOrEmpty()) { specialRulesHead = ArrayList() } specialRulesHead!!.add(rule) @@ -235,53 +224,33 @@ constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int } fun addSpecialRuleBody(rule: SpecialRule) { - if (isEmpty(specialRulesBody)) { + if (specialRulesBody.isNullOrEmpty()) { specialRulesBody = ArrayList() } specialRulesBody!!.add(rule) hasSpecialRules = true } - // fun getDescription(): String { - // return description ?: name - // } - fun getHeadLength(medtronicDeviceType: MedtronicDeviceType): Int { - return if (hasSpecialRules) { - if (isNotEmpty(specialRulesHead)) { - determineSizeByRule(medtronicDeviceType, headLength, specialRulesHead) - } else { - headLength - } + return if (hasSpecialRules && !specialRulesHead.isNullOrEmpty()) { + determineSizeByRule(medtronicDeviceType, headLength, specialRulesHead!!) } else { headLength } } fun getBodyLength(medtronicDeviceType: MedtronicDeviceType): Int { - return if (hasSpecialRules) { - if (isNotEmpty(specialRulesBody)) { - determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody) - } else { - bodyLength - } + return if (hasSpecialRules && !specialRulesBody.isNullOrEmpty()) { + determineSizeByRule(medtronicDeviceType, bodyLength, specialRulesBody!!) } else { bodyLength } } - private fun isNotEmpty(list: List<*>?): Boolean { - return list != null && !list.isEmpty() - } - - private fun isEmpty(list: List<*>?): Boolean { - return list == null || list.isEmpty() - } - // byte[] dh = { 2, 3 }; - private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType, defaultValue: Int, rules: List?): Int { + private fun determineSizeByRule(medtronicDeviceType: MedtronicDeviceType, defaultValue: Int, rules: List): Int { var size = defaultValue - for (rule in rules!!) { + for (rule in rules) { if (MedtronicDeviceType.isSameDevice(medtronicDeviceType, rule.deviceType)) { size = rule.size break @@ -293,12 +262,6 @@ constructor(opCode: Byte, name: String?, group: PumpHistoryEntryGroup, head: Int class SpecialRule internal constructor(var deviceType: MedtronicDeviceType, var size: Int) init { - this.code = opCode //as Byte.toInt() - description = name - headLength = head - dateLength = date - bodyLength = body - totalLength = head + date + body - this.group = group + totalLength = headLength + dateLength + bodyLength } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt index 166a668d3e..82633d015d 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/PumpMessage.kt @@ -85,9 +85,9 @@ class PumpMessage : RLMessage { // + commandType); // rawContent = just response without code (contents-2, messageBody.txData-1); - val rawContent: ByteArray? + val rawContent: ByteArray get() { - if (messageBody == null || messageBody!!.txData == null || messageBody!!.txData!!.size == 0) return null + if (messageBody == null || messageBody!!.txData == null || messageBody!!.txData!!.size == 0) return byteArrayOf() val data = messageBody!!.txData var length = ByteUtil.asUINT8(data!![0]) // length is not always correct so, we check whole array if we have // data, after length @@ -121,7 +121,7 @@ class PumpMessage : RLMessage { get() { val raw = messageBody!!.txData return if (raw == null || raw.size == 0) { - ByteArray(0) + byteArrayOf() } else { ByteUtil.substring(raw, 1, Math.min(FRAME_DATA_LENGTH, raw.size - 1)) } @@ -178,6 +178,7 @@ class PumpMessage : RLMessage { } companion object { + const val FRAME_DATA_LENGTH = 64 } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index 7bcf1934e3..7bb6ff8c74 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -43,8 +43,6 @@ class MedtronicUIPostprocessor @Inject constructor( 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) } } @@ -145,40 +143,53 @@ class MedtronicUIPostprocessor @Inject constructor( } private fun postProcessSettings(uiTask: MedtronicUITask) { - val settings = uiTask.result as Map? + val settings = uiTask.result as? Map + + if (settings == null) + return + medtronicUtil.settings = settings - var checkValue: PumpSettingDTO? - medtronicPumpPlugin.rileyLinkService!!.verifyConfiguration() + 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) + if (settings.containsKey("PCFG_BASAL_PROFILES_ENABLED") && settings.containsKey("PCFG_ACTIVE_BASAL_PROFILE")) { + checkValue = settings["PCFG_BASAL_PROFILES_ENABLED"]!! + if ("Yes" != checkValue.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) + if (settings.containsKey("PCFG_TEMP_BASAL_TYPE")) { + if ("Units" != settings["PCFG_TEMP_BASAL_TYPE"]!!.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) + if (settings.containsKey("PCFG_MAX_BOLUS")) { + 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) + + if (settings.containsKey("PCFG_MAX_BASAL")) { + 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) + } } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 4f32043e66..6a227c7c98 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -429,16 +429,16 @@ class MedtronicHistoryData @Inject constructor( private fun uploadCareportalEventIfFoundInHistory(historyRecord: PumpHistoryEntry, eventSP: String, eventType: DetailedBolusInfo.EventType) { val lastPrimeFromAAPS = sp.getLong(eventSP, 0L) if (historyRecord.atechDateTime != lastPrimeFromAAPS) { - var result = pumpSync.insertTherapyEventIfNewWithTimestamp( + val result = pumpSync.insertTherapyEventIfNewWithTimestamp( DateTimeUtil.toMillisFromATD(historyRecord.atechDateTime), eventType, null, historyRecord.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ROOT, "insertTherapyEventIfNewWithTimestamp [date=%d, eventType=%s, pumpId=%d, pumpSerial=%s] - Result: %b", historyRecord.atechDateTime, eventType, historyRecord.pumpId, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) sp.putLong(eventSP, historyRecord.atechDateTime) } @@ -460,7 +460,7 @@ class MedtronicHistoryData @Inject constructor( totalsDTO.insulinTotal, tdd.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!! + medtronicPumpStatus.serialNumber ) } } @@ -515,11 +515,11 @@ class MedtronicHistoryData @Inject constructor( type, bolus.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithTempId [date=%d, temporaryId=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", bolus.atechDateTime, temporaryId, bolus.pumpId, deliveredAmount, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) } else { val result = pumpSync.syncBolusWithPumpId( tryToGetByLocalTime(bolus.atechDateTime), @@ -527,11 +527,11 @@ class MedtronicHistoryData @Inject constructor( type, bolus.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithPumpId [date=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", bolus.atechDateTime, bolus.pumpId, deliveredAmount, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) } addCarbs(bolus) @@ -548,11 +548,11 @@ class MedtronicHistoryData @Inject constructor( false, bolus.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncExtendedBolusWithPumpId [date=%d, amount=%.2f, duration=%d, pumpId=%d, pumpSerial=%s, multiwave=%b] - Result: %b", bolus.atechDateTime, bolusDTO.deliveredAmount, bolusDTO.duration, bolus.pumpId, - medtronicPumpStatus.serialNumber!!, isMultiwave, result)) + medtronicPumpStatus.serialNumber, isMultiwave, result)) } private fun addCarbs(bolus: PumpHistoryEntry) { @@ -563,7 +563,7 @@ class MedtronicHistoryData @Inject constructor( tryToGetByLocalTime(bolus.atechDateTime), bolusWizard.carbs.toDouble(), medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!, + medtronicPumpStatus.serialNumber, bolus.pumpId )) } @@ -589,8 +589,8 @@ class MedtronicHistoryData @Inject constructor( var processDTO: TempBasalProcessDTO? = null val processList: MutableList = mutableListOf() for (treatment in entryList) { - val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair? - if (tbr2!!.isCancelTBR) { + val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair + if (tbr2.isCancelTBR) { if (processDTO != null) { processDTO.itemTwo = treatment processDTO.cancelPresent = true @@ -627,7 +627,7 @@ class MedtronicHistoryData @Inject constructor( if (entryWithTempId != null) { aapsLogger.debug(LTag.PUMP, String.format("DD: tempIdEntry=%s, tbrEntry=%s, tempBasalProcessDTO=%s, pumpType=%s, serial=%s", - gson.toJson(entryWithTempId), gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber!!)) + gson.toJson(entryWithTempId), gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber)) val result = pumpSync.syncTemporaryBasalWithTempId( tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), @@ -638,12 +638,12 @@ class MedtronicHistoryData @Inject constructor( PumpSync.TemporaryBasalType.NORMAL, tempBasalProcessDTO.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncTemporaryBasalWithTempId [date=%d, temporaryId=%d, pumpId=%d, rate=%.2f %s, duration=%d, pumpSerial=%s] - Result: %b", tempBasalProcessDTO.atechDateTime, entryWithTempId.temporaryId, tempBasalProcessDTO.pumpId, tbrEntry.insulinRate, (if (tbrEntry.isPercent) "%" else "U"), tempBasalProcessDTO.duration, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) pumpSyncStorage.removeTemporaryBasalWithTemporaryId(entryWithTempId.temporaryId) tbrRecords.remove(entryWithTempId) @@ -664,12 +664,12 @@ class MedtronicHistoryData @Inject constructor( PumpSync.TemporaryBasalType.NORMAL, tempBasalProcessDTO.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncTemporaryBasalWithPumpId [date=%d, pumpId=%d, rate=%.2f %s, duration=%d, pumpSerial=%s] - Result: %b", tempBasalProcessDTO.atechDateTime, tempBasalProcessDTO.pumpId, tbrEntry.insulinRate, (if (tbrEntry.isPercent) "%" else "U"), tempBasalProcessDTO.duration, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) if (medtronicPumpStatus.runningTBR != null) { if (!isTBRActive(medtronicPumpStatus.runningTBR!!)) { @@ -682,7 +682,7 @@ class MedtronicHistoryData @Inject constructor( medtronicPumpStatus.runningTBR = PumpDbEntry(0L, tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!, + medtronicPumpStatus.serialNumber, null, PumpDbEntryTBR(tbrEntry.insulinRate, !tbrEntry.isPercent, tempBasalProcessDTO.duration, PumpSync.TemporaryBasalType.NORMAL), tempBasalProcessDTO.pumpId) @@ -716,13 +716,13 @@ class MedtronicHistoryData @Inject constructor( /** * Looks at all boluses that have temporaryId and find one that is correct for us (if such entry exists) */ - private fun findDbEntry(treatment: PumpHistoryEntry?, temporaryEntries: MutableList): PumpDbEntry? { + private fun findDbEntry(treatment: PumpHistoryEntry, temporaryEntries: MutableList): PumpDbEntry? { if (temporaryEntries.isEmpty()) { return null } - var proposedTime = DateTimeUtil.toMillisFromATD(treatment!!.atechDateTime) + var proposedTime = DateTimeUtil.toMillisFromATD(treatment.atechDateTime) // pumpTime should never be null, but it can theoretically happen if reading of time from pump fails this.pumpTime?.let { proposedTime += (it.timeDifference * 1000) } @@ -784,11 +784,11 @@ class MedtronicHistoryData @Inject constructor( PumpSync.TemporaryBasalType.PUMP_SUSPEND, tempBasalProcess.itemOne.pumpId, medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber!!) + medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "processSuspends::syncTemporaryBasalWithPumpId [date=%d, rate=%.2f, duration=%d, pumpId=%d, pumpSerial=%s] - Result: %b", tempBasalProcess.itemOne.atechDateTime, 0.0, tempBasalProcess.duration, tempBasalProcess.itemOne.pumpId, - medtronicPumpStatus.serialNumber!!, result)) + medtronicPumpStatus.serialNumber, result)) } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt index 81653e6eb6..e2793cf597 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt @@ -34,8 +34,7 @@ class BolusDTO constructor(atechDateTime: Long, @Expose var requestedAmount: Double, @Expose var deliveredAmount: Double, @Expose var duration: Int = 0 - ) - : PumpTimeStampedRecord(atechDateTime) { +) : PumpTimeStampedRecord(atechDateTime) { // @Expose // var requestedAmount: Double? = null @@ -50,7 +49,7 @@ class BolusDTO constructor(atechDateTime: Long, // var duration: Int? = null @Expose - var bolusType: PumpBolusType? = null + lateinit var bolusType: PumpBolusType var insulinOnBoard: Double? = null @@ -87,9 +86,9 @@ class BolusDTO constructor(atechDateTime: Long, } val bolusKey: String - get() = "Bolus_" + bolusType!!.name + get() = "Bolus_" + bolusType.name override fun toString(): String { - return "BolusDTO [type=" + bolusType!!.name + ", " + value + "]" + return "BolusDTO [type=" + bolusType.name + ", " + value + "]" } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt index f6f5c99300..ab480bbe54 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt @@ -1,9 +1,8 @@ package info.nightscout.androidaps.plugins.pump.medtronic.data.dto -import com.google.gson.annotations.Expose //import info.nightscout.androidaps.db.TDD +import com.google.gson.annotations.Expose 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 @@ -65,8 +64,8 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { } 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 + 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) } @@ -88,9 +87,9 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { } } - private fun decodeDailyTotals515(data: ByteArray?) { + private fun decodeDailyTotals515(data: ByteArray) { // LOG.debug("Can't decode DailyTotals515: Body={}", ByteUtil.getHex(data)); - insulinTotal = ByteUtil.toInt(data!![8], data[9]) / 40.0 + 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 @@ -102,8 +101,8 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { //LOG.debug("515: {}", toString()); } - private fun decodeDailyTotals522(data: ByteArray?) { - insulinTotal = ByteUtil.toInt(data!![8], data[9]) / 40.0 + 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 @@ -124,8 +123,8 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { //LOG.debug("522: {}", toString()); } - private fun decodeDailyTotals523(data: ByteArray?) { - insulinTotal = ByteUtil.toInt(data!![8], data[9]) / 40.0 + 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 @@ -177,23 +176,13 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { .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 -> { } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index 60dd954b20..07cf7bbe89 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -25,8 +25,7 @@ import java.util.* * * Author: Andy {andy@atech-software.com} */ -enum class MedtronicCommandType -{ +enum class MedtronicCommandType { InvalidCommand(0, "Invalid Command", null, null), // @@ -57,7 +56,7 @@ enum class MedtronicCommandType 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), // + 0, R.string.medtronic_cmd_desc_get_battery_status), // GetRemainingInsulin(0x73, "Read Remaining Insulin", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2, R.string.medtronic_cmd_desc_get_remaining_insulin), // 115 SetBolus(0x42, "Set Bolus", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, // @@ -130,9 +129,8 @@ enum class MedtronicCommandType // Fake Commands CancelTBR; - - companion object { + var mapByCode: MutableMap = HashMap() // private fun getDeviceTypesArray(vararg types: MedtronicDeviceType): HashMap { @@ -151,16 +149,19 @@ enum class MedtronicCommandType } } - fun constructMessageBody(messageType: MedtronicCommandType?, bodyData: ByteArray?): MessageBody { + fun constructMessageBody(messageType: MedtronicCommandType?, bodyData: ByteArray): MessageBody { return when (messageType) { CommandACK -> PumpAckMessageBody(bodyData) - else -> UnknownMessageBody(bodyData!!) + else -> UnknownMessageBody(bodyData) } } @JvmStatic fun getSettings(medtronicPumpModel: MedtronicDeviceType?): MedtronicCommandType { - return if (isSameDevice(medtronicPumpModel!!, MedtronicDeviceType.Medtronic_512_712)) Settings_512 else Settings + return if (isSameDevice(medtronicPumpModel!!, MedtronicDeviceType.Medtronic_512_712)) + Settings_512 + else + Settings } init { @@ -194,19 +195,19 @@ enum class MedtronicCommandType } constructor(code: Int, description: String, devices: MedtronicDeviceType?, - parameterType: MinimedCommandParameterType?, cmd_params: ByteArray) : this(code, description, devices, parameterType) { + parameterType: MinimedCommandParameterType?, cmd_params: ByteArray) : this(code, description, devices, parameterType) { 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) { + 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) { + parameterType: MinimedCommandParameterType?, expectedLength: Int, resourceId: Int) : this(code, description, devices, parameterType, 64, 1, expectedLength, resourceId) { } // NEW @@ -253,7 +254,6 @@ enum class MedtronicCommandType // } // } - override fun toString(): String { return name } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index 6ac69039cb..c5122ca1e8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -30,7 +30,7 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour ) : PumpStatus(PumpType.MEDTRONIC_522_722) { var errorDescription: String? = null - var serialNumber: String? = null + lateinit var serialNumber: String //? = null var pumpFrequency: String? = null var maxBolus: Double? = null var maxBasal: Double? = null @@ -58,6 +58,10 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour if (medtronicDeviceTypeMap.isEmpty()) createMedtronicDeviceTypeMap() lastConnection = sp.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L) lastDataTime = lastConnection + var serial = sp.getStringOrNull(MedtronicConst.Prefs.PumpSerial, null) + if (serial != null) { + serialNumber = serial + } } private fun createMedtronicDeviceTypeMap() { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt index ad56ff6ad9..30d7f123df 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.kt @@ -69,9 +69,10 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi * If you have customized RileyLinkServiceData you need to override this */ override fun initRileyLinkServiceData() { - frequencies = arrayOf() - frequencies[0] = resourceHelper.gs(R.string.key_medtronic_pump_frequency_us_ca) - frequencies[1] = resourceHelper.gs(R.string.key_medtronic_pump_frequency_worldwide) + frequencies = arrayOf(resourceHelper.gs(R.string.key_medtronic_pump_frequency_us_ca), + resourceHelper.gs(R.string.key_medtronic_pump_frequency_worldwide)) + // 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")) @@ -160,9 +161,9 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi medtronicPumpStatus.errorDescription = resourceHelper.gs(R.string.medtronic_error_pump_type_invalid) return false } else { - val pumpType = medtronicPumpStatus.medtronicPumpMap[pumpTypePart] + val pumpType = medtronicPumpStatus.medtronicPumpMap[pumpTypePart]!! medtronicPumpStatus.medtronicDeviceType = medtronicPumpStatus.medtronicDeviceTypeMap[pumpTypePart]!! - medtronicPumpStatus.pumpType = pumpType!! + medtronicPumpStatus.pumpType = pumpType medtronicPumpPlugin.pumpType = pumpType if (pumpTypePart.startsWith("7")) medtronicPumpStatus.reservoirFullUnits = 300 else medtronicPumpStatus.reservoirFullUnits = 176 } @@ -245,7 +246,7 @@ class RileyLinkMedtronicService // This empty constructor must be kept, otherwi private fun reconfigureService(forceRileyLinkAddressRenewal: Boolean): Boolean { if (!inPreInit) { if (serialChanged) { - setPumpIDString(medtronicPumpStatus.serialNumber!!) // short operation + setPumpIDString(medtronicPumpStatus.serialNumber) // short operation serialChanged = false } if (rileyLinkAddressChanged || forceRileyLinkAddressRenewal) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt index 9d54d2941f..5826a1e0e6 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/util/MedtronicUtil.kt @@ -173,7 +173,7 @@ class MedtronicUtil @Inject constructor( b = b or 128.toByte() // b |= doneBit; frameData.add(0, b) - checkAndAppenLastFrame(frameData) + checkAndAppendLastFrame(frameData) lastFrame = true done = true } else { @@ -194,12 +194,12 @@ class MedtronicUtil @Inject constructor( b = b or 128.toByte() // b |= doneBit; frameData.add(b) - checkAndAppenLastFrame(frameData) + checkAndAppendLastFrame(frameData) } return frames } - private fun checkAndAppenLastFrame(frameData: MutableList) { + private fun checkAndAppendLastFrame(frameData: MutableList) { if (frameData.size == BIG_FRAME_LENGTH) return val missing = BIG_FRAME_LENGTH - frameData.size for (i in 0 until missing) { From e24af3934fd9eb44bd1ec35733f539ef67e2e7e4 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Mon, 24 May 2021 16:57:54 +0100 Subject: [PATCH 32/39] - refactorings kotlin !! - moved 2 filed into pump-common module (newly created) --- app/build.gradle | 1 + .../dependencyInjection/AppModule.kt | 29 +++++--- .../pump/common/defs/PumpHistoryEntryGroup.kt | 5 +- medtronic/build.gradle | 1 + .../pump/medtronic/MedtronicPumpPlugin.kt | 67 ++++++++++--------- .../comm/MedtronicCommunicationManager.kt | 8 ++- .../pump/MedtronicPumpHistoryDecoder.kt | 4 +- .../comm/ui/MedtronicUIPostprocessor.kt | 2 +- .../medtronic/data/MedtronicHistoryData.kt | 26 +++---- .../pump/medtronic/data/dto/BolusDTO.kt | 9 --- .../pump/medtronic/data/dto/DailyTotalsDTO.kt | 4 +- .../medtronic/defs/MedtronicCommandType.kt | 4 +- .../defs/MedtronicStatusRefreshType.kt | 2 +- .../dialog/MedtronicHistoryActivity.kt | 34 +++++----- .../medtronic/driver/MedtronicPumpStatus.kt | 4 +- pump-common/.gitignore | 1 + pump-common/build.gradle | 24 +++++++ pump-common/consumer-rules.pro | 0 pump-common/proguard-rules.pro | 21 ++++++ pump-common/src/main/AndroidManifest.xml | 7 ++ .../plugins/pump/common/PumpPluginAbstract.kt | 19 ++---- .../plugins/pump/common/data/PumpStatus.kt | 0 .../plugins/pump/common/sync/PumpDbEntry.kt | 21 +++--- .../common/sync/PumpSyncEntriesCreator.java | 0 .../pump/common/sync/PumpSyncStorage.kt | 34 +++------- pump-common/src/main/res/values/strings.xml | 4 ++ settings.gradle | 4 +- 27 files changed, 187 insertions(+), 148 deletions(-) create mode 100644 pump-common/.gitignore create mode 100644 pump-common/build.gradle create mode 100644 pump-common/consumer-rules.pro create mode 100644 pump-common/proguard-rules.pro create mode 100644 pump-common/src/main/AndroidManifest.xml rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt (96%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt (78%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt (90%) create mode 100644 pump-common/src/main/res/values/strings.xml diff --git a/app/build.gradle b/app/build.gradle index ccf044fa41..faaa85cae6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -186,6 +186,7 @@ dependencies { implementation project(':danars') implementation project(':danar') implementation project(':insight') + implementation project(':pump-common') implementation project(':rileylink') implementation project(':medtronic') implementation project(':omnipod-common') diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt index 1266f526fe..9946d55cd0 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt @@ -77,27 +77,36 @@ open class AppModule { pumpSync: PumpSync, sp: SP, aapsLogger: AAPSLogger - ): PumpSyncStorage { - return PumpSyncStorage(pumpSync, sp, aapsLogger) + ): info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage { + return info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage(pumpSync, sp, aapsLogger) } @Module interface AppBindings { + @Binds fun bindContext(mainApp: MainApp): Context @Binds fun bindInjector(mainApp: MainApp): HasAndroidInjector @Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePlugin @Binds fun bindCommandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider @Binds fun bindConfigInterface(config: ConfigImpl): Config - @Binds fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilder + @Binds + fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilder @Binds fun bindTreatmentsInterface(treatmentsPlugin: TreatmentsPlugin): TreatmentsInterface - @Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface - @Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolderImpl): NotificationHolder - @Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefsImpl): ImportExportPrefs - @Binds fun bindIconsProviderInterface(iconsProvider: IconsProviderImplementation): IconsProvider + @Binds + fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface + @Binds + fun bindNotificationHolderInterface(notificationHolder: NotificationHolderImpl): NotificationHolder + @Binds + fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefsImpl): ImportExportPrefs + @Binds + fun bindIconsProviderInterface(iconsProvider: IconsProviderImplementation): IconsProvider @Binds fun bindLoopInterface(loopPlugin: LoopPlugin): LoopInterface - @Binds fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculator - @Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicator - @Binds fun bindDataSyncSelector(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector + @Binds + fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculator + @Binds + fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicator + @Binds + fun bindDataSyncSelector(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector @Binds fun bindPumpSync(pumpSyncImplementation: PumpSyncImplementation): PumpSync } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt index 8c7cbafada..38fca57a8e 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt @@ -32,6 +32,7 @@ enum class PumpHistoryEntryGroup(val resourceId: Int) { } companion object { + private var translatedList: MutableList? = null private fun doTranslation(resourceHelper: ResourceHelper) { @@ -43,9 +44,9 @@ enum class PumpHistoryEntryGroup(val resourceId: Int) { } @JvmStatic - fun getTranslatedList(resourceHelper: ResourceHelper): List? { + fun getTranslatedList(resourceHelper: ResourceHelper): List { if (translatedList == null) doTranslation(resourceHelper) - return translatedList + return translatedList!! } } diff --git a/medtronic/build.gradle b/medtronic/build.gradle index a3cb9f789e..4c3af48c8a 100644 --- a/medtronic/build.gradle +++ b/medtronic/build.gradle @@ -16,5 +16,6 @@ android { dependencies { implementation project(':core') + implementation project(':pump-common') implementation project(':rileylink') } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index a77cee4a57..a0649be977 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -90,8 +90,8 @@ class MedtronicPumpPlugin @Inject constructor( dateUtil: DateUtil, aapsSchedulers: AapsSchedulers, pumpSync: PumpSync, - pumpSyncStorage: PumpSyncStorage -) : PumpPluginAbstract(PluginDescription() // + pumpSyncStorage: info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage +) : info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract(PluginDescription() // .mainType(PluginType.PUMP) // .fragmentClass(MedtronicFragment::class.java.name) // .pluginIcon(R.drawable.ic_veo_128) @@ -101,7 +101,7 @@ class MedtronicPumpPlugin @Inject constructor( .description(R.string.description_pump_medtronic), // PumpType.MEDTRONIC_522_722, // we default to most basic model, correct model from config is loaded later injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy, dateUtil, aapsSchedulers, pumpSync, pumpSyncStorage -), Pump, RileyLinkPumpDevice, PumpSyncEntriesCreator { +), Pump, RileyLinkPumpDevice, info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator { private lateinit var rileyLinkMedtronicService: RileyLinkMedtronicService @@ -199,7 +199,7 @@ class MedtronicPumpPlugin @Inject constructor( SystemClock.sleep(60000) if (this.isInitialized) { val statusRefresh = workWithStatusRefresh( - StatusRefreshAction.GetData, null, null) + StatusRefreshAction.GetData, null, null)!! if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { if (!commandQueue.statusInQueue()) { commandQueue.readStatus("Scheduled Status Refresh", null) @@ -214,7 +214,7 @@ class MedtronicPumpPlugin @Inject constructor( override val serviceClass: Class<*> get() = RileyLinkMedtronicService::class.java - override val pumpStatusData: PumpStatus + override val pumpStatusData: info.nightscout.androidaps.plugins.pump.common.data.PumpStatus get() = medtronicPumpStatus override fun deviceID(): String { @@ -334,7 +334,7 @@ class MedtronicPumpPlugin @Inject constructor( private fun refreshAnyStatusThatNeedsToBeRefreshed() { val statusRefresh = workWithStatusRefresh(StatusRefreshAction.GetData, null, - null) + null)!! if (!doWeHaveAnyStatusNeededRefereshing(statusRefresh)) { return } @@ -354,7 +354,7 @@ class MedtronicPumpPlugin @Inject constructor( // execute val refreshTypesNeededToReschedule: MutableSet = mutableSetOf() - for ((key, value) in statusRefresh!!) { + for ((key, value) in statusRefresh) { if (value > 0 && System.currentTimeMillis() > value) { when (key) { MedtronicStatusRefreshType.PumpHistory -> { @@ -389,8 +389,8 @@ class MedtronicPumpPlugin @Inject constructor( if (resetTime) medtronicPumpStatus.setLastCommunicationToNow() } - private fun doWeHaveAnyStatusNeededRefereshing(statusRefresh: Map?): Boolean { - for ((_, value) in statusRefresh!!) { + private fun doWeHaveAnyStatusNeededRefereshing(statusRefresh: Map): Boolean { + for ((_, value) in statusRefresh) { if (value > 0 && System.currentTimeMillis() > value) { return true } @@ -583,10 +583,10 @@ class MedtronicPumpPlugin @Inject constructor( scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0) } - override fun deliverBolus(detailedBolusInfo: DetailedBolusInfo?): PumpEnactResult { + override fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - " + BolusDeliveryType.DeliveryPrepared) setRefreshButtonEnabled(false) - if (detailedBolusInfo!!.insulin > medtronicPumpStatus.reservoirRemainingUnits) { + if (detailedBolusInfo.insulin > medtronicPumpStatus.reservoirRemainingUnits) { return PumpEnactResult(injector) // .success(false) // .enacted(false) // @@ -621,7 +621,12 @@ class MedtronicPumpPlugin @Inject constructor( setRefreshButtonEnabled(true) // LOG.debug("MedtronicPumpPlugin::deliverBolus - Response: {}", response); - if (response!!) { + return if (response == null || !response) { + PumpEnactResult(injector) // + .success(bolusDeliveryType == BolusDeliveryType.CancelDelivery) // + .enacted(false) // + .comment(R.string.medtronic_cmd_bolus_could_not_be_delivered) + } else { if (bolusDeliveryType == BolusDeliveryType.CancelDelivery) { // LOG.debug("MedtronicPumpPlugin::deliverBolus - Delivery Canceled after Bolus started."); Thread(Runnable { @@ -648,11 +653,6 @@ class MedtronicPumpPlugin @Inject constructor( .enacted(true) // .bolusDelivered(detailedBolusInfo.insulin) // .carbsDelivered(detailedBolusInfo.carbs) - } else { - PumpEnactResult(injector) // - .success(bolusDeliveryType == BolusDeliveryType.CancelDelivery) // - .enacted(false) // - .comment(R.string.medtronic_cmd_bolus_could_not_be_delivered) } } finally { finishAction("Bolus") @@ -739,13 +739,13 @@ class MedtronicPumpPlugin @Inject constructor( // CANCEL val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) val response = responseTask2.result as Boolean? - if (response!!) { - aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") - } else { + if (response == null || !response) { aapsLogger.error(logPrefix + "setTempBasalAbsolute - Cancel TBR failed.") finishAction("TBR") return PumpEnactResult(injector).success(false).enacted(false) .comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op) + } else { + aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") } } @@ -763,7 +763,7 @@ class MedtronicPumpPlugin @Inject constructor( medtronicPumpStatus.tempBasalAmount = absoluteRate medtronicPumpStatus.tempBasalLength = durationInMinutes - val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + val tempData = info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) @@ -956,10 +956,13 @@ class MedtronicPumpPlugin @Inject constructor( val tbr = responseTask.result as TempBasalPair? // we sometimes get rate returned even if TBR is no longer running - if (tbr!!.durationMinutes == 0) { - tbr.insulinRate = 0.0 - } - tbr + if (tbr != null) { + if (tbr.durationMinutes == 0) { + tbr.insulinRate = 0.0 + } + tbr + } else + null } else { null } @@ -992,7 +995,11 @@ class MedtronicPumpPlugin @Inject constructor( val responseTask2 = rileyLinkMedtronicService.medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR) val response = responseTask2.result as Boolean? finishAction("TBR") - return if (response!!) { + return if (response == null || !response) { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR failed.") + PumpEnactResult(injector).success(false).enacted(false) // + .comment(R.string.medtronic_cmd_cant_cancel_tbr) + } else { aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR successful.") val runningTBR = medtronicPumpStatus.runningTBR @@ -1022,19 +1029,13 @@ class MedtronicPumpPlugin @Inject constructor( } } - //pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) - PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) - } else { - aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR failed.") - PumpEnactResult(injector).success(response).enacted(response) // - .comment(R.string.medtronic_cmd_cant_cancel_tbr) } } override fun manufacturer(): ManufacturerType { - return pumpDescription.pumpType.manufacturer!! + return ManufacturerType.Medtronic } override fun model(): PumpType { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index cde2df1c2b..2a9dc6bf66 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -140,7 +140,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth medtronicUtil.medtronicPumpModel = pumpModel!! medtronicUtil.isModelSet = true } - aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "isDeviceReachable. PumpModel is %s - Valid: %b (rssi=%d)", pumpModel!!.name, valid, + aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "isDeviceReachable. PumpModel is %s - Valid: %b (rssi=%d)", medtronicUtil.medtronicPumpModel, valid, radioResponse.rssi)) if (valid) { if (state === PumpDeviceState.PumpUnreachable) @@ -313,7 +313,9 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth aapsLogger.error(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Problem acknowledging frame response. (retry=%d)", retries)) } } - if (nextMsg != null) currentResponse = GetHistoryPageCarelinkMessageBody(nextMsg.messageBody!!.txData) else { + if (nextMsg != null) + currentResponse = GetHistoryPageCarelinkMessageBody(nextMsg.messageBody!!.txData) + else { aapsLogger.error(LTag.PUMPCOMM, "We couldn't acknowledge frame from pump, aborting operation.") } } @@ -602,7 +604,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth fun getTemporaryBasal(): TempBasalPair? { return sendAndGetResponseWithCheck(MedtronicCommandType.ReadTemporaryBasal) { _, _, rawContent -> - TempBasalPair(aapsLogger, rawContent!!) + TempBasalPair(aapsLogger, rawContent) } } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt index 697e8ca417..3152c423da 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoder.kt @@ -117,7 +117,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( if (decoded === RecordDecodeStatus.OK || decoded === RecordDecodeStatus.Ignored) { //Log.i(TAG, "#" + record + " " + decoded.getDescription() + " " + pe); } else { - aapsLogger.warn(LTag.PUMPBTCOMM, "#" + record + " " + decoded!!.description + " " + pe) + aapsLogger.warn(LTag.PUMPBTCOMM, "#" + record + " " + decoded.description + " " + pe) } addToStatistics(pe, decoded, null) record++ @@ -130,7 +130,7 @@ class MedtronicPumpHistoryDecoder @Inject constructor( return outList } - override fun decodeRecord(record: PumpHistoryEntry): RecordDecodeStatus? { + override fun decodeRecord(record: PumpHistoryEntry): RecordDecodeStatus { return try { decodeRecordInternal(record) } catch (ex: Exception) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt index 7bb6ff8c74..9ad461c0d6 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUIPostprocessor.kt @@ -39,7 +39,7 @@ class MedtronicUIPostprocessor @Inject constructor( when (uiTask.commandType) { MedtronicCommandType.SetBasalProfileSTD -> { val response = uiTask.result as Boolean? - if (response!!) { + if (response != null && response) { val basalProfile = uiTask.getParameter(0) as BasalProfile aapsLogger.debug("D: basal profile returned after set: $basalProfile") diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 6a227c7c98..3f828417a8 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -55,7 +55,7 @@ class MedtronicHistoryData @Inject constructor( val medtronicPumpStatus: MedtronicPumpStatus, val databaseHelper: DatabaseHelperInterface, val pumpSync: PumpSync, - val pumpSyncStorage: PumpSyncStorage + val pumpSyncStorage: info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage ) { val allHistory: MutableList = mutableListOf() @@ -381,12 +381,12 @@ class MedtronicHistoryData @Inject constructor( } } - private fun processPrime(primeRecords: List) { + private fun processPrime(primeRecords: List) { val maxAllowedTimeInPast = DateTimeUtil.getATDWithAddedMinutes(GregorianCalendar(), -30) var lastPrimeRecordTime = 0L var lastPrimeRecord: PumpHistoryEntry? = null for (primeRecord in primeRecords) { - val fixedAmount = primeRecord!!.getDecodedDataEntry("FixedAmount") + val fixedAmount = primeRecord.getDecodedDataEntry("FixedAmount") if (fixedAmount != null && fixedAmount as Float == 0.0f) { // non-fixed primes are used to prime the tubing // fixed primes are used to prime the cannula @@ -456,7 +456,7 @@ class MedtronicHistoryData @Inject constructor( pumpSync.createOrUpdateTotalDailyDose( DateTimeUtil.toMillisFromATD(tdd.atechDateTime), totalsDTO.insulinBolus, - totalsDTO.insulinBasal!!, + totalsDTO.insulinBasal, totalsDTO.insulinTotal, tdd.pumpId, medtronicPumpStatus.pumpType, @@ -559,7 +559,7 @@ class MedtronicHistoryData @Inject constructor( if (bolus.containsDecodedData("Estimate")) { val bolusWizard = bolus.decodedData["Estimate"] as BolusWizardDTO - pumpSyncStorage.addCarbs(PumpDbEntryCarbs( + pumpSyncStorage.addCarbs(info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs( tryToGetByLocalTime(bolus.atechDateTime), bolusWizard.carbs.toDouble(), medtronicPumpStatus.pumpType, @@ -571,9 +571,9 @@ class MedtronicHistoryData @Inject constructor( private fun processTBREntries(entryList: MutableList) { Collections.reverse(entryList) - val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair? + val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair var readOldItem = false - if (tbr!!.isCancelTBR) { + if (tbr.isCancelTBR) { val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) if (oneMoreEntryFromHistory != null) { entryList.add(0, oneMoreEntryFromHistory) @@ -679,12 +679,12 @@ class MedtronicHistoryData @Inject constructor( if (isTBRActive(tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), tempBasalProcessDTO.duration)) { if (medtronicPumpStatus.runningTBR == null) { - medtronicPumpStatus.runningTBR = PumpDbEntry(0L, + medtronicPumpStatus.runningTBR = info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry(0L, tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), medtronicPumpStatus.pumpType, medtronicPumpStatus.serialNumber, null, - PumpDbEntryTBR(tbrEntry.insulinRate, !tbrEntry.isPercent, tempBasalProcessDTO.duration, PumpSync.TemporaryBasalType.NORMAL), + info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR(tbrEntry.insulinRate, !tbrEntry.isPercent, tempBasalProcessDTO.duration, PumpSync.TemporaryBasalType.NORMAL), tempBasalProcessDTO.pumpId) } } @@ -693,7 +693,7 @@ class MedtronicHistoryData @Inject constructor( } // collection } - fun isTBRActive(dbEntry: PumpDbEntry): Boolean { + fun isTBRActive(dbEntry: info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry): Boolean { return isTBRActive(dbEntry.date, dbEntry.tbrData!!.durationInMinutes) } @@ -716,7 +716,7 @@ class MedtronicHistoryData @Inject constructor( /** * Looks at all boluses that have temporaryId and find one that is correct for us (if such entry exists) */ - private fun findDbEntry(treatment: PumpHistoryEntry, temporaryEntries: MutableList): PumpDbEntry? { + private fun findDbEntry(treatment: PumpHistoryEntry, temporaryEntries: MutableList): info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry? { if (temporaryEntries.isEmpty()) { return null @@ -728,7 +728,7 @@ class MedtronicHistoryData @Inject constructor( this.pumpTime?.let { proposedTime += (it.timeDifference * 1000) } val proposedTimeDiff: LongArray = longArrayOf(proposedTime - (2 * 60 * 1000), proposedTime + (2L * 60L * 1000L)) - val tempEntriesList: MutableList = mutableListOf() + val tempEntriesList: MutableList = mutableListOf() for (temporaryEntry in temporaryEntries) { if (temporaryEntry.date > proposedTimeDiff[0] && temporaryEntry.date < proposedTimeDiff[1]) { @@ -750,7 +750,7 @@ class MedtronicHistoryData @Inject constructor( sec = 59 } val diff = sec * 1000 - val outList: MutableList = mutableListOf() + val outList: MutableList = mutableListOf() for (treatment1 in tempEntriesList) { if (treatment1.date > proposedTime - diff && treatment1.date < proposedTime + diff) { outList.add(treatment1) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt index e2793cf597..2b738c34f0 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/BolusDTO.kt @@ -36,18 +36,9 @@ class BolusDTO constructor(atechDateTime: Long, @Expose var duration: Int = 0 ) : PumpTimeStampedRecord(atechDateTime) { - // @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 lateinit var bolusType: PumpBolusType diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt index ab480bbe54..a295c76aff 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/DailyTotalsDTO.kt @@ -36,7 +36,7 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { var insulinTotal = 0.0 @Expose - var insulinBasal: Double? = 0.0 + var insulinBasal: Double = 0.0 @Expose var insulinBolus = 0.0 @@ -55,7 +55,7 @@ class DailyTotalsDTO(var entry: PumpHistoryEntry) { private var bolusCountFood: Int? = null private var bolusCountCorr: Int? = null private fun setDisplayable() { - if (insulinBasal == null) { + if (insulinBasal == 0.0) { entry.displayableValue = "Total Insulin: " + StringUtil.getFormatedValueUS(insulinTotal, 2) } else { entry.displayableValue = ("Basal Insulin: " + StringUtil.getFormatedValueUS(insulinBasal, 2) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index 07cf7bbe89..77772a867f 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -157,8 +157,8 @@ enum class MedtronicCommandType { } @JvmStatic - fun getSettings(medtronicPumpModel: MedtronicDeviceType?): MedtronicCommandType { - return if (isSameDevice(medtronicPumpModel!!, MedtronicDeviceType.Medtronic_512_712)) + fun getSettings(medtronicPumpModel: MedtronicDeviceType): MedtronicCommandType { + return if (isSameDevice(medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712)) Settings_512 else Settings diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt index 5a416b80a8..3185212739 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicStatusRefreshType.kt @@ -13,7 +13,7 @@ enum class MedtronicStatusRefreshType(val refreshTime: Int, PumpTime(60, MedtronicCommandType.GetRealTimeClock // ); - fun getCommandType(medtronicDeviceType: MedtronicDeviceType?): MedtronicCommandType? { + fun getCommandType(medtronicDeviceType: MedtronicDeviceType): MedtronicCommandType? { return if (this == Configuration) { MedtronicCommandType.getSettings(medtronicDeviceType) } else diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt index 75a399f1eb..6257099574 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/MedtronicHistoryActivity.kt @@ -22,8 +22,8 @@ import javax.inject.Inject class MedtronicHistoryActivity : DaggerActivity() { - @Inject lateinit var medtronicHistoryData: MedtronicHistoryData - @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var medtronicHistoryData: MedtronicHistoryData + @Inject lateinit var resourceHelper: ResourceHelper lateinit var historyTypeSpinner: Spinner lateinit var statusView: TextView @@ -33,7 +33,7 @@ class MedtronicHistoryActivity : DaggerActivity() { var filteredHistoryList: MutableList = ArrayList() var manualChange = false - var typeListFull: List? = null + lateinit var typeListFull: List //private var _binding: MedtronicHistoryActivityBinding? = null @@ -60,8 +60,8 @@ class MedtronicHistoryActivity : DaggerActivity() { } } - recyclerViewAdapter.setHistoryListInternal(filteredHistoryList) - recyclerViewAdapter.notifyDataSetChanged() + recyclerViewAdapter.setHistoryListInternal(filteredHistoryList) + recyclerViewAdapter.notifyDataSetChanged() //LOG.debug("Items on filtered list: {}", filteredHistoryList.size()); } @@ -74,8 +74,8 @@ class MedtronicHistoryActivity : DaggerActivity() { private fun setHistoryTypeSpinner() { manualChange = true - for (i in typeListFull!!.indices) { - if (typeListFull!![i].entryGroup === selectedGroup) { + for (i in typeListFull.indices) { + if (typeListFull[i].entryGroup === selectedGroup) { historyTypeSpinner.setSelection(i) break } @@ -119,15 +119,16 @@ class MedtronicHistoryActivity : DaggerActivity() { }) } - private fun getTypeList(list: List?): List { + private fun getTypeList(list: List): List { val typeList = ArrayList() - for (pumpHistoryEntryGroup in list!!) { + for (pumpHistoryEntryGroup in list) { typeList.add(TypeList(pumpHistoryEntryGroup)) } return typeList } class TypeList internal constructor(var entryGroup: PumpHistoryEntryGroup) { + var name: String override fun toString(): String { return name @@ -140,7 +141,6 @@ class MedtronicHistoryActivity : DaggerActivity() { class RecyclerViewAdapter internal constructor(var historyList: List) : RecyclerView.Adapter() { - fun setHistoryListInternal(historyList: List) { // this.historyList.clear(); // this.historyList.addAll(historyList); @@ -157,22 +157,17 @@ class MedtronicHistoryActivity : DaggerActivity() { override fun onBindViewHolder(holder: HistoryViewHolder, position: Int) { val record = historyList[position] - //if (record != null) { - holder.timeView.text = record.dateTimeString - holder.typeView.text = record.entryType.description - holder.valueView.text = record.displayableValue - //} + holder.timeView.text = record.dateTimeString + holder.typeView.text = record.entryType.description + holder.valueView.text = record.displayableValue } override fun getItemCount(): Int { return historyList.size } - override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { - super.onAttachedToRecyclerView(recyclerView) - } - class HistoryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var timeView: TextView var typeView: TextView var valueView: TextView @@ -188,6 +183,7 @@ class MedtronicHistoryActivity : DaggerActivity() { } companion object { + var showingType: TypeList? = null var selectedGroup = PumpHistoryEntryGroup.All } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index c5122ca1e8..e659db4962 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -27,14 +27,14 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour private val sp: SP, private val rxBus: RxBusWrapper, private val rileyLinkUtil: RileyLinkUtil -) : PumpStatus(PumpType.MEDTRONIC_522_722) { +) : info.nightscout.androidaps.plugins.pump.common.data.PumpStatus(PumpType.MEDTRONIC_522_722) { var errorDescription: String? = null lateinit var serialNumber: String //? = null var pumpFrequency: String? = null var maxBolus: Double? = null var maxBasal: Double? = null - var runningTBR: PumpDbEntry? = null + var runningTBR: info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry? = null // statuses var pumpDeviceState = PumpDeviceState.NeverContacted diff --git a/pump-common/.gitignore b/pump-common/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/pump-common/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/pump-common/build.gradle b/pump-common/build.gradle new file mode 100644 index 0000000000..996daf31dd --- /dev/null +++ b/pump-common/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'com.hiya.jacoco-android' + +apply from: "${project.rootDir}/gradle/android_dependencies.gradle" +apply from: "${project.rootDir}/gradle/android_module_dependencies.gradle" +apply from: "${project.rootDir}/gradle/test_dependencies.gradle" + +android { + defaultConfig { + versionCode 1 + versionName "1.0" + } +} + +dependencies { + implementation project(':core') + //implementation project(':database') + + implementation('com.thoughtworks.xstream:xstream:1.4.7') { + exclude group: 'xmlpull', module: 'xmlpull' + } +} diff --git a/pump-common/consumer-rules.pro b/pump-common/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pump-common/proguard-rules.pro b/pump-common/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/pump-common/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/pump-common/src/main/AndroidManifest.xml b/pump-common/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..d4055a4210 --- /dev/null +++ b/pump-common/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt similarity index 96% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index b2462ade1f..a9a871f0b5 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -24,9 +24,6 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewB 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.plugins.pump.common.sync.PumpDbEntryCarbs -import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator -import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter.to0Decimal import info.nightscout.androidaps.utils.DecimalFormatter.to2Decimal @@ -38,7 +35,6 @@ import io.reactivex.disposables.CompositeDisposable import org.json.JSONException import org.json.JSONObject - /** * Created by andy on 23.04.18. */ @@ -58,14 +54,14 @@ abstract class PumpPluginAbstract protected constructor( var dateUtil: DateUtil, var aapsSchedulers: AapsSchedulers, var pumpSync: PumpSync, - var pumpSyncStorage: PumpSyncStorage -) : PumpPluginBase(pluginDescription!!, injector!!, aapsLogger, resourceHelper, commandQueue), Pump, Constraints, PumpSyncEntriesCreator { + var pumpSyncStorage: info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage +) : PumpPluginBase(pluginDescription!!, injector!!, aapsLogger, resourceHelper, commandQueue), Pump, Constraints, info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator { private val disposable = CompositeDisposable() // Pump capabilities final override var pumpDescription = PumpDescription() - //protected set + //protected set @JvmField protected var serviceConnection: ServiceConnection? = null @JvmField protected var serviceRunning = false @@ -79,7 +75,6 @@ abstract class PumpPluginAbstract protected constructor( pumpDescription.fillFor(value) } - protected var gson = GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() abstract fun initPumpStatusData() @@ -282,7 +277,7 @@ abstract class PumpPluginAbstract protected constructor( override fun shortStatus(veryShort: Boolean): String { var ret = "" - if (pumpStatusData.lastConnection==0L) { + if (pumpStatusData.lastConnection == 0L) { ret += "LastConn: never\n" } else { val agoMsec = System.currentTimeMillis() - pumpStatusData.lastConnection @@ -343,7 +338,7 @@ abstract class PumpPluginAbstract protected constructor( detailedBolusInfo.timestamp = System.currentTimeMillis() // no bolus required, carb only treatment - pumpSyncStorage.addCarbs(PumpDbEntryCarbs(detailedBolusInfo, this)) + pumpSyncStorage.addCarbs(info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs(detailedBolusInfo, this)) val bolusingEvent = EventOverviewBolusProgress bolusingEvent.t = EventOverviewBolusProgress.Treatment(0.0, detailedBolusInfo.carbs.toInt(), detailedBolusInfo.bolusType === DetailedBolusInfo.BolusType.SMB) @@ -370,12 +365,11 @@ abstract class PumpPluginAbstract protected constructor( return pumpType } - override fun canHandleDST(): Boolean { return false } - protected abstract fun deliverBolus(detailedBolusInfo: DetailedBolusInfo?): PumpEnactResult + protected abstract fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult protected abstract fun triggerUIChange() @@ -383,7 +377,6 @@ abstract class PumpPluginAbstract protected constructor( return PumpEnactResult(injector).success(false).enacted(false).comment(resourceId) } - init { pumpDescription.fillFor(pumpType) this.pumpType = pumpType diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt similarity index 78% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt index c84312cebc..e1b734b048 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpDbEntry.kt @@ -4,14 +4,13 @@ import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.plugins.pump.common.defs.PumpType - data class PumpDbEntry constructor(var temporaryId: Long, - var date: Long, - var pumpType: PumpType, - var serialNumber: String, - var bolusData: PumpDbEntryBolus? = null, - var tbrData: PumpDbEntryTBR? = null, - var pumpId: Long? = null) { + var date: Long, + var pumpType: PumpType, + var serialNumber: String, + var bolusData: PumpDbEntryBolus? = null, + var tbrData: PumpDbEntryTBR? = null, + var pumpId: Long? = null) { constructor(temporaryId: Long, date: Long, @@ -41,7 +40,6 @@ data class PumpDbEntry constructor(var temporaryId: Long, } - data class PumpDbEntryBolus(var insulin: Double, var carbs: Double, var bolusType: DetailedBolusInfo.BolusType) @@ -51,11 +49,12 @@ data class PumpDbEntryCarbs(var date: Long, var pumpType: PumpType, var serialNumber: String, var pumpId: Long? = null) { + constructor(detailedBolusInfo: DetailedBolusInfo, creator: PumpSyncEntriesCreator) : this(detailedBolusInfo.timestamp, - detailedBolusInfo.carbs, - creator.model(), - creator.serialNumber()) + detailedBolusInfo.carbs, + creator.model(), + creator.serialNumber()) } data class PumpDbEntryTBR(var rate: Double, diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncEntriesCreator.java diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt similarity index 90% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt index 99903e73cb..8084d52cd6 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/sync/PumpSyncStorage.kt @@ -2,14 +2,12 @@ package info.nightscout.androidaps.plugins.pump.common.sync import com.google.gson.Gson import com.google.gson.GsonBuilder -import com.google.gson.reflect.TypeToken import com.thoughtworks.xstream.XStream import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.utils.sharedPreferences.SP -import java.lang.reflect.Type import java.util.* import javax.inject.Inject import javax.inject.Singleton @@ -25,19 +23,17 @@ class PumpSyncStorage @Inject constructor( ) { val pumpSyncStorageKey: String = "pump_sync_storage_xstream" - var pumpSyncStorage: MutableMap> = mutableMapOf() + var pumpSyncStorage: MutableMap> = mutableMapOf() var TBR: String = "TBR" var BOLUS: String = "BOLUS" var storageInitialized: Boolean = false var gson: Gson = GsonBuilder().create() var xstream: XStream = XStream() - init { initStorage() } - fun initStorage() { if (storageInitialized) return @@ -61,7 +57,6 @@ class PumpSyncStorage @Inject constructor( } } - fun saveStorage() { if (!isStorageEmpty()) { sp.putString(pumpSyncStorageKey, xstream.toXML(pumpSyncStorage)) @@ -69,22 +64,18 @@ class PumpSyncStorage @Inject constructor( } } - - fun isStorageEmpty() : Boolean { + fun isStorageEmpty(): Boolean { return pumpSyncStorage[BOLUS]!!.isEmpty() && pumpSyncStorage[TBR]!!.isEmpty() } - - fun getBoluses() : MutableList { + fun getBoluses(): MutableList { return pumpSyncStorage[BOLUS]!!; } - - fun getTBRs() : MutableList { + fun getTBRs(): MutableList { return pumpSyncStorage[TBR]!!; } - fun addBolusWithTempId(detailedBolusInfo: DetailedBolusInfo, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator): Boolean { val temporaryId = creator.generateTempId(detailedBolusInfo.timestamp) val result = pumpSync.addBolusWithTempId( @@ -99,12 +90,12 @@ class PumpSyncStorage @Inject constructor( detailedBolusInfo.timestamp, temporaryId, detailedBolusInfo.insulin, detailedBolusInfo.bolusType, creator.serialNumber(), result)) - if (detailedBolusInfo.carbs>0.0) { + if (detailedBolusInfo.carbs > 0.0) { addCarbs(PumpDbEntryCarbs(detailedBolusInfo, creator)) } if (result && writeToInternalHistory) { - var innerList: MutableList = pumpSyncStorage[BOLUS]!! + val innerList: MutableList = pumpSyncStorage[BOLUS]!! innerList.add(PumpDbEntry(temporaryId, detailedBolusInfo.timestamp, creator.model(), creator.serialNumber(), detailedBolusInfo)) pumpSyncStorage[BOLUS] = innerList @@ -113,7 +104,6 @@ class PumpSyncStorage @Inject constructor( return result } - fun addCarbs(carbsDto: PumpDbEntryCarbs) { val result = pumpSync.syncCarbsWithTimestamp( carbsDto.date, @@ -126,9 +116,8 @@ class PumpSyncStorage @Inject constructor( carbsDto.date, carbsDto.carbs, carbsDto.serialNumber, result)) } - - fun addTemporaryBasalRateWithTempId(temporaryBasal: PumpDbEntryTBR, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator) : Boolean { - val timenow : Long = System.currentTimeMillis() + fun addTemporaryBasalRateWithTempId(temporaryBasal: PumpDbEntryTBR, writeToInternalHistory: Boolean, creator: PumpSyncEntriesCreator): Boolean { + val timenow: Long = System.currentTimeMillis() val temporaryId = creator.generateTempId(timenow) val response = pumpSync.addTemporaryBasalWithTempId( @@ -142,7 +131,7 @@ class PumpSyncStorage @Inject constructor( creator.serialNumber()) if (response && writeToInternalHistory) { - var innerList: MutableList = pumpSyncStorage[TBR]!! + val innerList: MutableList = pumpSyncStorage[TBR]!! innerList.add(PumpDbEntry(temporaryId, timenow, creator.model(), creator.serialNumber(), null, temporaryBasal)) pumpSyncStorage[BOLUS] = innerList @@ -152,21 +141,18 @@ class PumpSyncStorage @Inject constructor( return response; } - fun removeBolusWithTemporaryId(temporaryId: Long) { val bolusList = removeTemporaryId(temporaryId, pumpSyncStorage[BOLUS]!!) pumpSyncStorage[BOLUS] = bolusList saveStorage() } - fun removeTemporaryBasalWithTemporaryId(temporaryId: Long) { val tbrList = removeTemporaryId(temporaryId, pumpSyncStorage[TBR]!!) pumpSyncStorage[TBR] = tbrList saveStorage() } - private fun removeTemporaryId(temporaryId: Long, list: MutableList): MutableList { var dbEntry: PumpDbEntry? = null @@ -176,7 +162,7 @@ class PumpSyncStorage @Inject constructor( } } - if (dbEntry!=null) { + if (dbEntry != null) { list.remove(dbEntry) } diff --git a/pump-common/src/main/res/values/strings.xml b/pump-common/src/main/res/values/strings.xml new file mode 100644 index 0000000000..0d2c4cc409 --- /dev/null +++ b/pump-common/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index a35251b846..15a8fcf539 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,8 +8,10 @@ include ':combo' include ':dana' include ':danar' include ':danars' +include ':pump-common' include ':rileylink' include ':medtronic' include ':omnipod-common' include ':omnipod-eros' -include ':omnipod-dash' \ No newline at end of file +include ':omnipod-dash' + From 029eb55f0e0d084c51bfd21a36c32dcfeb7f3ccb Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 26 May 2021 13:14:17 +0100 Subject: [PATCH 33/39] - changes according to comment in PR - moved files from core to pump-common (which we could without major changes) - removed DbObjectBase, and removed its deps in files (3) - changed id for rileylink project (was the same as for pump-common) --- app/build.gradle | 2 +- .../dependencyInjection/AppComponent.kt | 4 +- .../dependencyInjection/AppModule.kt | 19 +- .../treatments/TreatmentsPlugin.java.orig | 343 ++++++++++++++++++ app/src/main/res/values-v21/strings.xml | 4 + app/src/main/res/values-w820dp/strings.xml | 4 + core/build.gradle | 4 - .../nightscout/androidaps/db/DbObjectBase.kt | 8 - .../androidaps/db/OmnipodHistoryRecord.java | 4 +- .../androidaps/db/TemporaryBasal.java | 4 +- .../nightscout/androidaps/db/Treatment.java | 6 +- core/src/main/res/values/strings.xml | 26 -- .../pump/medtronic/MedtronicPumpPlugin.kt | 5 - .../cgms/MedtronicCGMSHistoryDecoder.kt | 1 - .../medtronic/comm/message/MessageBody.kt | 2 +- .../pump/medtronic/comm/ui/MedtronicUITask.kt | 28 +- .../medtronic/data/MedtronicHistoryData.kt | 4 - .../pump/medtronic/di/MedtronicModule.kt | 15 +- .../dialog/RileyLinkStatusDeviceMedtronic.kt | 15 +- .../medtronic/driver/MedtronicPumpStatus.kt | 2 - omnipod-eros/build.gradle | 1 + .../omnipod/eros/OmnipodErosPumpPlugin.java | 22 +- .../plugins/pump/common/PumpPluginAbstract.kt | 2 +- .../plugins/pump/common/data/PumpStatus.kt | 3 +- .../pump/common/defs/PumpDeviceState.kt | 2 +- .../pump/common/defs/PumpDriverState.kt | 0 .../pump/common/defs/PumpHistoryEntryGroup.kt | 2 +- .../pump/common/defs/PumpStatusType.kt | 0 .../plugins/pump/common/defs/TempBasalPair.kt | 0 .../pump/common/di/PumpCommonModule.kt | 25 ++ .../plugins/pump/common/utils/ByteUtil.java | 0 .../plugins/pump/common/utils/ProfileUtil.kt | 0 .../plugins/pump/common/utils/StringUtil.java | 0 .../plugins/pump/common/utils/ThreadUtil.java | 0 pump-common/src/main/res/values/strings.xml | 28 ++ rileylink/build.gradle | 1 + rileylink/src/main/AndroidManifest.xml | 6 +- .../dialog/RileyLinkBLEConfigActivity.java | 2 +- .../common/hw/rileylink/RileyLinkConst.java | 2 - .../pump/common/hw/rileylink/ble/RFSpy.java | 2 +- .../ble/defs/RileyLinkEncodingType.java | 8 +- .../hw/rileylink/defs/RileyLinkError.java | 6 +- .../rileylink/defs/RileyLinkServiceState.java | 22 +- .../rileylink/defs/RileyLinkTargetDevice.java | 2 +- .../dialog/RileyLinkStatusActivity.java | 5 +- .../dialog/RileyLinkStatusDevice.java | 9 +- .../RileyLinkStatusGeneralFragment.java | 2 +- .../RileyLinkStatusHistoryFragment.java | 5 +- 48 files changed, 502 insertions(+), 155 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig create mode 100644 app/src/main/res/values-v21/strings.xml create mode 100644 app/src/main/res/values-w820dp/strings.xml delete mode 100644 core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt (91%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt (96%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt (100%) create mode 100644 pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/di/PumpCommonModule.kt rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java (100%) rename {core => pump-common}/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java (100%) diff --git a/app/build.gradle b/app/build.gradle index faaa85cae6..d27743c7f9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -250,6 +250,6 @@ if (isMaster() && !gitAvailable()) { throw new GradleException('GIT system is not available. On Windows try to run Android Studio as an Administrator. Check if GIT is installed and Studio have permissions to use it') } if (isMaster() && !allCommitted()) { - throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update') + //throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update') } diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt index 1421d586ed..5b74972932 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt @@ -8,13 +8,14 @@ import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.automation.di.AutomationModule import info.nightscout.androidaps.combo.di.ComboModule import info.nightscout.androidaps.dana.di.DanaHistoryModule -import info.nightscout.androidaps.di.CoreModule import info.nightscout.androidaps.dana.di.DanaModule import info.nightscout.androidaps.danar.di.DanaRModule import info.nightscout.androidaps.danars.di.DanaRSModule import info.nightscout.androidaps.database.DatabaseModule +import info.nightscout.androidaps.di.CoreModule import info.nightscout.androidaps.insight.di.InsightDatabaseModule import info.nightscout.androidaps.insight.di.InsightModule +import info.nightscout.androidaps.plugins.pump.common.di.PumpCommonModule import info.nightscout.androidaps.plugins.pump.common.di.RileyLinkModule import info.nightscout.androidaps.plugins.pump.medtronic.di.MedtronicModule import info.nightscout.androidaps.plugins.pump.omnipod.eros.dagger.OmnipodErosModule @@ -36,6 +37,7 @@ import javax.inject.Singleton CommandQueueModule::class, ObjectivesModule::class, WizardModule::class, + PumpCommonModule::class, RileyLinkModule::class, MedtronicModule::class, OmnipodErosModule::class, diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt index 9946d55cd0..d1a2962a3f 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt @@ -20,7 +20,6 @@ import info.nightscout.androidaps.plugins.general.nsclient.DataSyncSelectorImple import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation -import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.CommandQueue import info.nightscout.androidaps.utils.DateUtil @@ -71,16 +70,6 @@ open class AppModule { return ProfileFunctionImplementation(aapsLogger, sp, resourceHelper, activePlugin, repository, dateUtil) } - @Provides - @Singleton - fun providesPumpSyncStorage( - pumpSync: PumpSync, - sp: SP, - aapsLogger: AAPSLogger - ): info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage { - return info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage(pumpSync, sp, aapsLogger) - } - @Module interface AppBindings { @@ -89,22 +78,30 @@ open class AppModule { @Binds fun bindActivePluginProvider(pluginStore: PluginStore): ActivePlugin @Binds fun bindCommandQueueProvider(commandQueue: CommandQueue): CommandQueueProvider @Binds fun bindConfigInterface(config: ConfigImpl): Config + @Binds fun bindConfigBuilderInterface(configBuilderPlugin: ConfigBuilderPlugin): ConfigBuilder @Binds fun bindTreatmentsInterface(treatmentsPlugin: TreatmentsPlugin): TreatmentsInterface + @Binds fun bindDatabaseHelperInterface(databaseHelperProvider: DatabaseHelperProvider): DatabaseHelperInterface + @Binds fun bindNotificationHolderInterface(notificationHolder: NotificationHolderImpl): NotificationHolder + @Binds fun bindImportExportPrefsInterface(importExportPrefs: ImportExportPrefsImpl): ImportExportPrefs + @Binds fun bindIconsProviderInterface(iconsProvider: IconsProviderImplementation): IconsProvider @Binds fun bindLoopInterface(loopPlugin: LoopPlugin): LoopInterface + @Binds fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculator + @Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicator + @Binds fun bindDataSyncSelector(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector @Binds fun bindPumpSync(pumpSyncImplementation: PumpSyncImplementation): PumpSync diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig new file mode 100644 index 0000000000..28b960101f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig @@ -0,0 +1,343 @@ +package info.nightscout.androidaps.plugins.treatments; + +import android.content.Context; +import android.os.Bundle; + +import com.google.firebase.analytics.FirebaseAnalytics; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import dagger.android.HasAndroidInjector; +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.activities.ErrorHelperActivity; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.database.AppRepository; +import info.nightscout.androidaps.db.ExtendedBolus; +import info.nightscout.androidaps.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; +import info.nightscout.androidaps.db.Treatment; +import info.nightscout.androidaps.interfaces.ActivePlugin; +import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.ProfileFunction; +import info.nightscout.androidaps.interfaces.TreatmentServiceInterface; +import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.interfaces.UpdateReturn; +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.bus.RxBusWrapper; +<<<<<<< HEAD +import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; +import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; +import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; +======= +>>>>>>> dev2_dana_combo_only +import info.nightscout.androidaps.utils.DateUtil; +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; + +@Singleton +public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface { + +<<<<<<< HEAD + private final Context context; + private final AapsSchedulers aapsSchedulers; +======= +>>>>>>> dev2_dana_combo_only + private final SP sp; + private final RxBusWrapper rxBus; + private final ResourceHelper resourceHelper; + private final ProfileFunction profileFunction; + private final ActivePlugin activePlugin; + private final FabricPrivacy fabricPrivacy; + private final DateUtil dateUtil; + private final DatabaseHelperInterface databaseHelper; + private final AppRepository repository; + + private final CompositeDisposable disposable = new CompositeDisposable(); + + protected TreatmentServiceInterface service; + private final boolean useNewPumpSync = false; + + + @Inject + public TreatmentsPlugin( + HasAndroidInjector injector, + AAPSLogger aapsLogger, + RxBusWrapper rxBus, + AapsSchedulers aapsSchedulers, + ResourceHelper resourceHelper, + Context context, + SP sp, + ProfileFunction profileFunction, + ActivePlugin activePlugin, + FabricPrivacy fabricPrivacy, + DateUtil dateUtil, + DatabaseHelperInterface databaseHelper, + AppRepository repository + ) { + super(new PluginDescription() + .mainType(PluginType.TREATMENT) + .fragmentClass(TreatmentsFragment.class.getName()) + .pluginIcon(R.drawable.ic_treatments) + .pluginName(R.string.treatments) + .shortName(R.string.treatments_shortname) + .alwaysEnabled(true) + .description(R.string.description_treatments) + .setDefault(), + aapsLogger, resourceHelper, injector + ); + this.resourceHelper = resourceHelper; + this.context = context; + this.rxBus = rxBus; + this.sp = sp; + this.profileFunction = profileFunction; + this.activePlugin = activePlugin; + this.fabricPrivacy = fabricPrivacy; + this.dateUtil = dateUtil; + this.databaseHelper = databaseHelper; + this.repository = repository; + } + + @Override + protected void onStart() { + this.service = new TreatmentService(getInjector()); + super.onStart(); +// disposable.add(rxBus +// .toObservable(EventReloadProfileSwitchData.class) +// .observeOn(aapsSchedulers.getIo()) +// .subscribe(event -> initializeProfileSwitchData(range()), +// fabricPrivacy::logException +// )); + } + + @Override + protected void onStop() { + disposable.clear(); + super.onStop(); + } + + @Override + public TreatmentServiceInterface getService() { + return this.service; + } + + protected long range() { + double dia = Constants.defaultDIA; + if (profileFunction.getProfile() != null) + dia = profileFunction.getProfile().getDia(); + return (long) (60 * 60 * 1000L * (24 + dia)); + } + + /** + * Returns all Treatments after specified timestamp. Also returns invalid entries (required to + * map "Fill Cannula" entries to history (and not to add double bolus for it) + * + * @param fromTimestamp + * @return + */ + @Deprecated + @Override + public List getTreatmentsFromHistoryAfterTimestamp(long fromTimestamp) { + return repository.getBolusesIncludingInvalidFromTimeToTime(fromTimestamp, dateUtil.now(), true) + .blockingGet() + .stream() + .map(bolus -> new Treatment(getInjector(), bolus)) + .collect(Collectors.toList()); +/* + List in5minback = new ArrayList<>(); + + long time = System.currentTimeMillis(); + synchronized (treatments) { +// getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: AllTreatmentsInDb: " + new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(treatments)); + + for (Treatment t : treatments) { + if (t.date >= fromTimestamp && t.date <= time) + in5minback.add(t); + } +// getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: FilteredTreatments: AfterTime={}, Items={} " + fromTimestamp + " " + new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(in5minback)); + return in5minback; + } +*/ + } +/* + @Override + public long getLastBolusTime() { + Treatment last = getService().getLastBolus(false); + if (last == null) { + getAapsLogger().debug(LTag.DATATREATMENTS, "Last bolus time: NOTHING FOUND"); + return 0; + } else { + getAapsLogger().debug(LTag.DATATREATMENTS, "Last bolus time: " + dateUtil.dateAndTimeString(last.date)); + return last.date; + } + } + + public long getLastBolusTime(boolean excludeSMB) { + Treatment last = getService().getLastBolus(excludeSMB); + if (last == null) { + getAapsLogger().debug(LTag.DATATREATMENTS, "Last manual bolus time: NOTHING FOUND"); + return 0; + } else { + getAapsLogger().debug(LTag.DATATREATMENTS, "Last manual bolus time: " + dateUtil.dateAndTimeString(last.date)); + return last.date; + } + } + + public long getLastCarbTime() { + Treatment last = getService().getLastCarb(); + if (last == null) { + getAapsLogger().debug(LTag.DATATREATMENTS, "Last Carb time: NOTHING FOUND"); + return 0; + } else { + getAapsLogger().debug(LTag.DATATREATMENTS, "Last Carb time: " + dateUtil.dateAndTimeString(last.date)); + return last.date; + } + } + + + */ + + @Deprecated + @Override + public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) { + throw new IllegalStateException("Migrate to new DB"); + //log.debug("Adding new ExtentedBolus record" + extendedBolus.log()); + /* + boolean newRecordCreated = databaseHelper.createOrUpdate(extendedBolus); + if (newRecordCreated) { + if (extendedBolus.durationInMinutes == 0) { + if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses()) + nsUpload.uploadTempBasalEnd(extendedBolus.date, true, extendedBolus.pumpId); + else + nsUpload.uploadExtendedBolusEnd(extendedBolus.date, extendedBolus.pumpId); + } else if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses()) + nsUpload.uploadTempBasalStartAbsolute(new TemporaryBasal(extendedBolus), extendedBolus.insulin); + else + nsUpload.uploadExtendedBolus(extendedBolus); + } + return newRecordCreated; + */ + } + + @Deprecated + @Override + public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { + if (useNewPumpSync) { + throw new IllegalStateException("Migrate to new DB"); + } else { + getAapsLogger().error("!!! addToHistoryTempBasal: Need to migrate to new DB"); + } + + //log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); + boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal); + if (newRecordCreated) { +// if (tempBasal.durationInMinutes == 0) +// nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); +// else if (tempBasal.isAbsolute) +// nsUpload.uploadTempBasalStartAbsolute(tempBasal, null); +// else +// nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); + } + return newRecordCreated; + } + + @Deprecated + public TreatmentUpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout) { + if (useNewPumpSync) { + throw new IllegalStateException("Migrate to new DB"); + } else { + getAapsLogger().error("!!! createOrUpdateMedtronic: Need to migrate to new DB"); + } + + UpdateReturn resultRecord = getService().createOrUpdateMedtronic(treatment, fromNightScout); + + return new TreatmentUpdateReturn(resultRecord.getSuccess(), resultRecord.getNewRecord()); + } + + // return true if new record is created + @Deprecated + @Override + public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) { + if (useNewPumpSync) { + throw new IllegalStateException("Migrate to new DB"); + } else { + getAapsLogger().error("!!! addToHistoryTreatment: Need to migrate to new DB"); + } + + boolean medtronicPump = activePlugin.getActivePump() instanceof MedtronicPumpPlugin; + + getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={} " + medtronicPump); + + Treatment treatment = new Treatment(); + treatment.date = detailedBolusInfo.timestamp; + treatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP; + treatment.pumpId = detailedBolusInfo.getBolusPumpId() != null ? detailedBolusInfo.getBolusPumpId() : 0; + treatment.insulin = detailedBolusInfo.insulin; + treatment.isValid = detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING; + treatment.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB; + if (detailedBolusInfo.carbTime == 0) + treatment.carbs = detailedBolusInfo.carbs; + treatment.mealBolus = treatment.carbs > 0; + // treatment.boluscalc = detailedBolusInfo.boluscalc != null ? detailedBolusInfo.boluscalc.toString() : null; + treatment.boluscalc = null; + UpdateReturn creatOrUpdateResult; + + getAapsLogger().debug(medtronicPump && MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::treatment={} " + treatment); + + if (!medtronicPump) + creatOrUpdateResult = getService().createOrUpdate(treatment); + else + creatOrUpdateResult = getService().createOrUpdateMedtronic(treatment, false); + + boolean newRecordCreated = creatOrUpdateResult.getNewRecord(); + //log.debug("Adding new Treatment record" + treatment.toString()); + if (detailedBolusInfo.carbTime != 0) { + + Treatment carbsTreatment = new Treatment(); + carbsTreatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP; + carbsTreatment.pumpId = detailedBolusInfo.getCarbsPumpId() != null ? detailedBolusInfo.getCarbsPumpId() : 0; // but this should never happen + carbsTreatment.date = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records + carbsTreatment.carbs = detailedBolusInfo.carbs; + + getAapsLogger().debug(medtronicPump && MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: carbTime!=0, creating second treatment. CarbsTreatment={}" + carbsTreatment); + + if (!medtronicPump) + getService().createOrUpdate(carbsTreatment); + else + getService().createOrUpdateMedtronic(carbsTreatment, false); + //log.debug("Adding new Treatment record" + carbsTreatment); + } + + getAapsLogger().error("nsUpload.uploadTreatmentRecord(detailedBolusInfo) not possible."); +// if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) +// nsUpload.uploadTreatmentRecord(detailedBolusInfo); + + if (!allowUpdate && !creatOrUpdateResult.getSuccess()) { + getAapsLogger().error("Treatment could not be added to DB", new Exception()); + + String status = String.format(resourceHelper.gs(R.string.error_adding_treatment_message), treatment.insulin, (int) treatment.carbs, dateUtil.dateAndTimeString(treatment.date)); + + ErrorHelperActivity.Companion.runAlarm(context, status, resourceHelper.gs(R.string.error_adding_treatment_title), R.raw.error); + + Bundle bundle = new Bundle(); + bundle.putString(FirebaseAnalytics.Param.ITEM_LIST_ID, "TreatmentClash"); + bundle.putString(FirebaseAnalytics.Param.ITEM_LIST_NAME, status); + fabricPrivacy.logCustom(bundle); + } + + return newRecordCreated; + + } +} diff --git a/app/src/main/res/values-v21/strings.xml b/app/src/main/res/values-v21/strings.xml new file mode 100644 index 0000000000..adec7323c6 --- /dev/null +++ b/app/src/main/res/values-v21/strings.xml @@ -0,0 +1,4 @@ + + + Connection Error + \ No newline at end of file diff --git a/app/src/main/res/values-w820dp/strings.xml b/app/src/main/res/values-w820dp/strings.xml new file mode 100644 index 0000000000..adec7323c6 --- /dev/null +++ b/app/src/main/res/values-w820dp/strings.xml @@ -0,0 +1,4 @@ + + + Connection Error + \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index 94176e85dc..9b2d54be1e 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -18,9 +18,5 @@ android { dependencies { implementation project(':database') - - implementation ('com.thoughtworks.xstream:xstream:1.4.7') { - exclude group: 'xmlpull', module: 'xmlpull' - } } diff --git a/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt b/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt deleted file mode 100644 index 85869e9bae..0000000000 --- a/core/src/main/java/info/nightscout/androidaps/db/DbObjectBase.kt +++ /dev/null @@ -1,8 +0,0 @@ -package info.nightscout.androidaps.db - -@Deprecated("This class is not needed for new database anymore") -interface DbObjectBase { - - fun getDate(): Long - fun getPumpId(): Long -} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java b/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java index 0f4b56b096..584f6cc150 100644 --- a/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java +++ b/core/src/main/java/info/nightscout/androidaps/db/OmnipodHistoryRecord.java @@ -9,7 +9,7 @@ import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; * Created by andy on 30.11.2019. */ @DatabaseTable(tableName = "PodHistory") -public class OmnipodHistoryRecord implements DbObjectBase, Comparable { +public class OmnipodHistoryRecord implements Comparable { @DatabaseField(id = true) public long date; @@ -42,7 +42,6 @@ public class OmnipodHistoryRecord implements DbObjectBase, ComparableTime detection %1$dh %2$dm - - Operation not supported by pump and/or driver. - Operation not YET supported by pump. - OK - - - Never contacted - Waking up - Error with communication - Timeout on communication - Pump unreachable - Invalid configuration - Active - Sleeping - - - Basals - Configurations - Notifications - Statistics - Unknowns - All - Boluses - Prime - Alarms - Glucose Mute for 5 minutes diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index a0649be977..a40940bab4 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -21,8 +21,6 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification -import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract -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.plugins.pump.common.events.EventRefreshButtonState @@ -34,9 +32,6 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask -import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR -import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncEntriesCreator -import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt index 9bd0b1fa6a..218330d6be 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/MedtronicCGMSHistoryDecoder.kt @@ -6,7 +6,6 @@ import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.MedtronicHistoryDecoder import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RecordDecodeStatus -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSHistoryEntryType import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.cgms.CGMSHistoryEntryType.Companion.getByCode import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil import okhttp3.internal.and diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt index 0dd03de7dd..45bfdcf5de 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/message/MessageBody.kt @@ -15,7 +15,7 @@ open class MessageBody { open fun init(rxData: ByteArray?) {} open val txData: ByteArray? - get() = if (data==null) byteArrayOf() else data + get() = if (data == null) byteArrayOf() else data override fun toString(): String { val sb = StringBuilder(javaClass.simpleName) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt index 3685db287c..a401e061fa 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/ui/MedtronicUITask.kt @@ -52,67 +52,67 @@ class MedtronicUITask { fun execute(communicationManager: MedtronicCommunicationManager) { aapsLogger.debug(LTag.PUMP, "MedtronicUITask: @@@ In execute. $commandType") when (commandType) { - MedtronicCommandType.PumpModel -> { + MedtronicCommandType.PumpModel -> { result = communicationManager.getPumpModel() } - MedtronicCommandType.GetBasalProfileSTD -> { + MedtronicCommandType.GetBasalProfileSTD -> { result = communicationManager.getBasalProfile() } - MedtronicCommandType.GetRemainingInsulin -> { + MedtronicCommandType.GetRemainingInsulin -> { result = communicationManager.getRemainingInsulin() } - MedtronicCommandType.GetRealTimeClock -> { + MedtronicCommandType.GetRealTimeClock -> { result = communicationManager.getPumpTime() //medtronicUtil.pumpTime = null } - MedtronicCommandType.SetRealTimeClock -> { + MedtronicCommandType.SetRealTimeClock -> { result = communicationManager.setPumpTime() } - MedtronicCommandType.GetBatteryStatus -> { + MedtronicCommandType.GetBatteryStatus -> { result = communicationManager.getRemainingBattery() } - MedtronicCommandType.SetTemporaryBasal -> { + MedtronicCommandType.SetTemporaryBasal -> { val tbr = getTbrSettings() if (tbr != null) { result = communicationManager.setTemporaryBasal(tbr) } } - MedtronicCommandType.ReadTemporaryBasal -> { + MedtronicCommandType.ReadTemporaryBasal -> { result = communicationManager.getTemporaryBasal() } - MedtronicCommandType.Settings, MedtronicCommandType.Settings_512 -> { + MedtronicCommandType.Settings, MedtronicCommandType.Settings_512 -> { result = communicationManager.getPumpSettings() } - MedtronicCommandType.SetBolus -> { + MedtronicCommandType.SetBolus -> { val amount = getDoubleFromParameters(0) if (amount != null) result = communicationManager.setBolus(amount) } - MedtronicCommandType.CancelTBR -> { + MedtronicCommandType.CancelTBR -> { result = communicationManager.cancelTBR() } MedtronicCommandType.SetBasalProfileSTD, - MedtronicCommandType.SetBasalProfileA -> { + MedtronicCommandType.SetBasalProfileA -> { val profile = parameters!![0] as BasalProfile result = communicationManager.setBasalProfile(profile) } - MedtronicCommandType.GetHistoryData -> { + MedtronicCommandType.GetHistoryData -> { result = communicationManager.getPumpHistory(parameters!![0] as PumpHistoryEntry?, parameters!![1] as LocalDateTime?) } - else -> { + else -> { aapsLogger.warn(LTag.PUMP, String.format(Locale.ENGLISH, "This commandType is not supported (yet) - %s.", commandType)) // invalid = true; responseType = MedtronicUIResponseType.Invalid diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 3f828417a8..cb904b9afe 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -11,10 +11,6 @@ import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.defs.PumpType -import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry -import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryCarbs -import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR -import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage 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.MedtronicPumpHistoryDecoder diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt index 30bbf1681d..13fb5f8b8c 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt @@ -15,18 +15,23 @@ import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtro @Module @Suppress("unused") abstract class MedtronicModule { - @ContributesAndroidInjector abstract fun contributesMedtronicHistoryActivity(): MedtronicHistoryActivity + + @ContributesAndroidInjector + abstract fun contributesMedtronicHistoryActivity(): MedtronicHistoryActivity @ContributesAndroidInjector abstract fun contributesMedtronicFragment(): MedtronicFragment - @ContributesAndroidInjector abstract fun contributesRileyLinkMedtronicService(): RileyLinkMedtronicService + @ContributesAndroidInjector + abstract fun contributesRileyLinkMedtronicService(): RileyLinkMedtronicService - @ContributesAndroidInjector abstract fun medtronicCommunicationManagerProvider(): MedtronicCommunicationManager + @ContributesAndroidInjector + abstract fun medtronicCommunicationManagerProvider(): MedtronicCommunicationManager @ContributesAndroidInjector abstract fun medtronicUITaskProvider(): MedtronicUITask - @ContributesAndroidInjector abstract fun contributesRileyLinkStatusDeviceMedtronic(): RileyLinkStatusDeviceMedtronic + @ContributesAndroidInjector + abstract fun contributesRileyLinkStatusDeviceMedtronic(): RileyLinkStatusDeviceMedtronic @ContributesAndroidInjector abstract fun medtronicUICommProvider(): MedtronicUIComm - companion object { + @Provides fun byteUtilProvider(): ByteUtil = ByteUtil(); } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt index fade5fbed0..31609e408a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt @@ -44,7 +44,6 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { // _binding = LoopFragmentBinding.inflate(inflater, container, false) // return binding.root - val rootView = inflater.inflate(R.layout.rileylink_status_device, container, false) adapter = RileyLinkCommandListAdapter() return rootView @@ -62,12 +61,14 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { } internal class ViewHolder { + var itemTime: TextView? = null var itemSource: TextView? = null var itemDescription: TextView? = null } inner class RileyLinkCommandListAdapter : BaseAdapter() { + private val historyItemList: MutableList private val mInflator: LayoutInflater fun addItem(item: RLHistoryItem) { @@ -113,12 +114,12 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { val viewHolder: ViewHolder // General ListView optimization code. // if (view == null) { - view = mInflator.inflate(R.layout.rileylink_status_device_item, null) - viewHolder = ViewHolder() - viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) - viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) - viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) - view.tag = viewHolder + view = mInflator.inflate(R.layout.rileylink_status_device_item, null) + viewHolder = ViewHolder() + viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) + viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) + viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) + view.tag = viewHolder // } // else { // viewHolder = view.tag as ViewHolder diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index e659db4962..109ae89acd 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -1,14 +1,12 @@ 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.common.sync.PumpDbEntry 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 diff --git a/omnipod-eros/build.gradle b/omnipod-eros/build.gradle index 63fcffcef6..e530957c56 100644 --- a/omnipod-eros/build.gradle +++ b/omnipod-eros/build.gradle @@ -16,6 +16,7 @@ android { dependencies { implementation project(':core') + implementation project(':pump-common') implementation project(':omnipod-common') implementation project(':rileylink') } diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java index 65a3c739ba..a1c5ead10b 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/OmnipodErosPumpPlugin.java @@ -1,10 +1,5 @@ package info.nightscout.androidaps.plugins.pump.omnipod.eros; -import static info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants.BASAL_STEP_DURATION; -import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute; -import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes; -import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.toStringFull; - import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -34,7 +29,6 @@ import javax.inject.Singleton; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.interfaces.Profile; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.events.EventAppExit; import info.nightscout.androidaps.events.EventAppInitialized; @@ -44,9 +38,10 @@ import info.nightscout.androidaps.interfaces.ActivePlugin; import info.nightscout.androidaps.interfaces.CommandQueueProvider; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.interfaces.Profile; import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.Pump; +import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.logging.AAPSLogger; @@ -110,6 +105,11 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers; import info.nightscout.androidaps.utils.sharedPreferences.SP; import io.reactivex.disposables.CompositeDisposable; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.convertedToAbsolute; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.getPlannedRemainingMinutes; +import static info.nightscout.androidaps.extensions.PumpStateExtensionKt.toStringFull; +import static info.nightscout.androidaps.plugins.pump.omnipod.eros.driver.definition.OmnipodConstants.BASAL_STEP_DURATION; + /** * Created by andy on 23.04.18. * @@ -651,7 +651,7 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements Pump, Riley activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, true); return new PumpEnactResult(getInjector()).success(true).enacted(true).bolusDelivered(0d) - .carbsDelivered(detailedBolusInfo.carbs).comment(info.nightscout.androidaps.core.R.string.common_resultok); + .carbsDelivered(detailedBolusInfo.carbs); } } @@ -1040,17 +1040,17 @@ public class OmnipodErosPumpPlugin extends PumpPluginBase implements Pump, Riley @NonNull @Override public PumpEnactResult setExtendedBolus(double insulin, int durationInMinutes) { aapsLogger.debug(LTag.PUMP, "setExtendedBolus [OmnipodPumpPlugin] - Not implemented."); - return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.core.R.string.pump_operation_not_supported_by_pump_driver); + return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.plugins.pump.common.R.string.pump_operation_not_supported_by_pump_driver); } @NonNull @Override public PumpEnactResult cancelExtendedBolus() { aapsLogger.debug(LTag.PUMP, "cancelExtendedBolus [OmnipodPumpPlugin] - Not implemented."); - return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.core.R.string.pump_operation_not_supported_by_pump_driver); + return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.plugins.pump.common.R.string.pump_operation_not_supported_by_pump_driver); } @NonNull @Override public PumpEnactResult loadTDDs() { aapsLogger.debug(LTag.PUMP, "loadTDDs [OmnipodPumpPlugin] - Not implemented."); - return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.core.R.string.pump_operation_not_supported_by_pump_driver); + return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.plugins.pump.common.R.string.pump_operation_not_supported_by_pump_driver); } public boolean isUseRileyLinkBatteryLevel() { diff --git a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index a9a871f0b5..6d530d1e0f 100644 --- a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -6,7 +6,7 @@ import android.content.ServiceConnection import android.text.format.DateFormat import com.google.gson.GsonBuilder import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.core.R + import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.events.EventAppExit diff --git a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt index 8c467ef234..9ecd30bca7 100644 --- a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/PumpStatus.kt @@ -2,7 +2,6 @@ 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 info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntry import java.util.* /** @@ -33,7 +32,7 @@ abstract class PumpStatus(var pumpType: PumpType) { // TDD var dailyTotalUnits: Double? = null var maxDailyTotalUnits: String? = null - var units : String? = null // Constants.MGDL or Constants.MMOL + var units: String? = null // Constants.MGDL or Constants.MMOL var pumpStatusType = PumpStatusType.Running var basalsByHour: DoubleArray? = null var tempBasalStart: Date? = null diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt similarity index 91% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt index b41a6bd4c1..803d1a8902 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDeviceState.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.common.defs -import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.plugins.pump.common.R enum class PumpDeviceState(var resourceId: Int) { diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpDriverState.kt diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt similarity index 96% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt index 38fca57a8e..081c76c8db 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpHistoryEntryGroup.kt @@ -1,6 +1,6 @@ package info.nightscout.androidaps.plugins.pump.common.defs -import info.nightscout.androidaps.core.R +import info.nightscout.androidaps.plugins.pump.common.R import info.nightscout.androidaps.utils.resources.ResourceHelper import java.util.* diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpStatusType.kt diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/TempBasalPair.kt diff --git a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/di/PumpCommonModule.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/di/PumpCommonModule.kt new file mode 100644 index 0000000000..a5c85412a4 --- /dev/null +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/di/PumpCommonModule.kt @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.plugins.pump.common.di + +import dagger.Module +import dagger.Provides +import info.nightscout.androidaps.interfaces.PumpSync +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Singleton + +@Module +@Suppress("unused") +class PumpCommonModule { + + @Provides + @Singleton + fun providesPumpSyncStorage( + pumpSync: PumpSync, + sp: SP, + aapsLogger: AAPSLogger + ): PumpSyncStorage { + return PumpSyncStorage(pumpSync, sp, aapsLogger) + } + +} \ No newline at end of file diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ByteUtil.java diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ProfileUtil.kt diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/StringUtil.java diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java rename to pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/ThreadUtil.java diff --git a/pump-common/src/main/res/values/strings.xml b/pump-common/src/main/res/values/strings.xml index 0d2c4cc409..cdbe2ba8bf 100644 --- a/pump-common/src/main/res/values/strings.xml +++ b/pump-common/src/main/res/values/strings.xml @@ -1,4 +1,32 @@ + + Operation not supported by pump and/or driver. + Operation not YET supported by pump. + OK + + + Never contacted + Waking up + Error with communication + Timeout on communication + Pump unreachable + Invalid configuration + Active + Sleeping + + + Basals + Configurations + Notifications + Statistics + Unknowns + All + Boluses + Prime + Alarms + Glucose + + \ No newline at end of file diff --git a/rileylink/build.gradle b/rileylink/build.gradle index 1cae2aa0f9..96f2bfa148 100644 --- a/rileylink/build.gradle +++ b/rileylink/build.gradle @@ -16,4 +16,5 @@ android { dependencies { implementation project(':core') + implementation project(':pump-common') } diff --git a/rileylink/src/main/AndroidManifest.xml b/rileylink/src/main/AndroidManifest.xml index 3236de84bd..79aa441d6a 100644 --- a/rileylink/src/main/AndroidManifest.xml +++ b/rileylink/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="info.nightscout.androidaps.plugins.pump.common.hw.rileylink"> @@ -8,7 +8,7 @@ - + @@ -16,7 +16,7 @@ diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEConfigActivity.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEConfigActivity.java index 3f2482c2cc..227b642d8c 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEConfigActivity.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/dialog/RileyLinkBLEConfigActivity.java @@ -35,8 +35,8 @@ import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; import info.nightscout.androidaps.interfaces.ActivePlugin; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.common.R; import info.nightscout.androidaps.plugins.pump.common.ble.BlePreCheck; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes; diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java index 2d6c93a0a9..da071355da 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkConst.java @@ -1,8 +1,6 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink; -import info.nightscout.androidaps.plugins.pump.common.R; - /** * Created by andy on 16/05/2018. */ diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java index 9d8c976363..a360c13d23 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java @@ -16,7 +16,7 @@ import info.nightscout.androidaps.events.EventRefreshOverview; 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.R; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.command.RileyLinkCommand; diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java index 663ed099e5..64d6950020 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/defs/RileyLinkEncodingType.java @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs; import java.util.HashMap; import java.util.Map; -import info.nightscout.androidaps.plugins.pump.common.R; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; import info.nightscout.androidaps.utils.resources.ResourceHelper; public enum RileyLinkEncodingType { @@ -21,11 +21,11 @@ public enum RileyLinkEncodingType { private static Map encodingTypeMap; RileyLinkEncodingType(int value) { - this.value = (byte)value; + this.value = (byte) value; } RileyLinkEncodingType(int value, Integer resourceId) { - this.value = (byte)value; + this.value = (byte) value; this.resourceId = resourceId; } @@ -33,7 +33,7 @@ public enum RileyLinkEncodingType { encodingTypeMap = new HashMap<>(); for (RileyLinkEncodingType encType : values()) { - if (encType.resourceId!=null) { + if (encType.resourceId != null) { encodingTypeMap.put(resourceHelper.gs(encType.resourceId), encType); } } diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java index 0334c8d54e..0a72d9a512 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkError.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; -import info.nightscout.androidaps.plugins.pump.common.R; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; /** * Created by andy on 14/05/2018. @@ -43,8 +43,8 @@ public enum RileyLinkError { if (this.resourceIdPod != null) { return targetDevice == RileyLinkTargetDevice.MedtronicPump ? // - this.resourceId - : this.resourceIdPod; + this.resourceId + : this.resourceIdPod; } else { return this.resourceId; } diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java index 97ce0c6ce1..3a6bee96b6 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkServiceState.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; -import info.nightscout.androidaps.plugins.pump.common.R; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; /** * Created by andy on 14/05/2018. @@ -13,21 +13,21 @@ public enum RileyLinkServiceState { // Bluetooth BluetoothInitializing(R.string.rileylink_state_bt_init), // (S) init BT (if error no BT interface -> Disabled, BT - // not enabled -> BluetoothError) + // not enabled -> BluetoothError) // BluetoothNotAvailable, // (E) BT not available, would happen only if device has no BT BluetoothError(R.string.rileylink_state_bt_error), // (E) if BT gets disabled ( -> EnableBluetooth) BluetoothReady(R.string.rileylink_state_bt_ready), // (OK) // RileyLink RileyLinkInitializing(R.string.rileylink_state_rl_init), // (S) start Gatt discovery (OK -> RileyLinkReady, Error -> - // BluetoothEnabled) ?? + // BluetoothEnabled) ?? RileyLinkError(R.string.rileylink_state_rl_error), // (E) RileyLinkReady(R.string.rileylink_state_rl_ready), // (OK) if tunning was already done we go to PumpConnectorReady // Tunning TuneUpDevice(R.string.rileylink_state_pc_tune_up), // (S) PumpConnectorError(R.string.rileylink_state_pc_error), // either TuneUp Error or pump couldn't not be contacted - // error + // error PumpConnectorReady(R.string.rileylink_state_connected), // (OK) RileyLink Ready for Pump Communication // Initializing, // get all parameters required for connection (if not possible -> Disabled, if sucessful -> @@ -58,17 +58,17 @@ public enum RileyLinkServiceState { public boolean isConnecting() { return (this == RileyLinkServiceState.BluetoothInitializing || // - // this == RileyLinkServiceState.BluetoothError || // - this == RileyLinkServiceState.BluetoothReady || // - this == RileyLinkServiceState.RileyLinkInitializing || // - this == RileyLinkReady - // this == RileyLinkServiceState.RileyLinkBLEError + // this == RileyLinkServiceState.BluetoothError || // + this == RileyLinkServiceState.BluetoothReady || // + this == RileyLinkServiceState.RileyLinkInitializing || // + this == RileyLinkReady + // this == RileyLinkServiceState.RileyLinkBLEError ); } public boolean isError() { return (this == RileyLinkServiceState.BluetoothError || // - // this == RileyLinkServiceState.PumpConnectorError || // - this == RileyLinkServiceState.RileyLinkError); + // this == RileyLinkServiceState.PumpConnectorError || // + this == RileyLinkServiceState.RileyLinkError); } } diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java index 1e560d0801..aff01e36a0 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/defs/RileyLinkTargetDevice.java @@ -1,7 +1,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs; -import info.nightscout.androidaps.plugins.pump.common.R; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; /** * Created by andy on 5/19/18. diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java index 882f7a84ca..beff5bb026 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusActivity.java @@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; @@ -10,16 +11,14 @@ import androidx.viewpager.widget.ViewPager; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.tabs.TabLayout; -import androidx.annotation.NonNull; - import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; -import info.nightscout.androidaps.plugins.pump.common.R; import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; import info.nightscout.androidaps.utils.resources.ResourceHelper; public class RileyLinkStatusActivity extends NoSplashAppCompatActivity { diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java index 3faff82981..8bc967bd9f 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusDevice.java @@ -15,14 +15,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import info.nightscout.androidaps.plugins.pump.common.R; import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.CommandValueDefinition; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType; -//import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.CommandValueDefinition; -//import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem; -//import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.CommandValueDefinitionType; -//import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil; + /** * Created by andy on 5/19/18. @@ -140,7 +137,7 @@ public class RileyLinkStatusDevice extends Fragment implements RefreshableInterf viewHolder.itemValue = view.findViewById(R.id.rileylink_device_action); view.setTag(viewHolder); } else { - viewHolder = (RileyLinkStatusDevice.ViewHolder)view.getTag(); + viewHolder = (RileyLinkStatusDevice.ViewHolder) view.getTag(); } // Z // RLHistoryItem item = historyItemList.get(i); diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneralFragment.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneralFragment.java index 2ae48e3f5a..7ab6625951 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneralFragment.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusGeneralFragment.java @@ -15,8 +15,8 @@ import javax.inject.Inject; import dagger.android.support.DaggerFragment; import info.nightscout.androidaps.interfaces.ActivePlugin; import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.plugins.pump.common.R; import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpInfo; diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistoryFragment.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistoryFragment.java index 452c99f905..7ae38c4d58 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistoryFragment.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/dialog/RileyLinkStatusHistoryFragment.java @@ -6,11 +6,10 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import androidx.annotation.NonNull; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -18,9 +17,9 @@ import java.util.List; import javax.inject.Inject; import dagger.android.support.DaggerFragment; -import info.nightscout.androidaps.plugins.pump.common.R; import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState; import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface; +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.R; 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.utils.DateUtil; From b40f8b79d1916b58c44e73529ca6c5efd62528ce Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 26 May 2021 16:04:47 +0100 Subject: [PATCH 34/39] - reverted change to remove check --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index d27743c7f9..faaa85cae6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -250,6 +250,6 @@ if (isMaster() && !gitAvailable()) { throw new GradleException('GIT system is not available. On Windows try to run Android Studio as an Administrator. Check if GIT is installed and Studio have permissions to use it') } if (isMaster() && !allCommitted()) { - //throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update') + throw new GradleException('There are uncommitted changes. Clone sources again as described in wiki and do not allow gradle update') } From 766b2b4bea6e14760e143e00e7048f6e23cc4f84 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 26 May 2021 20:16:17 +0100 Subject: [PATCH 35/39] - changes after comments --- app/build.gradle | 2 +- .../treatments/TreatmentsPlugin.java.orig | 343 ------------------ app/src/main/res/values-v21/strings.xml | 4 - app/src/main/res/values-w820dp/strings.xml | 4 - .../pump/medtronic/MedtronicPumpPlugin.kt | 17 +- .../comm/MedtronicCommunicationManager.kt | 26 -- .../comm/history/MedtronicHistoryDecoder.kt | 2 +- .../comm/history/MedtronicHistoryEntry.kt | 9 - .../medtronic/defs/MedtronicCommandType.kt | 45 +-- 9 files changed, 24 insertions(+), 428 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig delete mode 100644 app/src/main/res/values-v21/strings.xml delete mode 100644 app/src/main/res/values-w820dp/strings.xml diff --git a/app/build.gradle b/app/build.gradle index faaa85cae6..85354209ff 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,7 +111,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "2.8.2.1" + version "2.8.2.1-dev-e5" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig deleted file mode 100644 index 28b960101f..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java.orig +++ /dev/null @@ -1,343 +0,0 @@ -package info.nightscout.androidaps.plugins.treatments; - -import android.content.Context; -import android.os.Bundle; - -import com.google.firebase.analytics.FirebaseAnalytics; - -import java.util.List; -import java.util.stream.Collectors; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.ErrorHelperActivity; -import info.nightscout.androidaps.data.DetailedBolusInfo; -import info.nightscout.androidaps.database.AppRepository; -import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.db.Treatment; -import info.nightscout.androidaps.interfaces.ActivePlugin; -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.interfaces.TreatmentServiceInterface; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.interfaces.UpdateReturn; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -<<<<<<< HEAD -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; -import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; -import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; -======= ->>>>>>> dev2_dana_combo_only -import info.nightscout.androidaps.utils.DateUtil; -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; - -@Singleton -public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface { - -<<<<<<< HEAD - private final Context context; - private final AapsSchedulers aapsSchedulers; -======= ->>>>>>> dev2_dana_combo_only - private final SP sp; - private final RxBusWrapper rxBus; - private final ResourceHelper resourceHelper; - private final ProfileFunction profileFunction; - private final ActivePlugin activePlugin; - private final FabricPrivacy fabricPrivacy; - private final DateUtil dateUtil; - private final DatabaseHelperInterface databaseHelper; - private final AppRepository repository; - - private final CompositeDisposable disposable = new CompositeDisposable(); - - protected TreatmentServiceInterface service; - private final boolean useNewPumpSync = false; - - - @Inject - public TreatmentsPlugin( - HasAndroidInjector injector, - AAPSLogger aapsLogger, - RxBusWrapper rxBus, - AapsSchedulers aapsSchedulers, - ResourceHelper resourceHelper, - Context context, - SP sp, - ProfileFunction profileFunction, - ActivePlugin activePlugin, - FabricPrivacy fabricPrivacy, - DateUtil dateUtil, - DatabaseHelperInterface databaseHelper, - AppRepository repository - ) { - super(new PluginDescription() - .mainType(PluginType.TREATMENT) - .fragmentClass(TreatmentsFragment.class.getName()) - .pluginIcon(R.drawable.ic_treatments) - .pluginName(R.string.treatments) - .shortName(R.string.treatments_shortname) - .alwaysEnabled(true) - .description(R.string.description_treatments) - .setDefault(), - aapsLogger, resourceHelper, injector - ); - this.resourceHelper = resourceHelper; - this.context = context; - this.rxBus = rxBus; - this.sp = sp; - this.profileFunction = profileFunction; - this.activePlugin = activePlugin; - this.fabricPrivacy = fabricPrivacy; - this.dateUtil = dateUtil; - this.databaseHelper = databaseHelper; - this.repository = repository; - } - - @Override - protected void onStart() { - this.service = new TreatmentService(getInjector()); - super.onStart(); -// disposable.add(rxBus -// .toObservable(EventReloadProfileSwitchData.class) -// .observeOn(aapsSchedulers.getIo()) -// .subscribe(event -> initializeProfileSwitchData(range()), -// fabricPrivacy::logException -// )); - } - - @Override - protected void onStop() { - disposable.clear(); - super.onStop(); - } - - @Override - public TreatmentServiceInterface getService() { - return this.service; - } - - protected long range() { - double dia = Constants.defaultDIA; - if (profileFunction.getProfile() != null) - dia = profileFunction.getProfile().getDia(); - return (long) (60 * 60 * 1000L * (24 + dia)); - } - - /** - * Returns all Treatments after specified timestamp. Also returns invalid entries (required to - * map "Fill Cannula" entries to history (and not to add double bolus for it) - * - * @param fromTimestamp - * @return - */ - @Deprecated - @Override - public List getTreatmentsFromHistoryAfterTimestamp(long fromTimestamp) { - return repository.getBolusesIncludingInvalidFromTimeToTime(fromTimestamp, dateUtil.now(), true) - .blockingGet() - .stream() - .map(bolus -> new Treatment(getInjector(), bolus)) - .collect(Collectors.toList()); -/* - List in5minback = new ArrayList<>(); - - long time = System.currentTimeMillis(); - synchronized (treatments) { -// getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: AllTreatmentsInDb: " + new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(treatments)); - - for (Treatment t : treatments) { - if (t.date >= fromTimestamp && t.date <= time) - in5minback.add(t); - } -// getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: FilteredTreatments: AfterTime={}, Items={} " + fromTimestamp + " " + new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(in5minback)); - return in5minback; - } -*/ - } -/* - @Override - public long getLastBolusTime() { - Treatment last = getService().getLastBolus(false); - if (last == null) { - getAapsLogger().debug(LTag.DATATREATMENTS, "Last bolus time: NOTHING FOUND"); - return 0; - } else { - getAapsLogger().debug(LTag.DATATREATMENTS, "Last bolus time: " + dateUtil.dateAndTimeString(last.date)); - return last.date; - } - } - - public long getLastBolusTime(boolean excludeSMB) { - Treatment last = getService().getLastBolus(excludeSMB); - if (last == null) { - getAapsLogger().debug(LTag.DATATREATMENTS, "Last manual bolus time: NOTHING FOUND"); - return 0; - } else { - getAapsLogger().debug(LTag.DATATREATMENTS, "Last manual bolus time: " + dateUtil.dateAndTimeString(last.date)); - return last.date; - } - } - - public long getLastCarbTime() { - Treatment last = getService().getLastCarb(); - if (last == null) { - getAapsLogger().debug(LTag.DATATREATMENTS, "Last Carb time: NOTHING FOUND"); - return 0; - } else { - getAapsLogger().debug(LTag.DATATREATMENTS, "Last Carb time: " + dateUtil.dateAndTimeString(last.date)); - return last.date; - } - } - - - */ - - @Deprecated - @Override - public boolean addToHistoryExtendedBolus(ExtendedBolus extendedBolus) { - throw new IllegalStateException("Migrate to new DB"); - //log.debug("Adding new ExtentedBolus record" + extendedBolus.log()); - /* - boolean newRecordCreated = databaseHelper.createOrUpdate(extendedBolus); - if (newRecordCreated) { - if (extendedBolus.durationInMinutes == 0) { - if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses()) - nsUpload.uploadTempBasalEnd(extendedBolus.date, true, extendedBolus.pumpId); - else - nsUpload.uploadExtendedBolusEnd(extendedBolus.date, extendedBolus.pumpId); - } else if (activePlugin.getActivePump().isFakingTempsByExtendedBoluses()) - nsUpload.uploadTempBasalStartAbsolute(new TemporaryBasal(extendedBolus), extendedBolus.insulin); - else - nsUpload.uploadExtendedBolus(extendedBolus); - } - return newRecordCreated; - */ - } - - @Deprecated - @Override - public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { - if (useNewPumpSync) { - throw new IllegalStateException("Migrate to new DB"); - } else { - getAapsLogger().error("!!! addToHistoryTempBasal: Need to migrate to new DB"); - } - - //log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); - boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal); - if (newRecordCreated) { -// if (tempBasal.durationInMinutes == 0) -// nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); -// else if (tempBasal.isAbsolute) -// nsUpload.uploadTempBasalStartAbsolute(tempBasal, null); -// else -// nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); - } - return newRecordCreated; - } - - @Deprecated - public TreatmentUpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout) { - if (useNewPumpSync) { - throw new IllegalStateException("Migrate to new DB"); - } else { - getAapsLogger().error("!!! createOrUpdateMedtronic: Need to migrate to new DB"); - } - - UpdateReturn resultRecord = getService().createOrUpdateMedtronic(treatment, fromNightScout); - - return new TreatmentUpdateReturn(resultRecord.getSuccess(), resultRecord.getNewRecord()); - } - - // return true if new record is created - @Deprecated - @Override - public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) { - if (useNewPumpSync) { - throw new IllegalStateException("Migrate to new DB"); - } else { - getAapsLogger().error("!!! addToHistoryTreatment: Need to migrate to new DB"); - } - - boolean medtronicPump = activePlugin.getActivePump() instanceof MedtronicPumpPlugin; - - getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={} " + medtronicPump); - - Treatment treatment = new Treatment(); - treatment.date = detailedBolusInfo.timestamp; - treatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP; - treatment.pumpId = detailedBolusInfo.getBolusPumpId() != null ? detailedBolusInfo.getBolusPumpId() : 0; - treatment.insulin = detailedBolusInfo.insulin; - treatment.isValid = detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING; - treatment.isSMB = detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB; - if (detailedBolusInfo.carbTime == 0) - treatment.carbs = detailedBolusInfo.carbs; - treatment.mealBolus = treatment.carbs > 0; - // treatment.boluscalc = detailedBolusInfo.boluscalc != null ? detailedBolusInfo.boluscalc.toString() : null; - treatment.boluscalc = null; - UpdateReturn creatOrUpdateResult; - - getAapsLogger().debug(medtronicPump && MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::treatment={} " + treatment); - - if (!medtronicPump) - creatOrUpdateResult = getService().createOrUpdate(treatment); - else - creatOrUpdateResult = getService().createOrUpdateMedtronic(treatment, false); - - boolean newRecordCreated = creatOrUpdateResult.getNewRecord(); - //log.debug("Adding new Treatment record" + treatment.toString()); - if (detailedBolusInfo.carbTime != 0) { - - Treatment carbsTreatment = new Treatment(); - carbsTreatment.source = (detailedBolusInfo.getPumpType() == PumpType.USER) ? Source.USER : Source.PUMP; - carbsTreatment.pumpId = detailedBolusInfo.getCarbsPumpId() != null ? detailedBolusInfo.getCarbsPumpId() : 0; // but this should never happen - carbsTreatment.date = detailedBolusInfo.timestamp + detailedBolusInfo.carbTime * 60 * 1000L + 1000L; // add 1 sec to make them different records - carbsTreatment.carbs = detailedBolusInfo.carbs; - - getAapsLogger().debug(medtronicPump && MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: carbTime!=0, creating second treatment. CarbsTreatment={}" + carbsTreatment); - - if (!medtronicPump) - getService().createOrUpdate(carbsTreatment); - else - getService().createOrUpdateMedtronic(carbsTreatment, false); - //log.debug("Adding new Treatment record" + carbsTreatment); - } - - getAapsLogger().error("nsUpload.uploadTreatmentRecord(detailedBolusInfo) not possible."); -// if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) -// nsUpload.uploadTreatmentRecord(detailedBolusInfo); - - if (!allowUpdate && !creatOrUpdateResult.getSuccess()) { - getAapsLogger().error("Treatment could not be added to DB", new Exception()); - - String status = String.format(resourceHelper.gs(R.string.error_adding_treatment_message), treatment.insulin, (int) treatment.carbs, dateUtil.dateAndTimeString(treatment.date)); - - ErrorHelperActivity.Companion.runAlarm(context, status, resourceHelper.gs(R.string.error_adding_treatment_title), R.raw.error); - - Bundle bundle = new Bundle(); - bundle.putString(FirebaseAnalytics.Param.ITEM_LIST_ID, "TreatmentClash"); - bundle.putString(FirebaseAnalytics.Param.ITEM_LIST_NAME, status); - fabricPrivacy.logCustom(bundle); - } - - return newRecordCreated; - - } -} diff --git a/app/src/main/res/values-v21/strings.xml b/app/src/main/res/values-v21/strings.xml deleted file mode 100644 index adec7323c6..0000000000 --- a/app/src/main/res/values-v21/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Connection Error - \ No newline at end of file diff --git a/app/src/main/res/values-w820dp/strings.xml b/app/src/main/res/values-w820dp/strings.xml deleted file mode 100644 index adec7323c6..0000000000 --- a/app/src/main/res/values-w820dp/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Connection Error - \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index a40940bab4..aa29b8879b 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -108,7 +108,8 @@ class MedtronicPumpPlugin @Inject constructor( private var lastPumpHistoryEntry: PumpHistoryEntry? = null private val busyTimestamps: MutableList = ArrayList() private var hasTimeDateOrTimeZoneChanged = false - private val usePumpSync = false + private var isBusy = false + private val displayConnectionMessages = false override fun onStart() { aapsLogger.debug(LTag.PUMP, deviceID() + " started.") @@ -1125,7 +1126,7 @@ class MedtronicPumpPlugin @Inject constructor( } override fun executeCustomAction(customActionType: CustomActionType) { - val mcat = customActionType as MedtronicCustomActionType + val mcat = customActionType as? MedtronicCustomActionType when (mcat) { MedtronicCustomActionType.WakeUpAndTune -> { if (rileyLinkMedtronicService.verifyConfiguration()) { @@ -1144,6 +1145,10 @@ class MedtronicPumpPlugin @Inject constructor( MedtronicCustomActionType.ResetRileyLinkConfiguration -> { serviceTaskExecutor.startTask(ResetRileyLinkConfigurationTask(injector)) } + + null -> { + + } } } @@ -1165,12 +1170,4 @@ class MedtronicPumpPlugin @Inject constructor( refreshCustomActionsList() } - companion object { - - var isBusy = false - } - - init { - displayConnectionMessages = false - } } \ No newline at end of file diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index 2a9dc6bf66..602cd9102f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -444,32 +444,6 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth } } - // private fun sendAndGetResponseWithCheck(commandType: MedtronicCommandType, bodyData: ByteArray, clazz: Class): T? { - // aapsLogger.debug(LTag.PUMPCOMM, "getDataFromPump: $commandType") - // for (retries in 0 until MAX_COMMAND_TRIES) { - // try { - // val response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + DEFAULT_TIMEOUT * retries) - // val check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength) - // if (check == null) { - // val dataResponse = medtronicConverter!!.convertResponse(medtronicPumpPlugin!!.pumpDescription.pumpType, commandType, response.rawContent) as T? - // if (dataResponse != null) { - // errorResponse = null - // aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Converted response for %s is %s.", commandType.name, dataResponse)) - // return dataResponse - // } else { - // errorResponse = "Error decoding response." - // } - // } else { - // errorResponse = check - // // return null; - // } - // } catch (e: RileyLinkCommunicationException) { - // aapsLogger.warn(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "Error getting response from RileyLink (error=%s, retry=%d)", e.message, retries + 1)) - // } - // } - // return null - // } - private fun checkResponseContent(response: PumpMessage, method: String, expectedLength: Int): String? { if (!response.isValid) { val responseData = String.format("%s: Invalid response.", method) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt index 228a9ddef5..c834e92711 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryDecoder.kt @@ -62,7 +62,7 @@ abstract class MedtronicHistoryDecoder(var aapsLogge } } - protected fun addToStatistics(pumpHistoryEntry: MedtronicHistoryEntryInterface, status: RecordDecodeStatus?, opCode: Int?) { + protected fun addToStatistics(pumpHistoryEntry: MedtronicHistoryEntryInterface, status: RecordDecodeStatus, opCode: Int?) { if (!statisticsEnabled) return if (opCode != null) { if (!unknownOpCodes.containsKey(opCode)) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index 31f3fca4ef..d9baa82acc 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -67,11 +67,6 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { field = value } - // fun setLinkedObject(linkedObject: Any?) { - // linked = true - // this.linkedObject = linkedObject - // } - abstract fun generatePumpId(): Long abstract fun isEntryTypeSet(): Boolean @@ -126,10 +121,6 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { val isNoDataEntry: Boolean get() = sizes[0] == 2 && sizes[1] == 5 && sizes[2] == 0 - // fun getDecodedData(): Map? { - // return decodedData - // } - fun getDecodedDataEntry(key: String?): Any? { return if (decodedData.containsKey(key)) decodedData[key] else null } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index 77772a867f..07d69b893e 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -165,8 +165,6 @@ enum class MedtronicCommandType { } init { - RFPowerOn.maxAllowedTime = 17000 - RFPowerOn.allowedRetries = 0 RFPowerOn.recordLength = 0 RFPowerOn.minimalBufferSizeToStartReading = 1 for (medtronicCommandType in values()) { @@ -183,7 +181,8 @@ enum class MedtronicCommandType { var resourceId: Int? = null private set var allowedRetries = 2 - var maxAllowedTime = 2000 + + //var maxAllowedTime = 2000 var parameterType: MinimedCommandParameterType? = null var minimalBufferSizeToStartReading = 14 var expectedLength = 0 @@ -201,14 +200,21 @@ enum class MedtronicCommandType { } // NEW - constructor(code: Int, description: String, devices: MedtronicDeviceType?, // - parameterType: MinimedCommandParameterType?, expectedLength: Int) : this(code, description, devices, parameterType, 64, 1, expectedLength, null) { - } + // 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) { - } + // 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, @@ -222,7 +228,6 @@ enum class MedtronicCommandType { commandCode = code.toByte() commandDescription = description this.devices = devices - this.recordLength = recordLength maxRecords = max_recs this.resourceId = resourceId commandParametersCount = 0 @@ -234,26 +239,6 @@ enum class MedtronicCommandType { } } - // @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 } From 8be367e15669d38165173b0ac06d1d4674c15dde Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 26 May 2021 22:19:03 +0100 Subject: [PATCH 36/39] - refctoring MedtronicCommandType --- .../pump/medtronic/MedtronicPumpPlugin.kt | 5 +- .../medtronic/defs/MedtronicCommandType.kt | 180 ++++++------------ medtronic/src/main/res/values/strings.xml | 1 + 3 files changed, 65 insertions(+), 121 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index aa29b8879b..9f7bb11d92 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -109,7 +109,6 @@ class MedtronicPumpPlugin @Inject constructor( private val busyTimestamps: MutableList = ArrayList() private var hasTimeDateOrTimeZoneChanged = false private var isBusy = false - private val displayConnectionMessages = false override fun onStart() { aapsLogger.debug(LTag.PUMP, deviceID() + " started.") @@ -167,7 +166,9 @@ class MedtronicPumpPlugin @Inject constructor( } migrateSettings() - pumpSyncStorage.initStorage(); + pumpSyncStorage.initStorage() + + this.displayConnectionMessages = false } override fun triggerPumpConfigurationChangedEvent() { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index 07d69b893e..6594df3458 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -25,25 +25,34 @@ import java.util.* * * Author: Andy {andy@atech-software.com} */ -enum class MedtronicCommandType { +enum class MedtronicCommandType( + code: Int, + description: String, + var devices: MedtronicDeviceType = MedtronicDeviceType.All, + var parameterType: MinimedCommandParameterType = MinimedCommandParameterType.NoParameters, + var recordLength: Int = 64, + var maxRecords: Int = 1, + var expectedLength: Int = 0, + var resourceId: Int? = null, + var commandParameters: ByteArray? = null) { - InvalidCommand(0, "Invalid Command", null, null), // + InvalidCommand(code = 0, description = "Invalid Command"), // // Pump Responses (9) - CommandACK(0x06, "ACK - Acknowledge", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // - CommandNAK(0x15, "NAK - Not Acknowledged", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + CommandACK(code = 0x06, description = "ACK - Acknowledge"), // + CommandNAK(code = 0x15, description = "NAK - Not Acknowledged"), // // 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)), // + PushAck(code = 91, description = "Push ACK", parameterType = MinimedCommandParameterType.FixedParameters, commandParameters = byteArrayOf(2)), // + PushEsc(code = 91, description = "Push Esc", parameterType = MinimedCommandParameterType.FixedParameters, commandParameters = byteArrayOf(1)), // + PushButton(code = 0x5b, description = "Push Button"), // 91 + RFPowerOn(code = 93, description = "RF Power On", parameterType = MinimedCommandParameterType.FixedParameters, commandParameters = byteArrayOf(1, 10)), // + RFPowerOff(code = 93, description = "RF Power Off", parameterType = MinimedCommandParameterType.FixedParameters, commandParameters = 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), // + PumpState(code = 131, description = "Pump State"), // + ReadPumpErrorStatus(code = 117, description = "Pump Error Status"), // // 511 (InitCommand = 2, Config 7, Data = 1(+3) // DetectBolus(75, "Detect Bolus", MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray( @@ -51,24 +60,20 @@ enum class MedtronicCommandType { // 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, R.string.medtronic_cmd_desc_get_remaining_insulin), // 115 - SetBolus(0x42, "Set Bolus", MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, // - 0, R.string.medtronic_cmd_desc_set_bolus), // 66 + SetRealTimeClock(code = 0x40, description = "Set Pump Time", recordLength = 0, resourceId = R.string.medtronic_cmd_desc_set_time), // + GetRealTimeClock(112, description = "Get Pump Time", recordLength = 7, resourceId = R.string.medtronic_cmd_desc_get_time), // 0x70 + GetBatteryStatus(code = 0x72, description = "Get Battery Status", recordLength = 0, resourceId = R.string.medtronic_cmd_desc_get_battery_status), // + GetRemainingInsulin(code = 0x73, description = "Read Remaining Insulin", + recordLength = 2, resourceId = R.string.medtronic_cmd_desc_get_remaining_insulin), // 115 + SetBolus(code = 0x42, description = "Set Bolus", recordLength = 0, resourceId = 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 + ReadTemporaryBasal(code = 0x98, description = "Read Temporary Basal", devices = MedtronicDeviceType.Medtronic_512andHigher, // + recordLength = 5, resourceId = R.string.medtronic_cmd_desc_get_tbr), // 152 + SetTemporaryBasal(code = 76, description = "Set Temporay Basal", devices = MedtronicDeviceType.Medtronic_512andHigher, // + recordLength = 0, resourceId = R.string.medtronic_cmd_desc_set_tbr), // 512 Config + PumpModel(code = 141, description = "Pump Model", devices = MedtronicDeviceType.Medtronic_512andHigher, // + recordLength = 5, resourceId = R.string.medtronic_cmd_desc_get_model), // 0x8D // BGTargets_512(140, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512_712, // MinimedCommandParameterType.NoParameters), // @@ -76,49 +81,44 @@ enum class MedtronicCommandType { // 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), // + Settings_512(code = 145, description = "Configuration", devices = MedtronicDeviceType.Medtronic_512_712, + expectedLength = 18, resourceId = 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 + GetHistoryData(code = 128, description = "Get History", devices = MedtronicDeviceType.Medtronic_512andHigher, + parameterType = MinimedCommandParameterType.SubCommands, recordLength = 1024, maxRecords = 16, + expectedLength = 1024, resourceId = R.string.medtronic_cmd_desc_get_history), // 0x80 + GetBasalProfileSTD(code = 146, description = "Get Profile Standard", devices = MedtronicDeviceType.Medtronic_512andHigher, // + maxRecords = 3, expectedLength = 192, resourceId = R.string.medtronic_cmd_desc_get_basal_profile), // 146 + GetBasalProfileA(code = 147, description = "Get Profile A", devices = MedtronicDeviceType.Medtronic_512andHigher, // + maxRecords = 3, expectedLength = 192, resourceId = R.string.medtronic_cmd_desc_get_basal_profile), + GetBasalProfileB(code = 148, description = "Get Profile B", devices = MedtronicDeviceType.Medtronic_512andHigher, // + maxRecords = 3, expectedLength = 192, resourceId = R.string.medtronic_cmd_desc_get_basal_profile), // 148 + SetBasalProfileSTD(code = 0x6f, description = "Set Profile Standard", devices = MedtronicDeviceType.Medtronic_512andHigher, // + maxRecords = 3, expectedLength = 192, resourceId = R.string.medtronic_cmd_desc_set_basal_profile), // 111 + SetBasalProfileA(code = 0x30, description = "Set Profile A", devices = MedtronicDeviceType.Medtronic_512andHigher, // + maxRecords = 3, expectedLength = 192, resourceId = R.string.medtronic_cmd_desc_set_basal_profile), // 48 + SetBasalProfileB(code = 0x31, description = "Set Profile B", devices = MedtronicDeviceType.Medtronic_512andHigher, // + maxRecords = 3, expectedLength = 192, resourceId = 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), // + PumpStatus(code = 206, description = "Pump Status", devices = MedtronicDeviceType.Medtronic_515andHigher), // PumpConfiguration + Settings(code = 192, description = "Configuration", devices = MedtronicDeviceType.Medtronic_515andHigher, + maxRecords = 1, expectedLength = 21, resourceId = 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), // + SensorSettings_522(code = 153, description = "Sensor Configuration", devices = MedtronicDeviceType.Medtronic_522andHigher), // + GlucoseHistory(code = 154, description = "Glucose History", devices = MedtronicDeviceType.Medtronic_522andHigher, + MinimedCommandParameterType.SubCommands, recordLength = 1024, maxRecords = 32, expectedLength = 0), // // 523 - SensorSettings(207, "Sensor Configuration", MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), // + SensorSettings(code = 207, description = "Sensor Configuration", devices = MedtronicDeviceType.Medtronic_523andHigher), // // 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, @@ -127,20 +127,12 @@ enum class MedtronicCommandType { // READ_CURRENT_CBG_PAGE : 0xCD // }; // Fake Commands - CancelTBR; + CancelTBR(code = 250, description = "Cancel TBR", resourceId = R.string.medtronic_cmd_desc_cancel_tbr); companion object { var mapByCode: MutableMap = HashMap() - // private fun getDeviceTypesArray(vararg types: MedtronicDeviceType): HashMap { - // val hashMap = HashMap() - // for (type in types) { - // hashMap[type] = null - // } - // return hashMap - // } - fun getByCode(code: Byte): MedtronicCommandType? { return if (mapByCode.containsKey(code)) { mapByCode[code] @@ -165,8 +157,6 @@ enum class MedtronicCommandType { } init { - RFPowerOn.recordLength = 0 - RFPowerOn.minimalBufferSizeToStartReading = 1 for (medtronicCommandType in values()) { mapByCode[medtronicCommandType.commandCode] = medtronicCommandType } @@ -174,66 +164,18 @@ enum class MedtronicCommandType { } var commandCode: Byte = 0 - var commandDescription = "" - var commandParameters: ByteArray? = null + var commandDescription = description var commandParametersCount = 0 - var maxRecords = 1 - var resourceId: Int? = null - private set var allowedRetries = 2 //var maxAllowedTime = 2000 - var parameterType: MinimedCommandParameterType? = null + //var parameterType: MinimedCommandParameterType? = parameterType 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) { - 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) { + init { commandCode = code.toByte() - commandDescription = description - this.devices = devices - maxRecords = max_recs - this.resourceId = resourceId - commandParametersCount = 0 + this.commandParametersCount = if (commandParameters != null) commandParameters!!.size else 0 allowedRetries = 2 - this.parameterType = parameterType - this.expectedLength = expectedLength if (this.parameterType == MinimedCommandParameterType.SubCommands) { minimalBufferSizeToStartReading = 200 } diff --git a/medtronic/src/main/res/values/strings.xml b/medtronic/src/main/res/values/strings.xml index f2831199cb..56d216e9cf 100644 --- a/medtronic/src/main/res/values/strings.xml +++ b/medtronic/src/main/res/values/strings.xml @@ -104,6 +104,7 @@ Set Basal Profile Get Temporary Basal Set Temporary Basal + Cancel Temporary Basal Set Bolus Get Remaining Insulin From 16785838e93ac41434f6254ad8858da8733a404e Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 26 May 2021 22:28:22 +0100 Subject: [PATCH 37/39] - small change --- .../plugins/pump/medtronic/defs/MedtronicCommandType.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt index 6594df3458..35c8ec3a7b 100755 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/defs/MedtronicCommandType.kt @@ -169,12 +169,11 @@ enum class MedtronicCommandType( var allowedRetries = 2 //var maxAllowedTime = 2000 - //var parameterType: MinimedCommandParameterType? = parameterType var minimalBufferSizeToStartReading = 14 init { commandCode = code.toByte() - this.commandParametersCount = if (commandParameters != null) commandParameters!!.size else 0 + this.commandParametersCount = commandParameters?.size ?: 0 allowedRetries = 2 if (this.parameterType == MinimedCommandParameterType.SubCommands) { minimalBufferSizeToStartReading = 200 From 3c7b5fd2b39c06639267463f53f284182a7baecc Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Thu, 27 May 2021 18:10:35 +0100 Subject: [PATCH 38/39] - fixed test - add runtest for linux - some refactorings --- .../pump/medtronic/MedtronicFragment.kt | 12 +- .../comm/MedtronicCommunicationManager.kt | 4 +- .../comm/history/cgms/CGMSHistoryEntry.kt | 5 +- .../dialog/RileyLinkStatusDeviceMedtronic.kt | 58 +++-- .../MedtronicPumpHistoryDecoderUTest.java | 234 ------------------ .../pump/MedtronicPumpHistoryDecoderUTest.kt | 217 ++++++++++++++++ .../plugins/pump/common/PumpPluginAbstract.kt | 2 +- runtests.sh | 2 + 8 files changed, 271 insertions(+), 263 deletions(-) delete mode 100644 medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.java create mode 100644 medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.kt create mode 100755 runtests.sh diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt index 1a2a139189..95274476fa 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicFragment.kt @@ -98,7 +98,7 @@ class MedtronicFragment : DaggerFragment() { binding.pumpStatusIcon.text = "{fa-bed}" binding.history.setOnClickListener { - if (medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() == true) { + if (medtronicPumpPlugin.rileyLinkService.verifyConfiguration() == true) { startActivity(Intent(context, MedtronicHistoryActivity::class.java)) } else { displayNotConfiguredDialog() @@ -106,7 +106,7 @@ class MedtronicFragment : DaggerFragment() { } binding.refresh.setOnClickListener { - if (medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() != true) { + if (medtronicPumpPlugin.rileyLinkService.verifyConfiguration() != true) { displayNotConfiguredDialog() } else { binding.refresh.isEnabled = false @@ -120,7 +120,7 @@ class MedtronicFragment : DaggerFragment() { } binding.stats.setOnClickListener { - if (medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() == true) { + if (medtronicPumpPlugin.rileyLinkService.verifyConfiguration() == true) { startActivity(Intent(context, RileyLinkStatusActivity::class.java)) } else { displayNotConfiguredDialog() @@ -160,7 +160,7 @@ class MedtronicFragment : DaggerFragment() { .observeOn(aapsSchedulers.main) .subscribe({ aapsLogger.debug(LTag.PUMP, "EventMedtronicPumpConfigurationChanged triggered") - medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() + medtronicPumpPlugin.rileyLinkService.verifyConfiguration() updateGUI() }, fabricPrivacy::logException) disposable += rxBus @@ -192,7 +192,7 @@ class MedtronicFragment : DaggerFragment() { @Synchronized private fun setDeviceStatus() { val resourceId = rileyLinkServiceData.rileyLinkServiceState.resourceId - val rileyLinkError = medtronicPumpPlugin.rileyLinkService?.error + val rileyLinkError = medtronicPumpPlugin.rileyLinkService.error binding.rlStatus.text = when { rileyLinkServiceData.rileyLinkServiceState == RileyLinkServiceState.NotStarted -> resourceHelper.gs(resourceId) @@ -338,7 +338,7 @@ class MedtronicFragment : DaggerFragment() { binding.reservoir.text = resourceHelper.gs(R.string.reservoirvalue, medtronicPumpStatus.reservoirRemainingUnits, medtronicPumpStatus.reservoirFullUnits) warnColors.setColorInverse(binding.reservoir, medtronicPumpStatus.reservoirRemainingUnits, 50.0, 20.0) - medtronicPumpPlugin.rileyLinkService?.verifyConfiguration() + medtronicPumpPlugin.rileyLinkService.verifyConfiguration() binding.errors.text = medtronicPumpStatus.errorInfo val showRileyLinkBatteryLevel: Boolean = rileyLinkServiceData.showBatteryLevel diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt index 602cd9102f..4f918f1ceb 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.kt @@ -451,7 +451,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth return responseData } val contents = response.rawContent - return if (contents != null) { + return if (contents.size > 0) { if (contents.size >= expectedLength) { aapsLogger.debug(LTag.PUMPCOMM, String.format(Locale.ENGLISH, "%s: Content: %s", method, ByteUtil.shortHexString(contents))) null @@ -463,7 +463,7 @@ class MedtronicCommunicationManager // This empty constructor must be kept, oth responseData } } else { - val responseData = String.format("%s: Cannot return data. Null response.", method) + val responseData = String.format("%s: Cannot return data. Zero length response.", method) aapsLogger.warn(LTag.PUMPCOMM, responseData) responseData } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt index 494b8eb683..26e9cea75a 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/cgms/CGMSHistoryEntry.kt @@ -31,10 +31,7 @@ class CGMSHistoryEntry : MedtronicHistoryEntry() { get() = entryType.name override fun generatePumpId(): Long { - return if (entryType == null) - atechDateTime * 1000L - else - entryType.code + atechDateTime * 1000L + return entryType.code + atechDateTime * 1000L } override fun isEntryTypeSet(): Boolean { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt index 31609e408a..3874683f09 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt @@ -60,7 +60,16 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { // adapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); } - internal class ViewHolder { + internal class ViewHolder constructor(view: View, + var itemTime: TextView? = null, + var itemSource: TextView? = null, + var itemDescription: TextView? = null) { + + init { + itemTime = view.findViewById(R.id.rileylink_history_time) + itemSource = view.findViewById(R.id.rileylink_history_source) + itemDescription = view.findViewById(R.id.rileylink_history_description) + } var itemTime: TextView? = null var itemSource: TextView? = null @@ -109,26 +118,43 @@ class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { return i.toLong() } - override fun getView(i: Int, viewIn: View, viewGroup: ViewGroup): View { - var view = viewIn + override fun getView(i: Int, viewIn: View?, viewGroup: ViewGroup): View { + var rowView: View? val viewHolder: ViewHolder - // General ListView optimization code. -// if (view == null) { - view = mInflator.inflate(R.layout.rileylink_status_device_item, null) - viewHolder = ViewHolder() - viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) - viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) - viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) - view.tag = viewHolder - // } - // else { - // viewHolder = view.tag as ViewHolder - // } + + if (view == null) { + rowView = layoutInflater.inflate(R.layout.rileylink_status_device_item, viewGroup, false) + + viewHolder = ViewHolder(rowView) + rowView.tag = viewHolder + + } else { + rowView = view + viewHolder = rowView.tag as ViewHolder + } + val item = historyItemList[i] viewHolder.itemTime!!.text = StringUtil.toDateTimeString(dateUtil, item.dateTime) viewHolder.itemSource!!.text = "Riley Link" // for now viewHolder.itemDescription!!.text = item.getDescription(resourceHelper) - return view + + return rowView!! + + // // old + // if (view == null) { + // view = mInflator.inflate(R.layout.rileylink_status_device_item, viewGroup, false) + // } + // viewHolder = ViewHolder() + // viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) + // viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) + // viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) + // view.tag = viewHolder + // + // val item = historyItemList[i] + // viewHolder.itemTime!!.text = StringUtil.toDateTimeString(dateUtil, item.dateTime) + // viewHolder.itemSource!!.text = "Riley Link" // for now + // viewHolder.itemDescription!!.text = item.getDescription(resourceHelper) + // return view } init { diff --git a/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.java b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.java deleted file mode 100644 index 14a4c2926a..0000000000 --- a/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.java +++ /dev/null @@ -1,234 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.List; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.interfaces.ActivePlugin; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.AAPSLoggerTest; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RawHistoryPage; -import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType; -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 info.nightscout.androidaps.utils.rx.TestAapsSchedulers; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - -/** - * Created by andy on 11/1/18. - */ -@RunWith(PowerMockRunner.class) -public class MedtronicPumpHistoryDecoderUTest { - - @Mock HasAndroidInjector injector; - AAPSLogger aapsLogger = new AAPSLoggerTest(); - RxBusWrapper rxBusWrapper = new RxBusWrapper(new TestAapsSchedulers()); - @Mock ResourceHelper resourceHelper; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) ActivePlugin activePlugin; - @Mock RileyLinkUtil rileyLinkUtil; - @Mock SP sp; - MedtronicPumpStatus medtronicPumpStatus; - MedtronicUtil medtronicUtil; - MedtronicPumpHistoryDecoder decoder; - - - @Before - public void setup() { - medtronicPumpStatus = new MedtronicPumpStatus(resourceHelper, sp, rxBusWrapper, rileyLinkUtil); - medtronicUtil = new MedtronicUtil(aapsLogger, rxBusWrapper, rileyLinkUtil, medtronicPumpStatus); - decoder = new MedtronicPumpHistoryDecoder(aapsLogger, medtronicUtil); - } - - - -/* - - // @Test - public void decodeRecord() throws Exception { - - byte[] data = new byte[] { 0x07, 0x00, 0x00, 0x05, (byte)0xFA, (byte)0xBF, 0x12 }; - - PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(0x07); - - PumpHistoryEntry phe = new PumpHistoryEntry(); - phe.setEntryType(entryType); - phe.setData(ByteUtil.getListFromByteArray(data), false); - - decoder.decodeRecord(phe); - - System.out.println("Record: " + phe); - - } - - - // @Test - public void decodeLowAmount() { - byte[] data = new byte[] { 52, -12, 22, -81, 46, 3, 19 }; - - PumpHistoryEntryGroup.doNotTranslate = true; - PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(52); - - PumpHistoryEntry phe = new PumpHistoryEntry(); - phe.setEntryType(entryType); - phe.setData(ByteUtil.getListFromByteArray(data), false); - - decoder.decodeRecord(phe); - - System.out.println("Record: " + phe); - System.out.println("Record: " + phe.getDisplayableValue()); - - } - - - // @Test - public void decodeDailyTotals522() { - // PumpHistoryRecord [type=DailyTotals522 [109, 0x6D], DT: 01.11.2018 00:00:00, length=1,2,41(44), data={Raw - // Data=0x6D 0xA1 0x92 0x05 0x0C 0x00 0xE8 0x00 0x00 0x00 0x00 0x04 0x0A 0x04 0x0A 0x64 0x00 0x00 0x00 0x00 0x00 - // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0C 0x00 0xE8 0x00 0x00 - // 0x00}] - byte[] data4443 = new byte[] { - 0x6D, (byte)0xA1, (byte)0x92, 0x05, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0A, 0x04, 0x0A, - 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00 }; - - byte[] data = new byte[] { - 0x6D, (byte)0xA2, (byte)0x92, 0x05, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x02, - (byte)0xD4, 0x5B, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x64, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00 }; - - // basal 18.1, bolus 1.7 manual = 1.7 - // All (bg low hi, number Bgs, Sen Lo/Hi, Sens Cal/Data, Basal, Bolus, Carbs, Fodd, Corr, Manual=1.7, food/corr, - // Food+corr, manual bolus=1 - testRecord(data); - - } - - - // @Test - public void decodeDailyTotals515() { - - byte[] data = ByteUtil - .createByteArrayFromHexString("0x6C 0x17 0x93 0x06 0x08 0x00 0x2B 0x00 0x00 0x00 0x00 0x04 0x24 0x03 0x7C 0x54 0x00 0xA8 0x10 0x00 0x00 0x00 0xA8 0x10" - + " 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xA8 0x64 0x03 0x00 0x00"); - - // 0x6C 0x17 0x93 0x06 0x08 0x00 0x2B 0x00 0x00 0x00 0x00 0x04 0x24 0x03 0x7C 0x54 0x00 0xA8 0x10 0x00 0x00 0x00 - // 0xA8 0x10 - // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xA8 0x64 0x03 0x00 0x00 - - // Delivery Stats: BG AVG: Bg Low/Hi=none,Number BGs=0 - // Delivery Stats: INSULIN: Basal 22.30, Bolus=4.20, Catbs = 0g - // Delivery Stats: BOLUS: Food=0.00, Corr=0.00, Manual=4.20 - // Delivery Stats: NUM BOLUS: Food/Corr=0,Food+Corr=0, Manual=3 - - testRecord(data); - - } - - - // @Test - public void decodeDailyTotals523() { - - byte[] data = new byte[] { - 0x6E, (byte)0xB1, (byte)0x92, 0x05, 0x00, (byte)0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, (byte)0x9A, 0x00, - 0x50, 0x34, 0x00, 0x4A, 0x30, 0x00, 0x0B, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x80, (byte)0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }; - - // Carbs=11, total=3.850,basal=2.000, bolus=1.850, basal 52%, blus=48%, Manual=0.95, #manual=5, - // Food only=0.9, #Food Only=1,Corr Only =0, #Corr only=0,Food+Corr=0 - - // 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 - - testRecord(data); - - } - - - private void testRecord(byte[] data) { - // byte[] data = new byte[] { 0x07, 0x00, 0x00, 0x05, (byte)0xFA, (byte)0xBF, 0x12 }; - - PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(data[0]); - - PumpHistoryEntry phe = new PumpHistoryEntry(); - phe.setEntryType(entryType); - phe.setData(ByteUtil.getListFromByteArray(data), false); - - System.out.println("EntryType: " + entryType); - - decoder.decodeRecord(phe); - - System.out.println("Record: " + phe); - - } -*/ - - - @Test - public void historyProblem_148_amunhateb() throws Exception { - List pumpHistoryEntries = readAndParseHistoryPage("5A 0F 20 F4 0C 03 15 19 11 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 32 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1A 11 00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 32 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 33 01 12 12 00 25 DE 2D 43 15 01 50 50 00 26 EA 2D 43 15 01 4B 4B 00 2C C9 34 43 15 62 00 2F CB 17 03 15 01 33 33 00 16 DE 37 43 15 07 00 00 07 FE 23 95 6D 23 95 0A 08 00 2B 00 00 00 00 07 FE 03 8E 2C 04 70 38 00 00 04 70 38 00 00 00 00 00 00 04 70 64 06 00 00 00 06 08 00 2B 00 00 00 2C A0 2F E3 01 04 15 33 00 2F E7 04 44 15 00 16 03 2F E7 04 44 15 33 28 3B C2 06 44 15 00 16 01 3B C2 06 44 15 08 08 17 DB 0B 44 15 00 26 00 06 26 00 0C 26 00 12 28 00 18 26 00 1E 26 00 24 24 00 2A 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 18 17 DB 0B 44 15 00 26 00 02 26 00 04 26 00 06 24 00 08 24 00 0A 24 00 0C 26 00 0E 26 00 10 26 00 12 28 00 14 28 00 16 28 00 18 26 00 1A 26 00 1C 26 00 1E 26 00 20 26 00 22 26 00 24 24 00 26 24 00 28 24 00 2A 26 00 2C 26 00 2E 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 45 45 00 28 E9 2B 44 15 19 00 00 C1 0D 04 15 1A 00 15 C3 0D 04 15 1A 01 33 C3 0D 04 15 01 28 28 00 07 CC 2E 44 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 2D", - MedtronicDeviceType.Medtronic_522_722); - - Assert.assertEquals(20, pumpHistoryEntries.size()); - } - - - @Test - public void historyProblem_423_duzy78() throws Exception { - List pumpHistoryEntries = readAndParseHistoryPage("16 00 08 D0 0E 51 15 33 60 0A D0 0E 51 15 00 16 01 0A D0 0E 51 15 33 00 07 DF 0E 51 15 00 16 00 07 DF 0E 51 15 33 6C 09 DF 0E 51 15 00 16 01 09 DF 0E 51 15 33 00 25 ED 0E 51 15 00 16 00 25 ED 0E 51 15 33 2C 27 ED 0E 51 15 00 16 01 27 ED 0E 51 15 33 00 07 F4 0E 51 15 00 16 00 07 F4 0E 51 15 33 00 09 F4 0E 51 15 00 16 01 09 F4 0E 51 15 33 2C 25 D5 0F 51 15 00 16 01 25 D5 0F 51 15 01 3C 3C 00 30 D5 4F 51 15 33 2C 25 F7 0F 51 15 00 16 01 25 F7 0F 51 15 33 00 07 C6 10 51 15 00 16 00 07 C6 10 51 15 33 30 09 C6 10 51 15 00 16 01 09 C6 10 51 15 33 30 25 E8 10 51 15 00 16 01 25 E8 10 51 15 33 30 24 CF 11 51 15 00 16 01 24 CF 11 51 15 33 00 23 E4 11 51 15 00 16 00 23 E4 11 51 15 33 3C 25 E4 11 51 15 00 16 01 25 E4 11 51 15 33 00 23 E8 11 51 15 00 16 00 23 E8 11 51 15 33 4A 25 E8 11 51 15 00 16 01 25 E8 11 51 15 33 00 19 EE 11 51 15 00 16 00 19 EE 11 51 15 33 30 1B EE 11 51 15 00 16 01 1B EE 11 51 15 33 00 23 F2 11 51 15 00 16 00 23 F2 11 51 15 33 3E 25 F2 11 51 15 00 16 01 25 F2 11 51 15 33 00 24 C0 12 51 15 00 16 00 24 C0 12 51 15 33 5E 25 C0 12 51 15 00 16 01 25 C0 12 51 15 33 00 23 CF 12 51 15 00 16 00 23 CF 12 51 15 33 64 25 CF 12 51 15 00 16 01 25 CF 12 51 15 33 00 23 D9 12 51 15 00 16 00 23 D9 12 51 15 33 6A 25 D9 12 51 15 00 16 01 25 D9 12 51 15 33 00 23 E9 12 51 15 00 16 00 23 E9 12 51 15 33 30 25 E9 12 51 15 00 16 01 25 E9 12 51 15 01 16 16 00 10 C2 53 51 15 33 30 24 CF 13 51 15 00 16 01 24 CF 13 51 15 33 30 04 EE 13 51 15 00 16 01 04 EE 13 51 15 01 14 14 00 3B F0 53 51 15 33 00 22 C0 14 51 15 00 16 00 22 C0 14 51 15 33 22 24 C0 14 51 15 00 16 01 24 C0 14 51 15 33 22 03 DF 14 51 15 00 16 01 03 DF 14 51 15 1E 00 37 E1 14 11 15 1F 00 01 EE 14 11 15 33 22 03 C6 15 51 15 00 16 01 03 C6 15 51 15 33 00 20 D9 15 51 15 00 16 00 20 D9 15 51 15 33 34 22 D9 15 51 15 00 16 01 22 D9 15 51 15 39 14 0E DF 35 71 15 83 92 40 01 0B 0B 00 37 E0 55 51 15 33 00 21 E3 15 51 15 00 16 00 21 E3 15 51 15 33 22 22 E3 15 51 15 00 16 01 22 E3 15 51 15 33 00 21 E8 15 51 15 00 16 00 21 E8 15 51 15 33 30 23 E8 15 51 15 00 16 01 23 E8 15 51 15 33 00 20 ED 15 51 15 00 16 00 20 ED 15 51 15 33 22 22 ED 15 51 15 00 16 01 22 ED 15 51 15 33 00 03 F8 15 51 15 00 16 00 03 F8 15 51 15 33 32 05 F8 15 51 15 00 16 01 05 F8 15 51 15 33 00 01 CB 16 51 15 00 16 00 01 CB 16 51 15 33 20 03 CB 16 51 15 00 16 01 03 CB 16 51 15 33 2A 20 ED 16 51 15 00 16 01 20 ED 16 51 15 33 00 02 F8 16 51 15 00 16 00 02 F8 16 51 15 33 2C 04 F8 16 51 15 00 16 01 04 F8 16 51 15 33 00 1F CA 17 51 15 00 16 00 1F CA 17 51 15 33 34 21 CA 17 51 15 00 16 01 21 CA 17 51 15 33 00 1F D4 17 51 15 00 16 00 1F D4 17 51 15 33 38 21 D4 17 51 15 00 16 01 21 D4 17 51 15 33 00 15 EE 17 51 15 00 16 00 15 EE 17 51 15 33 42 17 EE 17 51 15 00 16 01 17 EE 17 51 15 07 00 00 08 0A 31 95 6C 31 95 05 00 A1 A1 A1 01 00 00 08 0A 04 8E 39 03 7C 2B 00 00 03 7C 2B 00 00 00 00 00 00 03 7C 64 07 00 00 00 07 33 00 05 C1 00 52 15 00 16 00 05 C1 00 52 15 33 50 07 C1 00 52 15 00 16 01 07 C1 00 52 15 33 00 01 CB 00 52 15 00 16 00 01 CB 00 52 15 33 26 03 CB 00 52 15 00 16 01 03 CB 00 52 15 33 00 1E DE 00 52 15 00 00 00 8F 0E", - MedtronicDeviceType.Medtronic_515_715); - - Assert.assertEquals(131, pumpHistoryEntries.size()); - } - - @Test - public void historyProblem_476_OpossumGit() throws Exception { - List pumpHistoryEntries = readAndParseHistoryPage("08 07 50 05 0D 4D 15 00 18 00 08 14 00 0E 10 00 14 08 00 1E 12 00 26 16 00 2B 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 18 50 05 0D 4D 15 00 18 00 02 18 00 04 18 00 06 18 00 08 14 00 0A 14 00 0C 14 00 0E 10 00 10 10 00 12 10 00 14 08 00 16 08 00 18 08 00 1A 08 00 1C 08 00 1E 14 00 20 14 00 22 14 00 24 14 00 26 16 00 28 16 00 2A 16 00 2C 1C 00 2E 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 04 04 00 44 09 4D 4D 15 33 06 57 15 0D 4D 15 00 16 01 57 15 0D 4D 15 33 00 77 15 0D 4D 15 00 16 00 77 15 0D 4D 15 33 00 5D 16 0D 4D 15 00 16 04 5D 16 0D 4D 15 33 00 61 1A 0D 4D 15 00 16 00 61 1A 0D 4D 15 5D 00 5E 31 0D 0D 15 1A 00 6E 31 0D 0D 15 06 03 04 D2 6E 31 6D 0D 15 0C 03 11 40 00 01 05 64 01 13 40 00 01 05 17 00 0A 41 00 01 05 18 00 40 39 15 0D 15 21 00 53 04 16 0D 15 03 00 00 00 58 57 09 36 0D 15 5D 01 78 0A 16 0D 15 64 01 78 0A 16 8D 15 2C 68 78 0A 16 8D 15 24 3C 78 0A 16 8D 15 63 02 78 0A 16 8D 15 1B 12 78 0A 16 8D 15 65 61 78 0A 16 8D 15 61 00 78 0A 16 8D 15 32 0E 78 0A 16 8D 15 66 00 78 0A 16 8D 15 3C 01 78 0A 16 8D 15 3D 88 32 93 00 00 00 3E 00 00 00 00 00 00 26 01 78 0A 16 8D 15 27 01 B2 08 00 00 00 28 00 00 00 00 00 00 60 00 78 0A 16 4D 15 23 00 78 0A 16 8D 15 5E 01 78 0A 16 8D 15 2D 01 78 0A 16 8D 15 5A 0F 78 0A 16 8D 15 49 13 00 07 12 0A 1E 0B 2A 0A 00 00 00 00 00 00 00 00 00 23 08 27 2C 23 00 00 00 00 00 00 00 00 00 00 00 32 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 13 00 07 12 0A 1E 0B 2A 0A 00 00 00 00 00 00 00 00 00 23 08 27 2C 23 00 00 00 00 00 00 00 00 00 00 00 32 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 62 00 78 0A 16 8D 15 5F 51 78 0A 16 8D 15 4F 00 78 0A 16 8D 15 40 01 00 6F 1C 16 1E 00 3C 14 00 1E 3C 1F 15 70 40 01 00 6F 1C 16 1E 00 3C 14 00 1E 3C 1F 15 70 08 18 78 0A 16 8D 15 00 18 00 02 18 00 04 18 00 06 18 00 08 14 00 0A 14 00 0C 14 00 0E 10 00 10 10 00 12 10 00 14 08 00 16 08 00 18 08 00 1A 08 00 1C 08 00 1E 14 00 20 14 00 22 14 00 24 14 00 26 16 00 28 16 00 2A 16 00 2C 1C 00 2E 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D6 06", - MedtronicDeviceType.Medtronic_522_722); - - Assert.assertEquals(41, pumpHistoryEntries.size()); - } - - - private List readAndParseHistoryPage(String historyPageString, MedtronicDeviceType medtronicDeviceType) throws Exception { - byte[] historyPageData = ByteUtil.createByteArrayFromString(historyPageString); - - aapsLogger.debug("History Page Length:" + historyPageData.length); - - medtronicUtil.setMedtronicPumpModel(medtronicDeviceType); - - RawHistoryPage historyPage = new RawHistoryPage(aapsLogger); - historyPage.appendData(historyPageData); - - List pumpHistoryEntries = decoder.processPageAndCreateRecords(historyPage); - - displayHistoryRecords(pumpHistoryEntries); - - return pumpHistoryEntries; - } - - - private void displayHistoryRecords(List pumpHistoryEntries) { - aapsLogger.debug("PumpHistoryEntries: " + pumpHistoryEntries.size()); - - for (PumpHistoryEntry pumpHistoryEntry : pumpHistoryEntries) { - aapsLogger.debug(pumpHistoryEntry.toString()); - } - } - - -} diff --git a/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.kt b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.kt new file mode 100644 index 0000000000..d94c453c95 --- /dev/null +++ b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/MedtronicPumpHistoryDecoderUTest.kt @@ -0,0 +1,217 @@ +package info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.interfaces.ActivePlugin +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.AAPSLoggerTest +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil +import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.RawHistoryPage +import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceType +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 info.nightscout.androidaps.utils.rx.TestAapsSchedulers +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Answers +import org.mockito.Mock +import org.powermock.modules.junit4.PowerMockRunner + +/** + * Created by andy on 11/1/18. + */ +@RunWith(PowerMockRunner::class) +class MedtronicPumpHistoryDecoderUTest { + + @Mock + var injector: HasAndroidInjector? = null + var aapsLogger: AAPSLogger = AAPSLoggerTest() + var rxBusWrapper = RxBusWrapper(TestAapsSchedulers()) + + @Mock + var resourceHelper: ResourceHelper? = null + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + var activePlugin: ActivePlugin? = null + + @Mock + var rileyLinkUtil: RileyLinkUtil? = null + + @Mock + var sp: SP? = null + var medtronicPumpStatus: MedtronicPumpStatus? = null + var medtronicUtil: MedtronicUtil? = null + var decoder: MedtronicPumpHistoryDecoder? = null + @Before fun setup() { + medtronicPumpStatus = MedtronicPumpStatus(resourceHelper!!, sp!!, rxBusWrapper, rileyLinkUtil!!) + medtronicUtil = MedtronicUtil(aapsLogger, rxBusWrapper, rileyLinkUtil!!, medtronicPumpStatus!!) + decoder = MedtronicPumpHistoryDecoder(aapsLogger, medtronicUtil!!, ByteUtil()) + } + + /* + + // @Test + public void decodeRecord() throws Exception { + + byte[] data = new byte[] { 0x07, 0x00, 0x00, 0x05, (byte)0xFA, (byte)0xBF, 0x12 }; + + PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(0x07); + + PumpHistoryEntry phe = new PumpHistoryEntry(); + phe.setEntryType(entryType); + phe.setData(ByteUtil.getListFromByteArray(data), false); + + decoder.decodeRecord(phe); + + System.out.println("Record: " + phe); + + } + + + // @Test + public void decodeLowAmount() { + byte[] data = new byte[] { 52, -12, 22, -81, 46, 3, 19 }; + + PumpHistoryEntryGroup.doNotTranslate = true; + PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(52); + + PumpHistoryEntry phe = new PumpHistoryEntry(); + phe.setEntryType(entryType); + phe.setData(ByteUtil.getListFromByteArray(data), false); + + decoder.decodeRecord(phe); + + System.out.println("Record: " + phe); + System.out.println("Record: " + phe.getDisplayableValue()); + + } + + + // @Test + public void decodeDailyTotals522() { + // PumpHistoryRecord [type=DailyTotals522 [109, 0x6D], DT: 01.11.2018 00:00:00, length=1,2,41(44), data={Raw + // Data=0x6D 0xA1 0x92 0x05 0x0C 0x00 0xE8 0x00 0x00 0x00 0x00 0x04 0x0A 0x04 0x0A 0x64 0x00 0x00 0x00 0x00 0x00 + // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0C 0x00 0xE8 0x00 0x00 + // 0x00}] + byte[] data4443 = new byte[] { + 0x6D, (byte)0xA1, (byte)0x92, 0x05, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0A, 0x04, 0x0A, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00 }; + + byte[] data = new byte[] { + 0x6D, (byte)0xA2, (byte)0x92, 0x05, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x02, + (byte)0xD4, 0x5B, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0x44, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x64, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, (byte)0xE8, 0x00, 0x00, 0x00 }; + + // basal 18.1, bolus 1.7 manual = 1.7 + // All (bg low hi, number Bgs, Sen Lo/Hi, Sens Cal/Data, Basal, Bolus, Carbs, Fodd, Corr, Manual=1.7, food/corr, + // Food+corr, manual bolus=1 + testRecord(data); + + } + + + // @Test + public void decodeDailyTotals515() { + + byte[] data = ByteUtil + .createByteArrayFromHexString("0x6C 0x17 0x93 0x06 0x08 0x00 0x2B 0x00 0x00 0x00 0x00 0x04 0x24 0x03 0x7C 0x54 0x00 0xA8 0x10 0x00 0x00 0x00 0xA8 0x10" + + " 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xA8 0x64 0x03 0x00 0x00"); + + // 0x6C 0x17 0x93 0x06 0x08 0x00 0x2B 0x00 0x00 0x00 0x00 0x04 0x24 0x03 0x7C 0x54 0x00 0xA8 0x10 0x00 0x00 0x00 + // 0xA8 0x10 + // 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xA8 0x64 0x03 0x00 0x00 + + // Delivery Stats: BG AVG: Bg Low/Hi=none,Number BGs=0 + // Delivery Stats: INSULIN: Basal 22.30, Bolus=4.20, Catbs = 0g + // Delivery Stats: BOLUS: Food=0.00, Corr=0.00, Manual=4.20 + // Delivery Stats: NUM BOLUS: Food/Corr=0,Food+Corr=0, Manual=3 + + testRecord(data); + + } + + + // @Test + public void decodeDailyTotals523() { + + byte[] data = new byte[] { + 0x6E, (byte)0xB1, (byte)0x92, 0x05, 0x00, (byte)0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, (byte)0x9A, 0x00, + 0x50, 0x34, 0x00, 0x4A, 0x30, 0x00, 0x0B, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x80, (byte)0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + // Carbs=11, total=3.850,basal=2.000, bolus=1.850, basal 52%, blus=48%, Manual=0.95, #manual=5, + // Food only=0.9, #Food Only=1,Corr Only =0, #Corr only=0,Food+Corr=0 + + // 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 + + testRecord(data); + + } + + + private void testRecord(byte[] data) { + // byte[] data = new byte[] { 0x07, 0x00, 0x00, 0x05, (byte)0xFA, (byte)0xBF, 0x12 }; + + PumpHistoryEntryType entryType = PumpHistoryEntryType.getByCode(data[0]); + + PumpHistoryEntry phe = new PumpHistoryEntry(); + phe.setEntryType(entryType); + phe.setData(ByteUtil.getListFromByteArray(data), false); + + System.out.println("EntryType: " + entryType); + + decoder.decodeRecord(phe); + + System.out.println("Record: " + phe); + + } +*/ + @Test @Throws(Exception::class) fun historyProblem_148_amunhateb() { + val pumpHistoryEntries = readAndParseHistoryPage("5A 0F 20 F4 0C 03 15 19 11 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 32 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1A 11 00 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 32 50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 33 01 12 12 00 25 DE 2D 43 15 01 50 50 00 26 EA 2D 43 15 01 4B 4B 00 2C C9 34 43 15 62 00 2F CB 17 03 15 01 33 33 00 16 DE 37 43 15 07 00 00 07 FE 23 95 6D 23 95 0A 08 00 2B 00 00 00 00 07 FE 03 8E 2C 04 70 38 00 00 04 70 38 00 00 00 00 00 00 04 70 64 06 00 00 00 06 08 00 2B 00 00 00 2C A0 2F E3 01 04 15 33 00 2F E7 04 44 15 00 16 03 2F E7 04 44 15 33 28 3B C2 06 44 15 00 16 01 3B C2 06 44 15 08 08 17 DB 0B 44 15 00 26 00 06 26 00 0C 26 00 12 28 00 18 26 00 1E 26 00 24 24 00 2A 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 18 17 DB 0B 44 15 00 26 00 02 26 00 04 26 00 06 24 00 08 24 00 0A 24 00 0C 26 00 0E 26 00 10 26 00 12 28 00 14 28 00 16 28 00 18 26 00 1A 26 00 1C 26 00 1E 26 00 20 26 00 22 26 00 24 24 00 26 24 00 28 24 00 2A 26 00 2C 26 00 2E 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 45 45 00 28 E9 2B 44 15 19 00 00 C1 0D 04 15 1A 00 15 C3 0D 04 15 1A 01 33 C3 0D 04 15 01 28 28 00 07 CC 2E 44 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 2D", + MedtronicDeviceType.Medtronic_522_722) + Assert.assertEquals(20, pumpHistoryEntries.size.toLong()) + } + + @Test @Throws(Exception::class) fun historyProblem_423_duzy78() { + val pumpHistoryEntries = readAndParseHistoryPage("16 00 08 D0 0E 51 15 33 60 0A D0 0E 51 15 00 16 01 0A D0 0E 51 15 33 00 07 DF 0E 51 15 00 16 00 07 DF 0E 51 15 33 6C 09 DF 0E 51 15 00 16 01 09 DF 0E 51 15 33 00 25 ED 0E 51 15 00 16 00 25 ED 0E 51 15 33 2C 27 ED 0E 51 15 00 16 01 27 ED 0E 51 15 33 00 07 F4 0E 51 15 00 16 00 07 F4 0E 51 15 33 00 09 F4 0E 51 15 00 16 01 09 F4 0E 51 15 33 2C 25 D5 0F 51 15 00 16 01 25 D5 0F 51 15 01 3C 3C 00 30 D5 4F 51 15 33 2C 25 F7 0F 51 15 00 16 01 25 F7 0F 51 15 33 00 07 C6 10 51 15 00 16 00 07 C6 10 51 15 33 30 09 C6 10 51 15 00 16 01 09 C6 10 51 15 33 30 25 E8 10 51 15 00 16 01 25 E8 10 51 15 33 30 24 CF 11 51 15 00 16 01 24 CF 11 51 15 33 00 23 E4 11 51 15 00 16 00 23 E4 11 51 15 33 3C 25 E4 11 51 15 00 16 01 25 E4 11 51 15 33 00 23 E8 11 51 15 00 16 00 23 E8 11 51 15 33 4A 25 E8 11 51 15 00 16 01 25 E8 11 51 15 33 00 19 EE 11 51 15 00 16 00 19 EE 11 51 15 33 30 1B EE 11 51 15 00 16 01 1B EE 11 51 15 33 00 23 F2 11 51 15 00 16 00 23 F2 11 51 15 33 3E 25 F2 11 51 15 00 16 01 25 F2 11 51 15 33 00 24 C0 12 51 15 00 16 00 24 C0 12 51 15 33 5E 25 C0 12 51 15 00 16 01 25 C0 12 51 15 33 00 23 CF 12 51 15 00 16 00 23 CF 12 51 15 33 64 25 CF 12 51 15 00 16 01 25 CF 12 51 15 33 00 23 D9 12 51 15 00 16 00 23 D9 12 51 15 33 6A 25 D9 12 51 15 00 16 01 25 D9 12 51 15 33 00 23 E9 12 51 15 00 16 00 23 E9 12 51 15 33 30 25 E9 12 51 15 00 16 01 25 E9 12 51 15 01 16 16 00 10 C2 53 51 15 33 30 24 CF 13 51 15 00 16 01 24 CF 13 51 15 33 30 04 EE 13 51 15 00 16 01 04 EE 13 51 15 01 14 14 00 3B F0 53 51 15 33 00 22 C0 14 51 15 00 16 00 22 C0 14 51 15 33 22 24 C0 14 51 15 00 16 01 24 C0 14 51 15 33 22 03 DF 14 51 15 00 16 01 03 DF 14 51 15 1E 00 37 E1 14 11 15 1F 00 01 EE 14 11 15 33 22 03 C6 15 51 15 00 16 01 03 C6 15 51 15 33 00 20 D9 15 51 15 00 16 00 20 D9 15 51 15 33 34 22 D9 15 51 15 00 16 01 22 D9 15 51 15 39 14 0E DF 35 71 15 83 92 40 01 0B 0B 00 37 E0 55 51 15 33 00 21 E3 15 51 15 00 16 00 21 E3 15 51 15 33 22 22 E3 15 51 15 00 16 01 22 E3 15 51 15 33 00 21 E8 15 51 15 00 16 00 21 E8 15 51 15 33 30 23 E8 15 51 15 00 16 01 23 E8 15 51 15 33 00 20 ED 15 51 15 00 16 00 20 ED 15 51 15 33 22 22 ED 15 51 15 00 16 01 22 ED 15 51 15 33 00 03 F8 15 51 15 00 16 00 03 F8 15 51 15 33 32 05 F8 15 51 15 00 16 01 05 F8 15 51 15 33 00 01 CB 16 51 15 00 16 00 01 CB 16 51 15 33 20 03 CB 16 51 15 00 16 01 03 CB 16 51 15 33 2A 20 ED 16 51 15 00 16 01 20 ED 16 51 15 33 00 02 F8 16 51 15 00 16 00 02 F8 16 51 15 33 2C 04 F8 16 51 15 00 16 01 04 F8 16 51 15 33 00 1F CA 17 51 15 00 16 00 1F CA 17 51 15 33 34 21 CA 17 51 15 00 16 01 21 CA 17 51 15 33 00 1F D4 17 51 15 00 16 00 1F D4 17 51 15 33 38 21 D4 17 51 15 00 16 01 21 D4 17 51 15 33 00 15 EE 17 51 15 00 16 00 15 EE 17 51 15 33 42 17 EE 17 51 15 00 16 01 17 EE 17 51 15 07 00 00 08 0A 31 95 6C 31 95 05 00 A1 A1 A1 01 00 00 08 0A 04 8E 39 03 7C 2B 00 00 03 7C 2B 00 00 00 00 00 00 03 7C 64 07 00 00 00 07 33 00 05 C1 00 52 15 00 16 00 05 C1 00 52 15 33 50 07 C1 00 52 15 00 16 01 07 C1 00 52 15 33 00 01 CB 00 52 15 00 16 00 01 CB 00 52 15 33 26 03 CB 00 52 15 00 16 01 03 CB 00 52 15 33 00 1E DE 00 52 15 00 00 00 8F 0E", + MedtronicDeviceType.Medtronic_515_715) + Assert.assertEquals(131, pumpHistoryEntries.size.toLong()) + } + + @Test @Throws(Exception::class) fun historyProblem_476_OpossumGit() { + val pumpHistoryEntries = readAndParseHistoryPage("08 07 50 05 0D 4D 15 00 18 00 08 14 00 0E 10 00 14 08 00 1E 12 00 26 16 00 2B 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 18 50 05 0D 4D 15 00 18 00 02 18 00 04 18 00 06 18 00 08 14 00 0A 14 00 0C 14 00 0E 10 00 10 10 00 12 10 00 14 08 00 16 08 00 18 08 00 1A 08 00 1C 08 00 1E 14 00 20 14 00 22 14 00 24 14 00 26 16 00 28 16 00 2A 16 00 2C 1C 00 2E 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 04 04 00 44 09 4D 4D 15 33 06 57 15 0D 4D 15 00 16 01 57 15 0D 4D 15 33 00 77 15 0D 4D 15 00 16 00 77 15 0D 4D 15 33 00 5D 16 0D 4D 15 00 16 04 5D 16 0D 4D 15 33 00 61 1A 0D 4D 15 00 16 00 61 1A 0D 4D 15 5D 00 5E 31 0D 0D 15 1A 00 6E 31 0D 0D 15 06 03 04 D2 6E 31 6D 0D 15 0C 03 11 40 00 01 05 64 01 13 40 00 01 05 17 00 0A 41 00 01 05 18 00 40 39 15 0D 15 21 00 53 04 16 0D 15 03 00 00 00 58 57 09 36 0D 15 5D 01 78 0A 16 0D 15 64 01 78 0A 16 8D 15 2C 68 78 0A 16 8D 15 24 3C 78 0A 16 8D 15 63 02 78 0A 16 8D 15 1B 12 78 0A 16 8D 15 65 61 78 0A 16 8D 15 61 00 78 0A 16 8D 15 32 0E 78 0A 16 8D 15 66 00 78 0A 16 8D 15 3C 01 78 0A 16 8D 15 3D 88 32 93 00 00 00 3E 00 00 00 00 00 00 26 01 78 0A 16 8D 15 27 01 B2 08 00 00 00 28 00 00 00 00 00 00 60 00 78 0A 16 4D 15 23 00 78 0A 16 8D 15 5E 01 78 0A 16 8D 15 2D 01 78 0A 16 8D 15 5A 0F 78 0A 16 8D 15 49 13 00 07 12 0A 1E 0B 2A 0A 00 00 00 00 00 00 00 00 00 23 08 27 2C 23 00 00 00 00 00 00 00 00 00 00 00 32 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 13 00 07 12 0A 1E 0B 2A 0A 00 00 00 00 00 00 00 00 00 23 08 27 2C 23 00 00 00 00 00 00 00 00 00 00 00 32 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 62 00 78 0A 16 8D 15 5F 51 78 0A 16 8D 15 4F 00 78 0A 16 8D 15 40 01 00 6F 1C 16 1E 00 3C 14 00 1E 3C 1F 15 70 40 01 00 6F 1C 16 1E 00 3C 14 00 1E 3C 1F 15 70 08 18 78 0A 16 8D 15 00 18 00 02 18 00 04 18 00 06 18 00 08 14 00 0A 14 00 0C 14 00 0E 10 00 10 10 00 12 10 00 14 08 00 16 08 00 18 08 00 1A 08 00 1C 08 00 1E 14 00 20 14 00 22 14 00 24 14 00 26 16 00 28 16 00 2A 16 00 2C 1C 00 2E 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D6 06", + MedtronicDeviceType.Medtronic_522_722) + Assert.assertEquals(41, pumpHistoryEntries.size.toLong()) + } + + @Throws(Exception::class) + private fun readAndParseHistoryPage(historyPageString: String, medtronicDeviceType: MedtronicDeviceType): List { + val historyPageData = ByteUtil.createByteArrayFromString(historyPageString) + aapsLogger.debug("History Page Length:" + historyPageData.size) + medtronicUtil!!.medtronicPumpModel = medtronicDeviceType + medtronicUtil!!.isModelSet = true + val historyPage = RawHistoryPage(aapsLogger) + historyPage.appendData(historyPageData) + val pumpHistoryEntries: List = decoder!!.processPageAndCreateRecords(historyPage) + displayHistoryRecords(pumpHistoryEntries) + return pumpHistoryEntries + } + + private fun displayHistoryRecords(pumpHistoryEntries: List) { + aapsLogger.debug("PumpHistoryEntries: " + pumpHistoryEntries.size) + for (pumpHistoryEntry in pumpHistoryEntries) { + aapsLogger.debug(pumpHistoryEntry.toString()) + } + } +} \ No newline at end of file diff --git a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index 6d530d1e0f..814e950f03 100644 --- a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -88,7 +88,7 @@ abstract class PumpPluginAbstract protected constructor( disposable.add(rxBus .toObservable(EventAppExit::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ event: EventAppExit? -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } + .subscribe({ _ -> context.unbindService(serviceConnection!!) }) { throwable: Throwable? -> fabricPrivacy.logException(throwable!!) } ) onStartCustomActions() } diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 0000000000..288ac90dda --- /dev/null +++ b/runtests.sh @@ -0,0 +1,2 @@ +#!/bin/zsh +./gradlew -Pcoverage -PfirebaseDisable testFullDebugUnitTest From 841c49b770bb07773d528186b13b893f414202ea Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Fri, 28 May 2021 11:34:41 +0200 Subject: [PATCH 39/39] fix medtronic merge --- .../pump/medtronic/di/MedtronicModule.kt | 3 - .../dialog/RileyLinkStatusDeviceMedtronic.kt | 165 ------------------ 2 files changed, 168 deletions(-) delete mode 100644 medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt index 13fb5f8b8c..0be7f1ba73 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/di/MedtronicModule.kt @@ -9,7 +9,6 @@ import info.nightscout.androidaps.plugins.pump.medtronic.comm.MedtronicCommunica import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUIComm import info.nightscout.androidaps.plugins.pump.medtronic.comm.ui.MedtronicUITask import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity -import info.nightscout.androidaps.plugins.pump.medtronic.dialog.RileyLinkStatusDeviceMedtronic import info.nightscout.androidaps.plugins.pump.medtronic.service.RileyLinkMedtronicService @Module @@ -26,8 +25,6 @@ abstract class MedtronicModule { @ContributesAndroidInjector abstract fun medtronicCommunicationManagerProvider(): MedtronicCommunicationManager @ContributesAndroidInjector abstract fun medtronicUITaskProvider(): MedtronicUITask - @ContributesAndroidInjector - abstract fun contributesRileyLinkStatusDeviceMedtronic(): RileyLinkStatusDeviceMedtronic @ContributesAndroidInjector abstract fun medtronicUICommProvider(): MedtronicUIComm companion object { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt deleted file mode 100644 index 3874683f09..0000000000 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/dialog/RileyLinkStatusDeviceMedtronic.kt +++ /dev/null @@ -1,165 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.medtronic.dialog - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter -import android.widget.ListView -import android.widget.TextView -import dagger.android.support.DaggerFragment -import info.nightscout.androidaps.plugins.pump.common.dialog.RefreshableInterface -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem -import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil -import info.nightscout.androidaps.plugins.pump.medtronic.R -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.resources.ResourceHelper -import io.reactivex.disposables.CompositeDisposable -import java.util.* -import javax.inject.Inject - -/** - * Created by andy on 5/19/18. - * NOTE: This class is not used yet, so it has no Bindings - * - * This is for 3rd tab, called Medtronic (in RileyLink stats), that should work similarly as the one in Loop. - * - * - * Showing currently selected RL, speed of RL, ability to issue simple commands (getModel, tuneUp, gerProfile) - */ -// TODO needs to be implemented -class RileyLinkStatusDeviceMedtronic : DaggerFragment(), RefreshableInterface { - - @Inject lateinit var resourceHelper: ResourceHelper - @Inject lateinit var dateUtil: DateUtil - - var listView: ListView? = null - var adapter: RileyLinkCommandListAdapter? = null - - private var disposable: CompositeDisposable = CompositeDisposable() - //private var _binding: RileyLinkStatusDeviceBinding? = null - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - - // _binding = LoopFragmentBinding.inflate(inflater, container, false) - // return binding.root - - val rootView = inflater.inflate(R.layout.rileylink_status_device, container, false) - adapter = RileyLinkCommandListAdapter() - return rootView - } - - override fun onStart() { - super.onStart() - //listView = activity!!.findViewById(R.id.rileylink_history_list) - //listView.setAdapter(adapter) - refreshData() - } - - override fun refreshData() { - // adapter.addItemsAndClean(RileyLinkUtil.getRileyLinkHistory()); - } - - internal class ViewHolder constructor(view: View, - var itemTime: TextView? = null, - var itemSource: TextView? = null, - var itemDescription: TextView? = null) { - - init { - itemTime = view.findViewById(R.id.rileylink_history_time) - itemSource = view.findViewById(R.id.rileylink_history_source) - itemDescription = view.findViewById(R.id.rileylink_history_description) - } - - var itemTime: TextView? = null - var itemSource: TextView? = null - var itemDescription: TextView? = null - } - - inner class RileyLinkCommandListAdapter : BaseAdapter() { - - private val historyItemList: MutableList - private val mInflator: LayoutInflater - fun addItem(item: RLHistoryItem) { - if (!historyItemList.contains(item)) { - historyItemList.add(item) - notifyDataSetChanged() - } - } - - fun getHistoryItem(position: Int): RLHistoryItem { - return historyItemList[position] - } - - fun addItemsAndClean(items: List) { - historyItemList.clear() - for (item in items) { - if (!historyItemList.contains(item)) { - historyItemList.add(item) - } - } - notifyDataSetChanged() - } - - fun clear() { - historyItemList.clear() - notifyDataSetChanged() - } - - override fun getCount(): Int { - return historyItemList.size - } - - override fun getItem(i: Int): Any { - return historyItemList[i] - } - - override fun getItemId(i: Int): Long { - return i.toLong() - } - - override fun getView(i: Int, viewIn: View?, viewGroup: ViewGroup): View { - var rowView: View? - val viewHolder: ViewHolder - - if (view == null) { - rowView = layoutInflater.inflate(R.layout.rileylink_status_device_item, viewGroup, false) - - viewHolder = ViewHolder(rowView) - rowView.tag = viewHolder - - } else { - rowView = view - viewHolder = rowView.tag as ViewHolder - } - - val item = historyItemList[i] - viewHolder.itemTime!!.text = StringUtil.toDateTimeString(dateUtil, item.dateTime) - viewHolder.itemSource!!.text = "Riley Link" // for now - viewHolder.itemDescription!!.text = item.getDescription(resourceHelper) - - return rowView!! - - // // old - // if (view == null) { - // view = mInflator.inflate(R.layout.rileylink_status_device_item, viewGroup, false) - // } - // viewHolder = ViewHolder() - // viewHolder.itemTime = view.findViewById(R.id.rileylink_history_time) - // viewHolder.itemSource = view.findViewById(R.id.rileylink_history_source) - // viewHolder.itemDescription = view.findViewById(R.id.rileylink_history_description) - // view.tag = viewHolder - // - // val item = historyItemList[i] - // viewHolder.itemTime!!.text = StringUtil.toDateTimeString(dateUtil, item.dateTime) - // viewHolder.itemSource!!.text = "Riley Link" // for now - // viewHolder.itemDescription!!.text = item.getDescription(resourceHelper) - // return view - } - - init { - historyItemList = ArrayList() - mInflator = this@RileyLinkStatusDeviceMedtronic.layoutInflater - } - } -} \ No newline at end of file