- kotlin changes almost done, 1 file left
This commit is contained in:
parent
6b7efdcb95
commit
08a5c50037
|
@ -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<ProfileSwitch> 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
|
||||
|
|
|
@ -12,6 +12,9 @@ android {
|
|||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* <p>
|
||||
* 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<PumpMessage> {
|
||||
|
||||
@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<List<Byte>> 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<Byte> 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<PumpHistoryEntry> 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> 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()) {
|
||||
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<String, PumpSettingDTO> getPumpSettings() {
|
||||
|
||||
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.getSettings(medtronicUtil
|
||||
.getMedtronicPumpModel()));
|
||||
|
||||
return responseObject == null ? null : (Map<String, PumpSettingDTO>) 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<List<Byte>> 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;
|
||||
|
||||
}
|
||||
}
|
|
@ -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<PumpMessage?>() {
|
||||
|
||||
@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<List<Byte>>): 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 <T> sendAndGetResponseWithCheck(commandType: MedtronicCommandType, bodyData: ByteArray, clazz: Class<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(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<String, PumpSettingDTO>? {
|
||||
val responseObject = sendAndGetResponseWithCheck(getSettings(medtronicUtil.medtronicPumpModel))
|
||||
return if (responseObject == null) null else responseObject as Map<String, PumpSettingDTO>?
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ abstract class MedtronicHistoryDecoder<T : MedtronicHistoryEntry?> : MedtronicHi
|
|||
}
|
||||
}
|
||||
|
||||
fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): List<T?>? {
|
||||
fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage): List<T> {
|
||||
return processPageAndCreateRecords(rawHistoryPage, false)
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ abstract class MedtronicHistoryDecoder<T : MedtronicHistoryEntry?> : MedtronicHi
|
|||
private fun processPageAndCreateRecords(rawHistoryPage: RawHistoryPage, partial: Boolean): List<T> {
|
||||
val dataClear = checkPage(rawHistoryPage, partial)
|
||||
val records: List<T> = createRecords(dataClear)
|
||||
for (record in records!!) {
|
||||
for (record in records) {
|
||||
decodeRecord(record)
|
||||
}
|
||||
runPostDecodeTasks()
|
||||
|
|
|
@ -25,14 +25,14 @@ class MedtronicCGMSHistoryDecoder : MedtronicHistoryDecoder<CGMSHistoryEntry>()
|
|||
|
||||
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<CGMSHistoryEntry>()
|
|||
}
|
||||
|
||||
override fun postProcess() {}
|
||||
|
||||
override fun createRecords(dataClearInput: List<Byte>): List<CGMSHistoryEntry> {
|
||||
val dataClear = reverseList(dataClearInput, Byte::class.java)
|
||||
prepareStatistics()
|
||||
|
|
|
@ -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<Byte>, 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]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 + //
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<BasalProfileEntry>
|
||||
get() {
|
||||
val entries: MutableList<BasalProfileEntry> = 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<BasalProfileEntry> {
|
||||
val entries: MutableList<BasalProfileEntry> = 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<Double> {
|
||||
var entriesCopy: List<BasalProfileEntry>? = 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
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ class MedtronicHistoryActivity : DaggerActivity() {
|
|||
var manualChange = false
|
||||
var typeListFull: List<TypeList>? = null
|
||||
|
||||
private var _binding: MedtronicHistoryActivityBinding? = 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 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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue