- more kotlinize, MedtronicHistoryActivity not yet working
This commit is contained in:
parent
a202178426
commit
6b7efdcb95
16 changed files with 2016 additions and 2615 deletions
|
@ -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() + '"'
|
||||
|
|
|
@ -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<Long, PumpDbEntry> 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<Long, PumpDbEntry> = 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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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)
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -599,6 +599,44 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
|
|||
}
|
||||
|
||||
|
||||
private <T> T sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData, Class<T> 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()) {
|
||||
|
|
|
@ -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<BasalProfileEntry>? = 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<Double?>): String {
|
||||
fun getProfilesByHourToString(data: Array<Double>): String {
|
||||
val stringBuilder = StringBuilder()
|
||||
for (value in data) {
|
||||
stringBuilder.append(String.format("%.3f", value))
|
||||
|
|
|
@ -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<PumpHistoryEntry> filteredHistoryList = new ArrayList<>();
|
||||
|
||||
RecyclerViewAdapter recyclerViewAdapter;
|
||||
boolean manualChange = false;
|
||||
|
||||
List<TypeList> typeListFull;
|
||||
|
||||
|
||||
private void filterHistory(PumpHistoryEntryGroup group) {
|
||||
|
||||
this.filteredHistoryList.clear();
|
||||
|
||||
List<PumpHistoryEntry> 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<TypeList> 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<TypeList> getTypeList(List<PumpHistoryEntryGroup> list) {
|
||||
|
||||
ArrayList<TypeList> 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<RecyclerViewAdapter.HistoryViewHolder> {
|
||||
|
||||
List<PumpHistoryEntry> historyList;
|
||||
|
||||
|
||||
RecyclerViewAdapter(List<PumpHistoryEntry> historyList) {
|
||||
this.historyList = historyList;
|
||||
}
|
||||
|
||||
|
||||
public void setHistoryList(List<PumpHistoryEntry> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<PumpHistoryEntry> = ArrayList()
|
||||
var manualChange = false
|
||||
var typeListFull: List<TypeList>? = null
|
||||
|
||||
private var _binding: MedtronicHistoryActivityBinding? = null
|
||||
|
||||
//@Inject
|
||||
//var fragmentInjector: DispatchingAndroidInjector<Fragment>? = 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<PumpHistoryEntry> = 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<PumpHistoryEntryGroup>?): List<TypeList> {
|
||||
val typeList = ArrayList<TypeList>()
|
||||
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<PumpHistoryEntry>) : RecyclerView.Adapter<RecyclerViewAdapter.HistoryViewHolder>() {
|
||||
|
||||
|
||||
fun setHistoryListInternal(historyList: List<PumpHistoryEntry>) {
|
||||
// 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
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
* <p>
|
||||
* This is for 3rd tab, called Medtronic (in RileyLink stats), that should work similarly as the one in Loop.
|
||||
* <p>
|
||||
* 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<RLHistoryItem> 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<RLHistoryItem> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<RLHistoryItem>
|
||||
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<RLHistoryItem>) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -33,6 +33,7 @@ enum class PumpHistoryEntryGroup(val resourceId: Int) {
|
|||
|
||||
companion object {
|
||||
private var translatedList: MutableList<PumpHistoryEntryGroup>? = 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<PumpHistoryEntryGroup>? {
|
||||
@JvmStatic
|
||||
fun getTranslatedList(resourceHelper: ResourceHelper): List<PumpHistoryEntryGroup>? {
|
||||
if (translatedList == null) doTranslation(resourceHelper)
|
||||
return translatedList
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
Loading…
Reference in a new issue