- integration started

- states visible
- command framework added
- we get currect profile and compare it with AAPS profile
- setProfile command is disabled, if pumps profile is different we get warning
- bolus is enabled and working
- get remaining reservoir level
This commit is contained in:
Andy Rozman 2018-06-16 18:13:29 +01:00
parent 9bae53e53a
commit 47427ec68e
50 changed files with 1926 additions and 515 deletions

View file

@ -169,7 +169,10 @@
<service
android:name=".plugins.Overview.notifications.DismissNotificationService"
android:exported="false" />
<service android:name=".plugins.PumpMedtronic.service.RileyLinkMedtronicService" />
<service
android:name=".plugins.PumpMedtronic.service.RileyLinkMedtronicService"
android:enabled="true"
android:exported="true" />
<meta-data
android:name="io.fabric.ApiKey"

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.PumpCommon;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.support.annotation.Nullable;
import com.squareup.otto.Subscribe;
@ -16,9 +15,9 @@ import java.util.Date;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
@ -26,13 +25,14 @@ import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpCommon.driver.PumpDriverInterface;
import info.nightscout.androidaps.plugins.PumpCommon.utils.PumpUtil;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
@ -47,7 +47,6 @@ import info.nightscout.utils.DecimalFormatter;
public abstract class PumpPluginAbstract extends PluginBase implements PumpInterface, ConstraintsInterface {
private static final Logger LOG = LoggerFactory.getLogger(PumpPluginAbstract.class);
//protected boolean pumpServiceRunning = false;
protected PumpDescription pumpDescription = new PumpDescription();
protected PumpStatus pumpStatusData;
@ -59,22 +58,29 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
protected ServiceConnection serviceConnection = null;
protected PumpPluginAbstract(PumpDriverInterface pumpDriverInterface, //
String internalName, //
String fragmentClassName, //
int pluginName, //
int pluginShortName, //
PumpType pumpType) {
this(pumpDriverInterface, //
internalName, //
new PluginDescription() //
.mainType(PluginType.PUMP) //
.fragmentClass(fragmentClassName) //
.pluginName(pluginName) //
.shortName(pluginShortName), //
pumpType //
);
}
protected static final PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult()
.success(false).enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump));
protected static final PumpEnactResult OPERATION_NOT_YET_SUPPORTED = new PumpEnactResult()
.success(false).enacted(false).comment(MainApp.gs(R.string.pump_operation_not_yet_supported_by_pump));
// protected PumpPluginAbstract(PumpDriverInterface pumpDriverInterface, //
// String internalName, //
// String fragmentClassName, //
// int pluginName, //
// int pluginShortName, //
// PumpType pumpType) {
// this(pumpDriverInterface, //
// internalName, //
// new PluginDescription() //
// .mainType(PluginType.PUMP) //
// .fragmentClass(fragmentClassName) //
// .pluginName(pluginName) //
// .shortName(pluginShortName), //
// pumpType //
// );
// }
protected PumpPluginAbstract(PumpDriverInterface pumpDriverInterface, //
@ -84,13 +90,23 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
) {
super(pluginDescription);
LOG.error("After super called.");
this.pumpDriver = pumpDriverInterface;
this.internalName = internalName;
initPumpStatusData();
LOG.error("Before Init Pump Statis Data called.");
PumpUtil.setPumpDescription(getPumpDescription(), pumpType);
initPumpStatusData();
LOG.error("Before set description");
LOG.error("Before pumpDriver");
this.pumpDriver.initDriver(this.pumpStatus, this.pumpDescription);
}
@ -213,9 +229,9 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
} // base basal rate, not temp basal
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
return pumpDriver.deliverTreatment(detailedBolusInfo);
}
// public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
// return pumpDriver.deliverTreatment(detailedBolusInfo);
// }
public void stopBolusDelivering() {
@ -247,7 +263,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public PumpEnactResult cancelExtendedBolus() {
return pumpDriver.cancelExtendedBolus();
LOG.warn("deviceID [PumpPluginAbstract] - Not implemented.");
return OPERATION_NOT_YET_SUPPORTED;
}
// Status to be passed to NS
@ -259,7 +276,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public String deviceID() {
return pumpDriver.deviceID();
LOG.warn("deviceID [PumpPluginAbstract] - Not implemented.");
return "FakeDevice";
}
// Pump capabilities
@ -273,7 +291,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public boolean isFakingTempsByExtendedBoluses() {
return pumpDriver.isInitialized();
LOG.warn("isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.");
return false;
}
@ -419,20 +438,60 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
}
@Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
try {
if (detailedBolusInfo.insulin == 0 && detailedBolusInfo.carbs == 0) {
// neither carbs nor bolus requested
LOG.error("deliverTreatment: Invalid input");
return new PumpEnactResult().success(false).enacted(false)
.bolusDelivered(0d).carbsDelivered(0d)
.comment(MainApp.gs(R.string.danar_invalidinput));
} else if (detailedBolusInfo.insulin > 0) {
// bolus needed, ask pump to deliver it
return deliverBolus(detailedBolusInfo);
} else {
// no bolus required, carb only treatment
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
bolusingEvent.t = new Treatment();
bolusingEvent.t.isSMB = detailedBolusInfo.isSMB;
bolusingEvent.percent = 100;
MainApp.bus().post(bolusingEvent);
return new PumpEnactResult().success(true).enacted(true)
.bolusDelivered(0d).carbsDelivered(detailedBolusInfo.carbs)
.comment(MainApp.gs(R.string.virtualpump_resultok));
}
} finally {
triggerUIChange();
}
}
protected abstract PumpEnactResult deliverBolus(DetailedBolusInfo detailedBolusInfo);
protected abstract void triggerUIChange();
// Profile interface
@Nullable
public ProfileStore getProfile() {
return this.pumpStatus.profileStore;
}
public String getUnits() {
return this.pumpStatus.units;
}
public String getProfileName() {
return this.pumpStatus.activeProfileName;
}
// @Nullable
// public ProfileStore getProfile() {
// return this.pumpStatus.profileStore;
// }
//
// public String getUnits() {
// return this.pumpStatus.units;
// }
//
// public String getProfileName() {
// return this.pumpStatus.activeProfileName;
// }
}

View file

@ -19,7 +19,7 @@ public abstract class PumpStatus {
// last bolus
public Date lastBolusTime;
public double lastBolusAmount;
public Double lastBolusAmount;
// other pump settings
public String activeProfileName = "0";
@ -51,6 +51,7 @@ public abstract class PumpStatus {
public Double constraintBolus;
public Integer constraintCarbs;
public Double constraintMaxIob;
public Double[] basalsByHour;
public PumpStatus(PumpDescription pumpDescription) {
@ -63,7 +64,7 @@ public abstract class PumpStatus {
public abstract void initSettings();
public void setLastDataTimeToNow() {
public void setLastCommunicationToNow() {
this.lastDataTime = new Date();
this.lastConnection = System.currentTimeMillis();
}
@ -111,5 +112,4 @@ public abstract class PumpStatus {
public double last_bolus_amount = 0;
}

View file

@ -41,9 +41,7 @@ import java.util.List;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.LocationHelper;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.utils.SP;
@ -87,16 +85,15 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity {
TextView textview = (TextView) view.findViewById(R.id.rileylink_device_address);
String bleAddress = textview.getText().toString();
//SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SP.putString(MedtronicConst.Prefs.RileyLinkAddress, bleAddress);
SP.putString(RileyLinkConst.Prefs.RileyLinkAddress, bleAddress);
//Notify that we have a new rileylinkAddressKey
RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_rileylinkAddressKey);
LOG.debug("New rileylinkAddressKey: " + bleAddress);
//Notify that we have a new pumpIDKey
RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_pumpIDKey);
// //Notify that we have a new rileylinkAddressKey
// RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_rileylinkAddressKey);
//
// LOG.debug("New rileylinkAddressKey: " + bleAddress);
//
// //Notify that we have a new pumpIDKey
// RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_pumpIDKey);
finish();
}
});
@ -338,7 +335,7 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity {
BluetoothDevice device = mLeDevices.get(i);
String deviceName = device.getName();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if (SP.getString(MedtronicConst.Prefs.RileyLinkAddress, "").compareTo(device.getAddress()) == 0) {
if (SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, "").compareTo(device.getAddress()) == 0) {
//viewHolder.deviceName.setTextColor(getColor(R.color.secondary_text_light));
//viewHolder.deviceAddress.setTextColor(getColor(R.color.secondary_text_light));
deviceName += " (" + getResources().getString(R.string.rileylink_scanner_selected_device) + ")";

View file

@ -51,6 +51,10 @@ public abstract class PumpDriverAbstract implements PumpDriverInterface {
@Override
public Date lastDataTime() {
if (this.pumpStatusData == null || this.pumpStatusData.lastDataTime == null) {
return new Date();
}
return this.pumpStatusData.lastDataTime;
}
}

View file

@ -18,7 +18,9 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.Riley
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpMessage;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
@ -137,6 +139,8 @@ public abstract class RileyLinkCommunicationManager {
// **** FIXME: this wakeup doesn't seem to work well... must revisit
//receiverDeviceAwakeForMinutes = duration_minutes;
MedtronicUtil.setPumpDeviceState(PumpDeviceState.WakingUp);
if (force)
nextWakeUpRequired = 0L;
@ -147,6 +151,8 @@ public abstract class RileyLinkCommunicationManager {
RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 200, (byte) 0, (byte) 0, 25000, (byte) 0);
LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw()));
// FIXME wakeUp successful !!!!!!!!!!!!!!!!!!
nextWakeUpRequired = System.currentTimeMillis() + (receiverDeviceAwakeForMinutes * 60 * 1000);
} else {
LOG.trace("Last pump communication was recent, not waking pump.");
@ -203,17 +209,17 @@ public abstract class RileyLinkCommunicationManager {
wakeUp(receiverDeviceAwakeForMinutes, false);
FrequencyScanResults results = new FrequencyScanResults();
for(int i = 0; i < frequencies.length; i++) {
for (int i = 0; i < frequencies.length; i++) {
int tries = 3;
FrequencyTrial trial = new FrequencyTrial();
trial.frequencyMHz = frequencies[i];
rfspy.setBaseFrequency(frequencies[i]);
int sumRSSI = 0;
for(int j = 0; j < tries; j++) {
for (int j = 0; j < tries; j++) {
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData);
RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0);
RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 0, (byte) 0, (byte) 0, 3000, (byte) 0);
if (resp.wasTimeout()) {
LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]);
} else if (resp.looksLikeRadioPacket()) {
@ -235,7 +241,7 @@ public abstract class RileyLinkCommunicationManager {
}
results.sort(); // sorts in ascending order
LOG.debug("Sorted scan results:");
for(int k = 0; k < results.trials.size(); k++) {
for (int k = 0; k < results.trials.size(); k++) {
FrequencyTrial one = results.trials.get(k);
LOG.debug("Scan Result[{}]: Freq={}, avg RSSI = {}", k, one.frequencyMHz, one.averageRSSI);
}
@ -289,7 +295,7 @@ public abstract class RileyLinkCommunicationManager {
public double quickTuneForPump(double startFrequencyMHz) {
double betterFrequency = startFrequencyMHz;
double stepsize = 0.05;
for(int tries = 0; tries < 4; tries++) {
for (int tries = 0; tries < 4; tries++) {
double evenBetterFrequency = quickTunePumpStep(betterFrequency, stepsize);
if (evenBetterFrequency == 0.0) {
// could not see the pump at all.
@ -346,7 +352,7 @@ public abstract class RileyLinkCommunicationManager {
lastGoodReceiverCommunicationTime = System.currentTimeMillis();
SP.putLong(MedtronicConst.Prefs.LastGoodPumpCommunicationTime, lastGoodReceiverCommunicationTime);
pumpStatus.setLastDataTimeToNow();
MedtronicUtil.getPumpStatus().setLastCommunicationToNow();
}

View file

@ -18,6 +18,8 @@ public class RileyLinkConst {
public static final String BluetoothDisconnected = Prefix + "Bluetooth_Disconnected";
public static final String RileyLinkDisconnected = Prefix + "RileyLink_Disconnected";
public static final String RileyLinkNewAddressSet = Prefix + "NewAddressSet";
public static final String INTENT_NEW_rileylinkAddressKey = Prefix + "INTENT_NEW_rileylinkAddressKey";
public static final String INTENT_NEW_pumpIDKey = Prefix + "INTENT_NEW_pumpIDKey";
}
@ -32,4 +34,9 @@ public class RileyLinkConst {
public static final String MSG_ServiceCommand = Prefix + "MSG_ServiceCommand";
}
public class Prefs {
public static final String PrefPrefix = "pref_rileylink_";
public static final String RileyLinkAddress = PrefPrefix + "mac_address";
}
}

View file

@ -10,7 +10,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.data.RLHistoryItem;
@ -24,6 +24,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.S
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTask;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
/**
@ -38,10 +39,10 @@ public class RileyLinkUtil {
private static RileyLinkBLE rileyLinkBLE;
private static RileyLinkServiceData rileyLinkServiceData;
private static List<RLHistoryItem> historyRileyLink = new ArrayList<>();
private static PumpType pumpType;
private static MedtronicPumpStatus medtronicPumpStatus;
//private static PumpType pumpType;
//private static MedtronicPumpStatus medtronicPumpStatus;
private static RileyLinkService rileyLinkService;
private static RileyLinkCommunicationManager rileyLinkCommunicationManager;
protected static RileyLinkCommunicationManager rileyLinkCommunicationManager;
//private static RileyLinkIPCConnection rileyLinkIPCConnection;
private static MedtronicDeviceType medtronicPumpModel;
private static RileyLinkTargetFrequency rileyLinkTargetFrequency;
@ -52,13 +53,13 @@ public class RileyLinkUtil {
public static void setContext(Context contextIn) {
context = contextIn;
RileyLinkUtil.context = contextIn;
}
public static void sendBroadcastMessage(String message) {
Intent intent = new Intent(message);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
LocalBroadcastManager.getInstance(RileyLinkUtil.context).sendBroadcast(intent);
}
@ -68,37 +69,38 @@ public class RileyLinkUtil {
public static RileyLinkServiceState getServiceState() {
return rileyLinkServiceData.serviceState;
return RileyLinkUtil.rileyLinkServiceData.serviceState;
}
public static RileyLinkError getError() {
return rileyLinkServiceData.errorCode;
return RileyLinkUtil.rileyLinkServiceData.errorCode;
}
public static void setServiceState(RileyLinkServiceState newState, RileyLinkError errorCode) {
rileyLinkServiceData.serviceState = newState;
rileyLinkServiceData.errorCode = errorCode;
RileyLinkUtil.rileyLinkServiceData.serviceState = newState;
RileyLinkUtil.rileyLinkServiceData.errorCode = errorCode;
LOG.warn("RileyLink State Changed: {} {}", newState, errorCode == null ? "" : " - Error State: " + errorCode.name());
historyRileyLink.add(new RLHistoryItem(rileyLinkServiceData.serviceState, rileyLinkServiceData.errorCode));
RileyLinkUtil.historyRileyLink.add(new RLHistoryItem(RileyLinkUtil.rileyLinkServiceData.serviceState, RileyLinkUtil.rileyLinkServiceData.errorCode));
MainApp.bus().post(new EventMedtronicDeviceStatusChange(newState, errorCode));
}
public static void setRileyLinkBLE(RileyLinkBLE rileyLinkBLEIn) {
rileyLinkBLE = rileyLinkBLEIn;
RileyLinkUtil.rileyLinkBLE = rileyLinkBLEIn;
}
public static RileyLinkBLE getRileyLinkBLE() {
return rileyLinkBLE;
return RileyLinkUtil.rileyLinkBLE;
}
public static RileyLinkServiceData getRileyLinkServiceData() {
return rileyLinkServiceData;
return RileyLinkUtil.rileyLinkServiceData;
}
@ -107,34 +109,29 @@ public class RileyLinkUtil {
}
public static void setPumpType(PumpType pumpType) {
RileyLinkUtil.pumpType = pumpType;
}
public static void setPumpStatus(MedtronicPumpStatus medtronicPumpStatus) {
RileyLinkUtil.medtronicPumpStatus = medtronicPumpStatus;
}
// public static void setMedtronicPumpStatus(MedtronicPumpStatus medtronicPumpStatus) {
//
// RileyLinkUtil.medtronicPumpStatus = medtronicPumpStatus;
// }
// public static void addHistoryEntry(RLHistoryItem rlHistoryItem) {
// historyRileyLink.add(rlHistoryItem);
// }
public static MedtronicPumpStatus getMedtronicPumpStatus() {
return medtronicPumpStatus;
}
// public static MedtronicPumpStatus getMedtronicPumpStatus() {
//
// return RileyLinkUtil.medtronicPumpStatus;
// }
public static boolean hasPumpBeenTunned() {
return rileyLinkServiceData.tuneUpDone;
return RileyLinkUtil.rileyLinkServiceData.tuneUpDone;
}
public static void tuneUpPump() {
rileyLinkService.doTunePump(); // FIXME thread
RileyLinkUtil.rileyLinkService.doTunePump(); // FIXME thread
}
@ -154,7 +151,7 @@ public class RileyLinkUtil {
public static RileyLinkCommunicationManager getRileyLinkCommunicationManager() {
return rileyLinkCommunicationManager;
return RileyLinkUtil.rileyLinkCommunicationManager;
}
@ -165,7 +162,7 @@ public class RileyLinkUtil {
static ServiceTask currentTask;
// FIXME remove ?
public static void setCurrentTask(ServiceTask task) {
if (currentTask == null) {
currentTask = task;
@ -205,33 +202,16 @@ public class RileyLinkUtil {
// }
public static boolean isModelSet() {
return RileyLinkUtil.medtronicPumpModel != null;
}
public static void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) {
if (medtronicPumpModel != null && medtronicPumpModel != MedtronicDeviceType.Unknown_Device) {
RileyLinkUtil.medtronicPumpModel = medtronicPumpModel;
}
}
public static MedtronicDeviceType getMedtronicPumpModel() {
return medtronicPumpModel;
}
public static void setRileyLinkTargetFrequency(RileyLinkTargetFrequency rileyLinkTargetFrequency) {
RileyLinkUtil.rileyLinkTargetFrequency = rileyLinkTargetFrequency;
}
public static RileyLinkTargetFrequency getRileyLinkTargetFrequency() {
return rileyLinkTargetFrequency;
return RileyLinkUtil.rileyLinkTargetFrequency;
}
public static MedtronicPumpStatus getPumpStatus() {
return pumpStatus;
return RileyLinkUtil.pumpStatus;
}
}

View file

@ -150,7 +150,7 @@ public class RFSpy {
public RFSpyResponse getRadioVersion() {
RFSpyResponse resp = writeToData(getCommandArray(RFSpyCommand.GetVersion, null), 1000);
RFSpyResponse resp = writeToData(getCommandArray(RFSpyCommand.GetVersion, null), EXPECTED_MAX_BLUETOOTH_LATENCY_MS);
if (resp == null) {
LOG.error("getRadioVersion returned null");
}

View file

@ -1,18 +1,52 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs;
import info.nightscout.androidaps.R;
/**
* Created by andy on 14/05/2018.
*/
public enum RileyLinkError {
ParametersNotSetOrInvalid, //
GattDiscoveryFailed, //
TuneUpOfPumpFailed, //
UnableToObtainBluetoothAdapter, //
BluetoothDisabled, //
GattDeviceNotFound, //
RileyLinkUnreachable, //
DeviceIsNotRileyLink, //
// Configuration
// BT
NoBluetoothAdapter(R.string.rileylink_error_no_bt_adapter), //
BluetoothDisabled(R.string.rileylink_error_bt_disabled), //
// RileyLink
RileyLinkUnreachable(R.string.rileylink_error_unreachable), //
DeviceIsNotRileyLink(R.string.rileylink_error_not_rl), //
// Device
TuneUpOfPumpFailed(R.string.rileylink_error_tuneup_failed), //
NoContactWithDevice(R.string.rileylink_error_pump_unreachable, R.string.rileylink_error_pod_unreachable), //
;
int resourceId;
Integer resourceIdPod;
RileyLinkError(int resourceId) {
this.resourceId = resourceId;
}
RileyLinkError(int resourceId, int resourceIdPod) {
this.resourceId = resourceId;
this.resourceIdPod = resourceIdPod;
}
public int getResourceId(RileyLinkTargetDevice targetDevice) {
if (this.resourceIdPod != null) {
return targetDevice == RileyLinkTargetDevice.MedtronicPump ? //
this.resourceId : this.resourceIdPod;
} else {
return this.resourceId;
}
}
}

View file

@ -1,29 +1,30 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs;
import info.nightscout.androidaps.R;
/**
* Created by andy on 14/05/2018.
*/
public enum RileyLinkServiceState {
NotStarted, //
NotStarted(R.string.rileylink_state_not_started), //
// Bluetooth
BluetoothInitializing, // (S) init BT (if error no BT interface -> Disabled, BT not enabled -> BluetoothError)
BluetoothNotAvailable, // (E) BT not available, would happen only if device has no BT
BluetoothError, // (E) if BT gets disabled ( -> EnableBluetooth)
BluetoothReady, // (OK)
BluetoothInitializing(R.string.rileylink_state_bt_init), // (S) init BT (if error no BT interface -> Disabled, BT not enabled -> BluetoothError)
//BluetoothNotAvailable, // (E) BT not available, would happen only if device has no BT
BluetoothError(R.string.rileylink_state_bt_error), // (E) if BT gets disabled ( -> EnableBluetooth)
BluetoothReady(R.string.rileylink_state_bt_ready), // (OK)
// RileyLink
RileyLinkInitializing, // (S) start Gatt discovery (OK -> RileyLinkReady, Error -> BluetoothEnabled) ??
RileyLinkError, // (E)
RileyLinkReady, // (OK) if tunning was already done we go to PumpConnectorReady
RileyLinkInitializing(R.string.rileylink_state_rl_init), // (S) start Gatt discovery (OK -> RileyLinkReady, Error -> BluetoothEnabled) ??
RileyLinkError(R.string.rileylink_state_rl_error), // (E)
RileyLinkReady(R.string.rileylink_state_connected), // (OK) if tunning was already done we go to PumpConnectorReady
// Tunning
TuneUpPump, // (S)
//TuneUpPumpError, //
PumpConnectorError, // either TuneUp Error or pump couldn't not be contacted error
PumpConnectorReady, // (OK) RileyLink Ready for Pump Communication
TuneUpPump(R.string.rileylink_state_pc_tune_up), // (S)
PumpConnectorError(R.string.rileylink_state_pc_error), // either TuneUp Error or pump couldn't not be contacted error
PumpConnectorReady(R.string.rileylink_state_connected), // (OK) RileyLink Ready for Pump Communication
//Initializing, // get all parameters required for connection (if not possible -> Disabled, if sucessful -> EnableBluetooth)
@ -39,7 +40,49 @@ public enum RileyLinkServiceState {
;
int resourceId;
Integer resourceIdPod;
RileyLinkServiceState(int resourceId) {
this.resourceId = resourceId;
}
RileyLinkServiceState(int resourceId, int resourceIdPod) {
this.resourceId = resourceId;
this.resourceIdPod = resourceIdPod;
}
public int getResourceId(RileyLinkTargetDevice targetDevice) {
if (this.resourceIdPod != null) {
return targetDevice == RileyLinkTargetDevice.MedtronicPump ? //
this.resourceId : this.resourceIdPod;
} else {
return this.resourceId;
}
}
public static boolean isReady(RileyLinkServiceState serviceState) {
return (serviceState == RileyLinkReady || serviceState == PumpConnectorReady);
}
public boolean isConnecting() {
return (this == RileyLinkServiceState.BluetoothInitializing || //
//this == RileyLinkServiceState.BluetoothError || //
this == RileyLinkServiceState.BluetoothReady || //
this == RileyLinkServiceState.RileyLinkInitializing //
//this == RileyLinkServiceState.RileyLinkError
);
}
public boolean isError() {
return (
this == RileyLinkServiceState.BluetoothError || //
//this == RileyLinkServiceState.PumpConnectorError || //
this == RileyLinkServiceState.RileyLinkError);
}
}

View file

@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -32,6 +31,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
import static info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil.getRileyLinkCommunicationManager;
@ -160,6 +160,7 @@ public abstract class RileyLinkService extends Service {
} else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
// FIXME remove
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
LOG.debug("Bluetooth Action State Changed: " + state);
@ -219,6 +220,8 @@ public abstract class RileyLinkService extends Service {
doTunePump();
} else if (action.equals(RileyLinkConst.IPC.MSG_PUMP_quickTune)) {
doTunePump();
} else if (RileyLinkConst.Intents.RileyLinkNewAddressSet.equals(action)) {
reconfigureRileyLink(MedtronicUtil.getPumpStatus().rileyLinkAddress);
} else if (action.startsWith("MSG_PUMP_")) {
handlePumpSpecificIntents(intent);
} else if (RileyLinkConst.IPC.MSG_ServiceCommand.equals(action)) {
@ -277,6 +280,8 @@ public abstract class RileyLinkService extends Service {
intentFilter.addAction(RileyLinkConst.Intents.BluetoothDisconnected);
intentFilter.addAction(RileyLinkConst.Intents.RileyLinkReady);
intentFilter.addAction(RileyLinkConst.Intents.RileyLinkDisconnected);
intentFilter.addAction(RileyLinkConst.Intents.RileyLinkNewAddressSet);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
//intentFilter.addAction(RT2Const.serviceLocal.ipcBound);
@ -342,7 +347,7 @@ public abstract class RileyLinkService extends Service {
if (bluetoothAdapter == null) {
LOG.error("Unable to obtain a BluetoothAdapter.");
RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.UnableToObtainBluetoothAdapter);
RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.NoBluetoothAdapter);
} else {
if (!bluetoothAdapter.isEnabled()) {
@ -362,7 +367,7 @@ public abstract class RileyLinkService extends Service {
// returns true if our Rileylink configuration changed
public boolean reconfigureRileylink(String deviceAddress) {
public boolean reconfigureRileyLink(String deviceAddress) {
RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkInitializing);
@ -381,7 +386,7 @@ public abstract class RileyLinkService extends Service {
return true;
}
} else {
Toast.makeText(context, "Using RL " + deviceAddress, Toast.LENGTH_SHORT).show();
//Toast.makeText(context, "Using RL " + deviceAddress, Toast.LENGTH_SHORT).show();
LOG.debug("handleIPCMessage: Using RL " + deviceAddress);
if (RileyLinkUtil.getServiceState() == RileyLinkServiceState.NotStarted) {

View file

@ -48,7 +48,7 @@ public class InitializePumpManagerTask extends ServiceTask {
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady);
//RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpFound), null);
} else {
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.GattDeviceNotFound);
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.NoContactWithDevice);
//RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpLost), null);
}

View file

@ -4,9 +4,11 @@ package info.nightscout.androidaps.plugins.PumpMedtronic;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentManager;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -14,11 +16,14 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.crashlytics.android.Crashlytics;
import com.joanzapata.iconify.widget.IconTextView;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
@ -29,13 +34,15 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.events.EventTempBasalChange;
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
import info.nightscout.androidaps.plugins.PumpCommon.dialog.RileylinkSettingsActivity;
import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.PumpDanaR.Dialogs.ProfileViewDialog;
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRHistoryActivity;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicNewStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicRileyLinkStatusChange;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPumpValuesChanged;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.events.EventQueueChanged;
import info.nightscout.utils.DateUtil;
@ -43,7 +50,7 @@ import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SetWarnColor;
public class MedtronicFragment extends SubscriberFragment {
private static Logger log = LoggerFactory.getLogger(MedtronicFragment.class);
private static Logger LOG = LoggerFactory.getLogger(MedtronicFragment.class);
private Handler loopHandler = new Handler();
private Runnable refreshLoop = new Runnable() {
@ -57,8 +64,8 @@ public class MedtronicFragment extends SubscriberFragment {
@BindView(R.id.medtronic_lastconnection)
TextView lastConnectionView;
@BindView(R.id.medtronic_btconnection)
TextView btConnectionView;
//@BindView(R.id.medtronic_btconnection)
//TextView btConnectionView;
@BindView(R.id.medtronic_lastbolus)
TextView lastBolusView;
@ -69,15 +76,15 @@ public class MedtronicFragment extends SubscriberFragment {
@BindView(R.id.medtronic_tempbasal)
TextView tempBasalView;
@BindView(R.id.medtronic_battery)
@BindView(R.id.medtronic_pumpstate_battery)
TextView batteryView;
@BindView(R.id.medtronic_rl_status)
IconTextView rileyLinkStatus;
@BindView(R.id.medtronic_reservoir)
TextView reservoirView;
@BindView(R.id.medtronic_iob)
TextView iobView;
@BindView(R.id.medtronic_errors)
TextView errorsView;
@ -88,8 +95,12 @@ public class MedtronicFragment extends SubscriberFragment {
@BindView(R.id.overview_pumpstatuslayout)
LinearLayout pumpStatusLayout;
@BindView(R.id.overview_pumpstatus)
TextView pumpStatusView;
@BindView(R.id.overview_pump_medtronic)
TextView overviewPumpMedtronicView;
@BindView(R.id.medtronic_pump_status)
IconTextView pumpStatusIconView;
public MedtronicFragment() {
}
@ -114,7 +125,14 @@ public class MedtronicFragment extends SubscriberFragment {
View view = inflater.inflate(R.layout.medtronic_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
pumpStatusView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
overviewPumpMedtronicView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
rileyLinkStatus.setText(getTranslation(RileyLinkServiceState.NotStarted.getResourceId(getTargetDevice())));
rileyLinkStatus.setTextSize(14);
pumpStatusIconView.setTextColor(Color.WHITE);
pumpStatusIconView.setTextSize(14);
pumpStatusIconView.setText("{fa-bed}");
return view;
} catch (Exception e) {
@ -141,51 +159,140 @@ public class MedtronicFragment extends SubscriberFragment {
startActivity(new Intent(getContext(), RileylinkSettingsActivity.class));
}
@OnClick(R.id.medtronic_btconnection)
/*@OnClick(R.id.medtronic_btconnection)
void onBtConnectionClick() {
log.debug("Clicked connect to pump");
DanaRPump.getInstance().lastConnection = 0;
ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked connect to pump", null);
}
}*/
@Subscribe
public void onStatusEvent(final EventPumpStatusChanged c) {
}
@Subscribe
public void onStatusEvent(final EventMedtronicDeviceStatusChange eventStatusChange) {
LOG.info("onStatusEvent(EventMedtronicDeviceStatusChange): {}", eventStatusChange);
Activity activity = getActivity();
final String status = c.textStatus();
//final String status = c.textStatus();
if (activity != null) {
activity.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (c.sStatus == EventPumpStatusChanged.CONNECTING)
btConnectionView.setText("{fa-bluetooth-b spin} " + c.sSecondsElapsed + "s");
else if (c.sStatus == EventPumpStatusChanged.CONNECTED)
btConnectionView.setText("{fa-bluetooth}");
else if (c.sStatus == EventPumpStatusChanged.DISCONNECTED)
btConnectionView.setText("{fa-bluetooth-b}");
if (!status.equals("")) {
pumpStatusView.setText(status);
pumpStatusLayout.setVisibility(View.VISIBLE);
} else {
pumpStatusLayout.setVisibility(View.GONE);
}
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
if (eventStatusChange.rileyLinkServiceState != null)
pumpStatus.rileyLinkServiceState = eventStatusChange.rileyLinkServiceState;
if (eventStatusChange.rileyLinkError != null)
pumpStatus.rileyLinkError = eventStatusChange.rileyLinkError;
if (eventStatusChange.pumpDeviceState != null)
pumpStatus.pumpDeviceState = eventStatusChange.pumpDeviceState;
setDeviceStatus(pumpStatus);
//pumpStatusIconView.setTextColor(Color.WHITE);
//pumpStatusIconView.setTextSize(20);
//pumpStatusIconView.setText("{fa-bed}");
}
}
);
}
}
@Subscribe
public void onStatusEvent(final EventMedtronicRileyLinkStatusChange s) {
private void setDeviceStatus(MedtronicPumpStatus pumpStatus) {
if (pumpStatus.rileyLinkServiceState != null) {
int resourceId = pumpStatus.rileyLinkServiceState.getResourceId(getTargetDevice());
rileyLinkStatus.setTextColor(Color.WHITE);
rileyLinkStatus.setTextSize(14);
if (pumpStatus.rileyLinkServiceState == RileyLinkServiceState.NotStarted) {
rileyLinkStatus.setText(" " + getTranslation(resourceId));
rileyLinkStatus.setTextSize(14);
} else if (pumpStatus.rileyLinkServiceState.isConnecting()) {
rileyLinkStatus.setText("{fa-bluetooth-b spin} " + getTranslation(resourceId));
} else if (pumpStatus.rileyLinkServiceState.isError()) {
rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
rileyLinkStatus.setTextColor(Color.RED);
} else {
rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
}
}
if (pumpStatus.rileyLinkError != null) {
int resourceId = pumpStatus.rileyLinkError.getResourceId(getTargetDevice());
errorsView.setText(getTranslation(resourceId));
}
if (pumpStatus.pumpDeviceState != null) {
// TODO Pump State
switch (pumpStatus.pumpDeviceState) {
case Sleeping:
pumpStatusIconView.setText("{fa-bed} " + pumpStatus.pumpDeviceState.name());
break;
case NeverContacted:
case WakingUp:
case ProblemContacting:
case InvalidConfiguration:
pumpStatusIconView.setText(" " + pumpStatus.pumpDeviceState.name());
break;
// FIXME
case Active:
pumpStatusIconView.setText(" " + pumpStatus.pumpDeviceState.name());
break;
// FIXME
case ErrorWhenCommunicating:
pumpStatusIconView.setText(" " + pumpStatus.pumpDeviceState.name());
break;
// FIXME
case TimeoutWhenCommunicating:
pumpStatusIconView.setText(" " + pumpStatus.pumpDeviceState.name());
break;
}
}
if (queueView != null) {
// FIXME
//queueView.setVisibility(View.GONE);
Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
if (status.toString().equals("")) {
queueView.setVisibility(View.GONE);
} else {
queueView.setVisibility(View.VISIBLE);
queueView.setText(status);
}
}
}
public RileyLinkTargetDevice getTargetDevice() {
return RileyLinkTargetDevice.MedtronicPump;
}
public String getTranslation(int resourceId) {
return MainApp.gs(resourceId);
}
@Subscribe
public void onStatusEvent(final EventMedtronicNewStatus s) {
public void onStatusEvent(final EventMedtronicPumpValuesChanged s) {
updateGUI();
}
@ -215,26 +322,41 @@ public class MedtronicFragment extends SubscriberFragment {
public void run() {
MedtronicPumpPlugin plugin = (MedtronicPumpPlugin) MedtronicPumpPlugin.getPlugin();
PumpStatus pump = plugin.getPumpStatusData();
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
if (pump.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastConnection;
setDeviceStatus(pumpStatus);
if (pumpStatus.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pumpStatus.lastConnection;
int agoMin = (int) (agoMsec / 60d / 1000d);
lastConnectionView.setText(DateUtil.timeString(pump.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
lastConnectionView.setText(DateUtil.timeString(pumpStatus.lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
}
if (pump.lastBolusTime != null && pump.lastBolusTime.getTime() != 0) {
Long agoMsec = System.currentTimeMillis() - pump.lastBolusTime.getTime();
double agoHours = agoMsec / 60d / 60d / 1000d;
if (agoHours < 6) // max 6h back
lastBolusView.setText(DateUtil.timeString(pump.lastBolusTime) + " " + DateUtil.sinceString(pump.lastBolusTime.getTime()) + " " + DecimalFormatter.to2Decimal(DanaRPump.getInstance().lastBolusAmount) + " U");
else
lastBolusView.setText("");
// last bolus
Double bolus = pumpStatus.lastBolusAmount;
Date bolusTime = pumpStatus.lastBolusTime;
if (bolus != null && bolusTime != null) {
long agoMsc = System.currentTimeMillis() - pumpStatus.lastBolusTime.getTime();
double bolusMinAgo = agoMsc / 60d / 1000d;
String unit = MainApp.gs(R.string.insulin_unit_shortname);
String ago;
if ((agoMsc < 60 * 1000)) {
ago = MainApp.gs(R.string.combo_pump_connected_now);
} else if (bolusMinAgo < 60) {
ago = DateUtil.minAgo(pumpStatus.lastBolusTime.getTime());
} else {
ago = DateUtil.hourAgo(pumpStatus.lastBolusTime.getTime());
}
lastBolusView.setText(MainApp.gs(R.string.combo_last_bolus, bolus, unit, ago));
} else {
lastBolusView.setText("");
}
//dailyUnitsView.setText(DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U");
//SetWarnColor.setColor(dailyUnitsView, pump.dailyTotalUnits, pump.maxDailyTotalUnits * 0.75d, pump.maxDailyTotalUnits * 0.9d);
basaBasalRateView.setText("(" + (pump.activeProfileName) + ") " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
basaBasalRateView.setText("(" + (pumpStatus.activeProfileName) + ") " + DecimalFormatter.to2Decimal(ConfigBuilderPlugin.getActivePump().getBaseBasalRate()) + " U/h");
if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
@ -251,29 +373,14 @@ public class MedtronicFragment extends SubscriberFragment {
}
}
reservoirView.setText(DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + " / " + pump.reservoirFullUnits + " U");
SetWarnColor.setColorInverse(reservoirView, pump.reservoirRemainingUnits, 50d, 20d);
batteryView.setText("{fa-battery-" + (pump.batteryRemaining / 25) + "}");
SetWarnColor.setColorInverse(batteryView, pump.batteryRemaining, 51d, 26d);
iobView.setText(pump.iob + " U");
reservoirView.setText(DecimalFormatter.to0Decimal(pumpStatus.reservoirRemainingUnits) + " / " + pumpStatus.reservoirFullUnits + " U");
SetWarnColor.setColorInverse(reservoirView, pumpStatus.reservoirRemainingUnits, 50d, 20d);
batteryView.setText("{fa-battery-" + (pumpStatus.batteryRemaining / 25) + "}");
SetWarnColor.setColorInverse(batteryView, pumpStatus.batteryRemaining, 51d, 26d);
//iobView.setText(pump.iob + " U");
if (queueView != null) {
// FIXME
queueView.setVisibility(View.GONE);
// Spanned status = ConfigBuilderPlugin.getCommandQueue().spannedStatus();
// if (status.toString().equals("")) {
// queueView.setVisibility(View.GONE);
// } else {
// queueView.setVisibility(View.VISIBLE);
// queueView.setText(status);
// }
}
errorsView.setText(pump.getErrorInfo());
errorsView.setText(pumpStatus.getErrorInfo());
}
});

View file

@ -3,19 +3,35 @@ package info.nightscout.androidaps.plugins.PumpMedtronic;
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.PumpCommon.PumpPluginAbstract;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUIComm;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUITask;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpDriver;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPumpValuesChanged;
import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
/**
* Created by andy on 23.04.18.
@ -28,10 +44,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private RileyLinkMedtronicService medtronicService;
protected static MedtronicPumpPlugin plugin = null;
protected MedtronicPumpStatus pumpStatusLocal = null;
private MedtronicPumpStatus pumpStatusLocal = null;
private MedtronicUIComm medtronicUIComm = new MedtronicUIComm();
boolean firstRun = true;
public static MedtronicPumpPlugin getPlugin() {
if (plugin == null)
plugin = new MedtronicPumpPlugin();
return plugin;
@ -39,6 +56,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private MedtronicPumpPlugin() {
// super(new PluginDescription() //
// .mainType(PluginType.PUMP) //
// .fragmentClass(MedtronicFragment.class.getName()) //
// .pluginName(R.string.medtronic_name) //
// .shortName(R.string.medtronic_name_short) //
// .preferencesId(R.xml.pref_medtronic));
super(new MedtronicPumpDriver(), //
"MedtronicPump", //
new PluginDescription() //
@ -50,17 +76,39 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
PumpType.Minimed_512_712 // we default to most basic model, correct model from config is loaded later
);
LOG.error("After supper called.");
serviceConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
LOG.debug("Service is disconnected");
LOG.debug("RileyLinkMedtronicService is disconnected");
medtronicService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
LOG.debug("Service is connected");
LOG.debug("RileyLinkMedtronicService is connected");
RileyLinkMedtronicService.LocalBinder mLocalBinder = (RileyLinkMedtronicService.LocalBinder) service;
medtronicService = mLocalBinder.getServiceInstance();
//pumpStatusLocal.setNotInPreInit();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
SystemClock.sleep(5000);
LOG.debug("Trying to start service L1.");
if (MedtronicUtil.getPumpStatus() != null) {
LOG.debug("Trying to starting service L2");
if (MedtronicUtil.getPumpStatus().setNotInPreInit()) {
break;
}
}
}
}
}).start();
}
};
@ -70,25 +118,54 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public void initPumpStatusData() {
pumpStatusLocal = new MedtronicPumpStatus(pumpDescription);
LOG.error("Init Pump Status Data");
this.pumpStatusLocal = new MedtronicPumpStatus(pumpDescription);
MedtronicUtil.setPumpStatus(pumpStatusLocal);
pumpStatusLocal.refreshConfiguration();
//MedtronicUtil.setPumpStatus(pumpStatusLocal);
LOG.debug("initPumpStatusData: {}", this.pumpStatusLocal);
this.pumpStatus = pumpStatusLocal;
if (pumpStatusLocal.maxBasal != null)
pumpDescription.maxTempAbsolute = (pumpStatusLocal.maxBasal != null) ? pumpStatusLocal.maxBasal : 35.0d;
// needs to be changed in configuration, after all functionalities are done
pumpDescription.isBolusCapable = false;
pumpDescription.isTempBasalCapable = true;
pumpDescription.isBolusCapable = true;
pumpDescription.isTempBasalCapable = false; // WIP
pumpDescription.isExtendedBolusCapable = false;
pumpDescription.isSetBasalProfileCapable = true;
pumpDescription.isRefillingCapable = false;
pumpDescription.isSetBasalProfileCapable = false;
// unchangable
pumpDescription.tempBasalStyle = PumpDescription.PERCENT;
pumpDescription.tempDurationStep15mAllowed = false;
pumpDescription.tempDurationStep30mAllowed = true;
pumpDescription.isRefillingCapable = true;
pumpDescription.storesCarbInfo = false;
pumpDescription.is30minBasalRatesCapable = true;
pumpDescription.supportsTDDs = true;
pumpDescription.needsManualTDDLoad = false;
//pumpStatusLocal.setNotInPreInit();
// set first Medtronic Pump Start
if (!SP.contains(MedtronicConst.Prefs.FirstPumpStart)) {
SP.putLong(MedtronicConst.Prefs.FirstPumpStart, System.currentTimeMillis());
}
}
public void onStartCustomActions() {
//pumpStatusLocal.setNotInPreInit();
}
public Class getServiceClass() {
@ -101,17 +178,23 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
return "Medtronic";
}
@Override
public PumpDescription getPumpDescription() {
return this.pumpDescription;
}
//@Override
//public String shortStatus(boolean veryShort) {
// return "Medtronic Pump";
//}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return false;
}
// we don't loadTDD
@Override
public PumpEnactResult loadTDDs() {
return OPERATION_NOT_SUPPORTED;
}
// Pump Plugin
@ -131,42 +214,381 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
return isServiceSet() && medtronicService.isBusy();
}
public boolean isConnected() {
return isServiceSet() && medtronicService.isConnected();
return isServiceSet() && medtronicService.isInitialized();
}
public boolean isConnecting() {
return isServiceSet() && medtronicService.isConnecting();
if (!isServiceSet())
return true;
else
return !medtronicService.isInitialized();
}
public void connect(String reason) {
if (isServiceSet()) {
medtronicService.connect(reason);
}
// we don't use this.
// we connect to RileyLink on startup and keep connection opened, then connection to pump
// is established when needed.
}
public void disconnect(String reason) {
if (isServiceSet()) {
medtronicService.disconnect(reason);
}
// see comment in connect
}
public void stopConnecting() {
if (isServiceSet()) {
medtronicService.stopConnecting();
}
// see comment in connect
}
// FIXME
@Override
public void getPumpStatus() {
if (isServiceSet()) {
medtronicService.getPumpStatus();
if (this.pumpStatusLocal == null) {
// FIXME I don't know why this happens
LOG.debug("getPumpStatus: reset pumoStatusLocal ");
this.pumpStatusLocal = MedtronicUtil.getPumpStatus();
}
if (firstRun) {
initializePump();
}
LOG.error("MedtronicPumpPlugin::getPumpStatus NOT IMPLEMENTED.");
LOG.debug("getPumpStatus: {}", this.pumpStatusLocal);
LOG.debug("getPumpStatus: {}", MedtronicUtil.getPumpStatus());
pumpStatusLocal.setLastCommunicationToNow();
MainApp.bus().post(new EventMedtronicPumpValuesChanged());
}
private void initializePump() {
LOG.error("MedtronicPumpPlugin::initializePump NOT IMPLEMENTED.");
// pump history handling - special, updates every 5 minutes ???
// remaining insulin (>50 = 4h; 50-20 = 1h; 15m)
medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin);
// remaining power (1h)
// configuration (1h -> maybe just if something configured (something we are interested in))
// read profile
medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD);
this.firstRun = false;
}
@Override
public boolean isThisProfileSet(Profile profile) {
//LOG.error("MedtronicPumpPlugin::isThisProfileSet NOT IMPLEMENTED.");
if (!isConnected()) {
return true;
}
MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD);
boolean invalid = false;
if (responseTask.haveData()) {
Double[] basalsByHour = getMDTPumpStatus().basalsByHour;
int index = 0;
for (Profile.BasalValue basalValue : profile.getBasalValues()) {
int hour = basalValue.timeAsSeconds / (60 * 60);
//LOG.debug("Basal profile::Pump rate={}, NS rate={}", basalsByHour[index], basalValue.value);
//LOG.debug("Basal profile::Pump time={}, NS time={}", index, basalValue.timeAsSeconds / (60 * 60));
if (MedtronicUtil.isSame(basalsByHour[index], basalValue.value)) {
if (index != hour) {
invalid = true;
break;
}
} else {
invalid = true;
break;
}
index++;
}
if (!invalid) {
LOG.debug("Basal profile is same as AAPS one.");
} else {
LOG.debug("Basal profile on Pump is differentr than AAPS one.");
}
} else {
invalid = true;
LOG.debug("Basal profile NO DATA");
}
return (!invalid);
}
@Override
public Date lastDataTime() {
if (pumpStatusLocal != null && pumpStatusLocal.lastDataTime != null) {
return pumpStatusLocal.lastDataTime;
}
return new Date();
}
@Override
public double getBaseBasalRate() {
return getMDTPumpStatus().getBasalProfileForHour();
}
private MedtronicPumpStatus getMDTPumpStatus() {
if (pumpStatusLocal == null) {
LOG.warn("Reset Pump Status Local");
pumpStatusLocal = MedtronicUtil.getPumpStatus();
}
return pumpStatusLocal;
}
protected void triggerUIChange() {
MainApp.bus().post(new EventMedtronicPumpValuesChanged());
}
@NonNull
protected PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) {
try {
LOG.error("MedtronicPumpPlugin::deliverBolus Not fully implemented - Just base command.");
MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, detailedBolusInfo.insulin);
Boolean response = (Boolean) responseTask.returnData;
if (response) {
}
readPumpHistory();
return new PumpEnactResult().success(response).enacted(response);
// pump.activity = MainApp.gs(R.string.combo_pump_action_bolusing, detailedBolusInfo.insulin);
// MainApp.bus().post(new EventComboPumpUpdateGUI());
//
// // check pump is ready and all pump bolus records are known
// CommandResult stateResult = runCommand(null, 2, () -> ruffyScripter.readQuickInfo(1));
// if (!stateResult.success) {
// return new PumpEnactResult().success(false).enacted(false)
// .comment(MainApp.gs(R.string.combo_error_no_connection_no_bolus_delivered));
// }
// if (stateResult.reservoirLevel != -1 && stateResult.reservoirLevel - 0.5 < detailedBolusInfo.insulin) {
// return new PumpEnactResult().success(false).enacted(false)
// .comment(MainApp.gs(R.string.combo_reservoir_level_insufficient_for_bolus));
// }
// // the commands above ensured a connection was made, which updated this field
// if (pumpHistoryChanged) {
// return new PumpEnactResult().success(false).enacted(false)
// .comment(MainApp.gs(R.string.combo_bolus_rejected_due_to_pump_history_change));
// }
//
// Bolus previousBolus = stateResult.history != null && !stateResult.history.bolusHistory.isEmpty()
// ? stateResult.history.bolusHistory.get(0)
// : new Bolus(0, 0, false);
//
// // reject a bolus if one with the exact same size was successfully delivered
// // within the last 1-2 minutes
// if (Math.abs(previousBolus.amount - detailedBolusInfo.insulin) < 0.01
// && previousBolus.timestamp + 60 * 1000 > System.currentTimeMillis()) {
// log.debug("Bolu request rejected, same bolus was successfully delivered very recently");
// return new PumpEnactResult().success(false).enacted(false)
// .comment(MainApp.gs(R.string.bolus_frequency_exceeded));
// }
//
//
//
// if (cancelBolus) {
// return new PumpEnactResult().success(true).enacted(false);
// }
//
// BolusProgressReporter progressReporter = detailedBolusInfo.isSMB ? nullBolusProgressReporter : bolusProgressReporter;
//
// // start bolus delivery
// scripterIsBolusing = true;
// runCommand(null, 0,
// () -> ruffyScripter.deliverBolus(detailedBolusInfo.insulin, progressReporter));
// scripterIsBolusing = false;
//
// // Note that the result of the issued bolus command is not checked. If there was
// // a connection problem, ruffyscripter tried to recover and we can just check the
// // history below to see what was actually delivered
//
// // get last bolus from pump history for verification
// // (reads 2 records to update `recentBoluses` further down)
// CommandResult postBolusStateResult = runCommand(null, 3, () -> ruffyScripter.readQuickInfo(2));
// if (!postBolusStateResult.success) {
// return new PumpEnactResult().success(false).enacted(false)
// .comment(MainApp.gs(R.string.combo_error_bolus_verification_failed));
// }
// Bolus lastPumpBolus = postBolusStateResult.history != null && !postBolusStateResult.history.bolusHistory.isEmpty()
// ? postBolusStateResult.history.bolusHistory.get(0)
// : null;
//
// // no bolus delivered?
// if (lastPumpBolus == null || lastPumpBolus.equals(previousBolus)) {
// if (cancelBolus) {
// return new PumpEnactResult().success(true).enacted(false);
// } else {
// return new PumpEnactResult()
// .success(false)
// .enacted(false)
// .comment(MainApp.gs(R.string.combo_error_no_bolus_delivered));
// }
// }
//
// // at least some insulin delivered, so add it to treatments
// if (!addBolusToTreatments(detailedBolusInfo, lastPumpBolus))
// return new PumpEnactResult().success(false).enacted(true)
// .comment(MainApp.gs(R.string.combo_error_updating_treatment_record));
//
// // check pump bolus record has a sane timestamp
// long now = System.currentTimeMillis();
// if (lastPumpBolus.timestamp < now - 10 * 60 * 1000 || lastPumpBolus.timestamp > now + 10 * 60 * 1000) {
// Notification notification = new Notification(Notification.COMBO_PUMP_ALARM, MainApp.gs(R.string.combo_suspious_bolus_time), Notification.URGENT);
// MainApp.bus().post(new EventNewNotification(notification));
// }
//
// // update `recentBoluses` so the bolus was just delivered won't be detected as a new
// // bolus that has been delivered on the pump
// recentBoluses = postBolusStateResult.history.bolusHistory;
//
// // only a partial bolus was delivered
// if (Math.abs(lastPumpBolus.amount - detailedBolusInfo.insulin) > 0.01) {
// if (cancelBolus) {
// return new PumpEnactResult().success(true).enacted(true);
// }
// return new PumpEnactResult().success(false).enacted(true)
// .comment(MainApp.gs(R.string.combo_error_partial_bolus_delivered,
// lastPumpBolus.amount, detailedBolusInfo.insulin));
// }
//
// // full bolus was delivered successfully
// incrementBolusCount();
// return new PumpEnactResult()
// .success(true)
// .enacted(lastPumpBolus.amount > 0)
// .bolusDelivered(lastPumpBolus.amount)
// .carbsDelivered(detailedBolusInfo.carbs);
} finally {
// pump.activity = null;
// MainApp.bus().post(new EventComboPumpUpdateGUI());
// MainApp.bus().post(new EventRefreshOverview("Bolus"));
// cancelBolus = false;
triggerUIChange();
}
}
@Override
public void stopBolusDelivering() {
}
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
LOG.error("MedtronicPumpPlugin::setTempBasalAbsolute Not fully implemented - Just base command.");
MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.SetTemporaryBasal, absoluteRate, durationInMinutes);
Boolean response = (Boolean) responseTask.returnData;
if (response) {
//pumpStatusLocal.tempBasalStart = new Date(); // TODO maybe not needed
//pumpStatusLocal.tempBasalRemainMin = durationInMinutes;
}
readPumpHistory();
return new PumpEnactResult().success(response).enacted(response);
}
private void readPumpHistory() {
LOG.error("MedtronicPumpPlugin::readPumpHistory NOT IMPLEMENTED.");
}
// TODO
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT IMPLEMENTED.");
return null;
//return OPERATION_NOT_YET_SUPPORTED;
}
// TODO
@Override
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
LOG.error("MedtronicPumpPlugin::cancelTempBasal Not fully implemented - Just base command.");
MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR);
Boolean response = (Boolean) responseTask.returnData;
if (response) {
}
readPumpHistory();
return new PumpEnactResult().success(response).enacted(response);
}
// TODO not supported but we will display message to user that he/she should do it on the pump
@Override
public PumpEnactResult cancelExtendedBolus() {
LOG.error("MedtronicPumpPlugin::cancelExtendedBolus NOT IMPLEMENTED.");
return null;
}
// OPERATIONS not supported by Pump
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
LOG.error("MedtronicPumpPlugin::setTempBasalPercent NOT IMPLEMENTED.");
return null;
}
@Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
LOG.error("MedtronicPumpPlugin::setNewBasalProfile NOT IMPLEMENTED.");
LOG.debug("isSetBasalProfileCapable:" + this.pumpDescription.isSetBasalProfileCapable);
return new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.medtronic_cmd_profile_not_set));
}
}

View file

@ -12,16 +12,13 @@ import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessageType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.Page;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.RawHistoryPage;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.history.Record;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.ButtonPressCarelinkMessageBody;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.CarelinkLongMessageBody;
@ -32,9 +29,13 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageBody
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PacketType;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpAckMessageBody;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.PumpMessage;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BatteryStatusDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
@ -65,7 +66,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
@Override
protected void configurePumpSpecificSettings() {
pumpStatus = RileyLinkUtil.getMedtronicPumpStatus();
pumpStatus = MedtronicUtil.getPumpStatus();
}
@ -85,9 +86,32 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
pumpModel = getPumpModel();
}
boolean connected = (pumpModel != MedtronicDeviceType.Unknown_Device);
if (connected) {
checkFirstConnectionTime();
setLastConnectionTime();
}
return (pumpModel != MedtronicDeviceType.Unknown_Device);
}
private void setLastConnectionTime() {
// FIXME rename
this.pumpStatus.setLastCommunicationToNow();
// FIXME set to SP
}
private void checkFirstConnectionTime() {
// FIXME set to SP
}
public static MedtronicCommunicationManager getInstance() {
return medtronicCommunicationManager;
@ -190,6 +214,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
// TODO fix this with new code, and new response (Page)
public Page getPumpHistoryPage(int pageNumber) {
RawHistoryPage rval = new RawHistoryPage();
wakeUp(receiverDeviceAwakeForMinutes, false);
@ -380,11 +405,20 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
return sendAndGetResponse(commandType, bodyData, 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) {
// wakeUp
wakeUp(receiverDeviceAwakeForMinutes, false);
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active);
// create message
PumpMessage msg;
@ -395,6 +429,9 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// send and wait for response
PumpMessage response = sendAndListen(msg, timeoutMs);
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return response;
}
@ -530,8 +567,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel);
if (!RileyLinkUtil.isModelSet()) {
RileyLinkUtil.setMedtronicPumpModel((MedtronicDeviceType) responseObject);
if (!MedtronicUtil.isModelSet()) {
MedtronicUtil.setMedtronicPumpModel((MedtronicDeviceType) responseObject);
}
return responseObject == null ? null : (MedtronicDeviceType) responseObject;
@ -564,7 +601,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
public List<PumpSettingDTO> getPumpSettings() {
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.getSettings(RileyLinkUtil.getMedtronicPumpModel()));
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.getSettings(MedtronicUtil.getMedtronicPumpModel()));
return responseObject == null ? null : (List<PumpSettingDTO>) responseObject;
}
@ -573,6 +610,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// TODO test with values bigger than 30U
public Boolean setBolus(double units) {
LOG.warn("setBolus: " + units);
wakeUp(false);
byte[] body = MedtronicUtil.getBolusStrokes(units);
@ -620,39 +659,20 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// FIXME:
public Integer getRemainingBattery() {
public BatteryStatusDTO getRemainingBattery() {
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.GetBatteryStatus);
return responseObject == null ? null : (Integer) responseObject;
return responseObject == null ? null : (BatteryStatusDTO) responseObject;
}
// FIXME --- After this line commands in development --- REMOVE THIS COMMANDS
// TODO remove for AAPS
// public ISFTable getPumpISFProfile() {
//
// PumpMessage response = sendAndGetResponse(MedtronicCommandType.ReadInsulinSensitivities);
//
// ISFTable table = new ISFTable();
// table.parseFrom(response.getContents());
// return table;
// }
// TODO remove for AAPS
public PumpMessage getBolusWizardCarbProfile() {
PumpMessage response = sendAndGetResponse(MedtronicCommandType.GetCarbohydrateRatios);
return response;
}
// TODO test
// TODO remove, we will see state from History
public PumpMessage getPumpState() {
PumpMessage response = sendAndGetResponse(MedtronicCommandType.PumpState);
@ -666,6 +686,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
// TODO remove, we will see bolus status from History
public PumpMessage getBolusStatus() {
PumpMessage response = sendAndGetResponse(MedtronicCommandType.SetBolus, new byte[]{0x03, 0x00, 0x00, 0x00}, 4000);
@ -711,27 +732,27 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
public byte[] getFullMessageBody(byte[] bodyData, int length) {
byte newBodyData[] = getEmptyMessage(length);
newBodyData[0] = (byte) bodyData.length;
for (int i = 0; i < bodyData.length; i++) {
newBodyData[i + 1] = bodyData[i];
}
return newBodyData;
}
// public byte[] getFullMessageBody(byte[] bodyData, int length) {
// byte newBodyData[] = getEmptyMessage(length);
//
// newBodyData[0] = (byte) bodyData.length;
//
// for (int i = 0; i < bodyData.length; i++) {
// newBodyData[i + 1] = bodyData[i];
// }
//
// return newBodyData;
// }
public byte[] getEmptyMessage(int length) {
byte newBodyData[] = new byte[length];
for (int i = 0; i < length; i++) {
newBodyData[i] = 0x00;
}
return newBodyData;
}
// public byte[] getEmptyMessage(int length) {
// byte newBodyData[] = new byte[length];
// for (int i = 0; i < length; i++) {
// newBodyData[i] = 0x00;
// }
//
// return newBodyData;
// }
public PumpMessage cancelBolus() {
@ -753,24 +774,25 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
return null;
}
// Set TBR
// Cancel TBR (set TBR 100%)
// Set TBR 100%
// Cancel TBR (set TBR 100%) 100%
// Get Status (40%)
// Set Bolus 80%
// Set Bolus 100%
// Set Extended Bolus 20%
// Cancel Bolus 0% ?
// Cancel Extended Bolus 0% ?
// Cancel Bolus 0% -- NOT SUPPORTED
// Cancel Extended Bolus 0% -- NOT SUPPORTED
// Get Basal Profile (0x92) Read STD 100%
// Set Basal Profile 20%
// Set Basal Profile 0% -- NOT SUPPORTED
// Read History 60%
// Load TDD ?
// FIXME remove - each part needs to be gotten manually
public void updatePumpManagerStatus() {
Integer resp = getRemainingBattery();
pumpStatus.batteryRemaining = resp == null ? -1 : resp;
//Integer resp = getRemainingBattery();
//pumpStatus.batteryRemaining = resp == null ? -1 : resp;
pumpStatus.remainUnits = getRemainingInsulin();

View file

@ -70,7 +70,7 @@ public abstract class MedtronicHistoryDecoder {
List<? extends MedtronicHistoryEntry> minimedHistoryRecords = processPageAndCreateRecords(dataPage);
for(MedtronicHistoryEntry record : minimedHistoryRecords) {
for (MedtronicHistoryEntry record : minimedHistoryRecords) {
decodeRecord(record);
}
@ -94,7 +94,7 @@ public abstract class MedtronicHistoryDecoder {
return byteList;
}
if (MedtronicUtil.getDeviceType() == null) {
if (MedtronicUtil.getMedtronicPumpModel() == null) {
LOG.error("Device Type is not defined.");
return byteList;
}
@ -116,7 +116,7 @@ public abstract class MedtronicHistoryDecoder {
unknownOpCodes = new HashMap<Integer, Integer>();
mapStatistics = new HashMap<RecordDecodeStatus, Map<String, String>>();
for(RecordDecodeStatus stat : RecordDecodeStatus.values()) {
for (RecordDecodeStatus stat : RecordDecodeStatus.values()) {
mapStatistics.put(stat, new HashMap<String, String>());
}
}
@ -141,7 +141,7 @@ public abstract class MedtronicHistoryDecoder {
protected void showStatistics() {
StringBuilder sb = new StringBuilder();
for(Map.Entry unknownEntry : unknownOpCodes.entrySet()) {
for (Map.Entry unknownEntry : unknownOpCodes.entrySet()) {
StringUtil.appendToStringBuilder(sb, "" + unknownEntry.getKey(), ", ");
}
@ -151,13 +151,13 @@ public abstract class MedtronicHistoryDecoder {
LOG.debug("Unknown Op Codes: {}", sb.toString());
}
for(Map.Entry<RecordDecodeStatus, Map<String, String>> entry : mapStatistics.entrySet()) {
for (Map.Entry<RecordDecodeStatus, Map<String, String>> entry : mapStatistics.entrySet()) {
sb = new StringBuilder();
if (entry.getKey() != RecordDecodeStatus.OK) {
if (entry.getValue().size() == 0) continue;
for(Map.Entry<String, String> entrysub : entry.getValue().entrySet()) {
for (Map.Entry<String, String> entrysub : entry.getValue().entrySet()) {
StringUtil.appendToStringBuilder(sb, entrysub.getKey(), ", ");
}

View file

@ -12,12 +12,12 @@ import java.util.List;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.BasalProfileEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.RawHistoryPage;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfileEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BolusWizardDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpBolusType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/**
@ -124,7 +124,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
int els = getUnsignedInt(elements);
for(int k = 0; k < (els - 2); k++) {
for (int k = 0; k < (els - 2); k++) {
listRawData.add((byte) dataClear.get(counter));
counter++;
}
@ -132,7 +132,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
special = true;
} else {
for(int j = 0; j < (entryType.getTotalLength() - 1); j++) {
for (int j = 0; j < (entryType.getTotalLength() - 1); j++) {
try {
listRawData.add(dataClear.get(counter));
@ -508,7 +508,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
Float rate = null;
int index = body[2];
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), MedtronicDeviceType.Medtronic_523andHigher)) {
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) {
rate = body[1] * 0.025f;
}
@ -530,7 +530,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
float bolus_strokes = 10.0f;
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), MedtronicDeviceType.Medtronic_523andHigher)) {
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) {
// https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102
bolus_strokes = 40.0f;
@ -607,7 +607,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
byte[] data = entry.getHead();
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), MedtronicDeviceType.Medtronic_523andHigher)) {
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), MedtronicDeviceType.Medtronic_523andHigher)) {
bolus.setRequestedAmount(bitUtils.toInt(data[0], data[1]) / 40.0f);
bolus.setDeliveredAmount(bitUtils.toInt(data[2], data[3]) / 10.0f);
bolus.setInsulinOnBoard(bitUtils.toInt(data[4], data[5]) / 40.0f);

View file

@ -361,7 +361,7 @@ public enum PumpHistoryEntryType //implements CodeEnum
int size = defaultValue;
for (SpecialRule rule : rules) {
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getDeviceType(), rule.deviceType)) {
if (MedtronicDeviceType.isSameDevice(MedtronicUtil.getMedtronicPumpModel(), rule.deviceType)) {
size = rule.size;
break;
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message;
/**
* Created by geoff on 6/2/16.
*/
@Deprecated
public class ButtonPressCarelinkMessageBody extends CarelinkLongMessageBody {
public static final byte BUTTON_EASY = 0x00;
public static final byte BUTTON_ESC = 0x01;

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message;
/**
* Created by geoff on 5/29/16.
*/
@Deprecated
public class GetPumpModelCarelinkMessageBody extends MessageBody {
@Override

View file

@ -10,14 +10,13 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BatteryStatusDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BatteryType;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpConfigurationGroup;
@ -38,7 +37,7 @@ public class MedtronicConverter {
LOG.debug("Raw response before convert: " + HexDump.toHexStringDisplayable(rawContent));
this.pumpModel = RileyLinkUtil.getMedtronicPumpModel();
this.pumpModel = MedtronicUtil.getMedtronicPumpModel();
switch (commandType) {
@ -132,39 +131,42 @@ public class MedtronicConverter {
}
private Integer decodeBatteryStatus(byte[] rawData) {
//00 00 7C 00 00
private BatteryStatusDTO decodeBatteryStatus(byte[] rawData) {
// 00 7C 00 00
if (rawData.length <= 2) {
BatteryStatusDTO batteryStatus = new BatteryStatusDTO();
int status = rawData[0];
int status = rawData[0];
if (status == 0) {
return 75; // NORMAL
} else if (status == 1) {
return 20; // LOW
} else if (status == 2) {
if (status == 0) {
batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Normal;
} else if (status == 1) {
batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Low;
} else if (status == 2) {
batteryStatus.batteryStatusType = BatteryStatusDTO.BatteryStatusType.Unknown;
}
}
if (rawData.length > 1) {
return null;
} else {
// if response in 3 bytes then we add additional information
//double d = MedtronicUtil.makeUnsignedShort(rawData[2], rawData[1]) / 100.0d;
double d = ByteUtil.toInt(rawData[1], rawData[2]) / 100.0d;
double perc = (d - BatteryType.Alkaline.lowVoltage) / (BatteryType.Alkaline.highVoltage - BatteryType.Alkaline.lowVoltage);
batteryStatus.voltage = d;
LOG.warn("Percent status: " + perc);
LOG.warn("Unknown status: " + rawData[0]);
LOG.warn("Full result: " + d);
// double perc = (d - BatteryType.Alkaline.lowVoltage) / (BatteryType.Alkaline.highVoltage - BatteryType.Alkaline.lowVoltage);
//
// LOG.warn("Percent status: " + perc);
// LOG.warn("Unknown status: " + rawData[0]);
// LOG.warn("Full result: " + d);
//
// int percent = (int) (perc * 100.0d);
int percent = (int) (perc * 100.0d);
return percent;
//return percent;
}
return batteryStatus;
}

View file

@ -0,0 +1,93 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/**
* Created by andy on 6/14/18.
*/
public class MedtronicUIComm {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicUIComm.class);
MedtronicCommunicationManager mcmInstance = null;
MedtronicUIPostprocessor uiPostprocessor = new MedtronicUIPostprocessor();
private MedtronicCommunicationManager getCommunicationManager() {
if (mcmInstance == null) {
mcmInstance = MedtronicCommunicationManager.getInstance();
}
return mcmInstance;
}
public synchronized MedtronicUITask executeCommand(MedtronicCommandType commandType, Object... parameters) {
LOG.warn("Execute Command: " + commandType.name());
MedtronicUITask task = new MedtronicUITask(commandType, parameters);
MedtronicUtil.setCurrentCommand(commandType);
// new Thread(() -> {
// LOG.warn("@@@ Start Thread");
//
// task.execute(getCommunicationManager());
//
// LOG.warn("@@@ End Thread");
// });
task.execute(getCommunicationManager());
// for (int i = 0; i < getMaxWaitTime(commandType); i++) {
// synchronized (task) {
//// try {
////
//// //task.wait(1000);
//// } catch (InterruptedException e) {
//// LOG.error("executeCommand InterruptedException", e);
//// }
//
//
// SystemClock.sleep(1000);
// }
//
// if (task.isReceived()) {
// break;
// }
// }
if (!task.isReceived()) {
LOG.warn("Reply not received for " + commandType);
}
task.postProcess(uiPostprocessor);
return task;
}
/**
* We return 25s as waitTime (17 for wakeUp, and addtional 8 for data retrieval) for normal commands and
* 120s for History. Real time for returning data would be arround 5s, but lets be sure.
*
* @param commandType
* @return
*/
private int getMaxWaitTime(MedtronicCommandType commandType) {
if (commandType == MedtronicCommandType.GetHistoryData)
return 120;
else
return 25;
}
}

View file

@ -0,0 +1,65 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/**
* Created by andy on 6/15/18.
*/
public class MedtronicUIPostprocessor {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicUIPostprocessor.class);
MedtronicPumpStatus pumpStatus;
public MedtronicUIPostprocessor() {
pumpStatus = MedtronicUtil.getPumpStatus();
}
// this is mostly intended for command that return certain statuses (Remaining Insulin, ...), and
// where responses won't be directly used
public void postProcessData(MedtronicUITask uiTask) {
switch (uiTask.commandType) {
case GetBasalProfileSTD: {
BasalProfile basalProfile = (BasalProfile) uiTask.returnData;
pumpStatus.basalsByHour = basalProfile.getProfilesByHour();
}
break;
case SetBolus: {
pumpStatus.lastBolusAmount = uiTask.getDoubleFromParameters(0);
pumpStatus.lastBolusTime = new Date();
}
break;
case GetRemainingInsulin: {
pumpStatus.reservoirRemainingUnits = (Float) uiTask.returnData;
}
break;
// no postprocessing
case PumpModel:
break;
default:
LOG.warn("Post-processing not implemented for {}.", uiTask.commandType.name());
}
}
}

View file

@ -0,0 +1,219 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/**
* Created by andy on 6/14/18.
*/
public class MedtronicUITask {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicUITask.class);
public MedtronicCommandType commandType;
private Object[] parameters;
private boolean received;
public Object returnData;
String errorDescription;
boolean invalid = false;
public MedtronicUITask(MedtronicCommandType commandType) {
this(commandType, null);
}
public MedtronicUITask(MedtronicCommandType commandType, Object... parameters) {
this.commandType = commandType;
this.parameters = parameters;
}
public void execute(MedtronicCommunicationManager communicationManager) {
LOG.warn("@@@ In execute. {}", commandType);
switch (commandType) {
case PumpModel: {
returnData = communicationManager.getPumpModel();
}
break;
case GetBasalProfileSTD: {
returnData = communicationManager.getBasalProfile();
}
break;
case GetRemainingInsulin: {
returnData = communicationManager.getRemainingInsulin();
}
break;
case RealTimeClock: {
returnData = communicationManager.getPumpTime();
}
break;
case GetBatteryStatus: {
returnData = communicationManager.getRemainingBattery();
}
break;
case SetTemporaryBasal: {
TempBasalPair tbr = getTBRSettings();
if (tbr != null) {
returnData = communicationManager.setTBR(tbr);
}
}
break;
case ReadTemporaryBasal: {
returnData = communicationManager.getTemporaryBasal();
}
break;
case PumpState: {
// TODO maybe remove this, data returned is almost useless
returnData = communicationManager.getPumpState();
}
break;
// case "RefreshData.GetBolus": {
// returnData = communicationManager.getBolusStatus();
// }
// break;
case Settings:
case Settings_512: {
returnData = communicationManager.getPumpSettings();
}
break;
case SetBolus: {
Double amount = getDoubleFromParameters(0);
if (amount != null)
returnData = communicationManager.setBolus(amount);
}
break;
case CancelTBR: {
// FIXME check if TBR is actually running
returnData = communicationManager.cancelTBR();
}
break;
case SetBasalProfileSTD:
case SetBasalProfileA: {
// Float amount = getAmount();
//
// if (amount != null) {
//
// BasalProfile profile = new BasalProfile();
//
// int basalStrokes1 = MedtronicUtil.getBasalStrokesInt(amount);
// int basalStrokes2 = MedtronicUtil.getBasalStrokesInt(amount * 2);
//
// for (int i = 0; i < 24; i++) {
// profile.addEntry(new BasalProfileEntry(i % 2 == 0 ? basalStrokes1 : basalStrokes2, i * 2));
// }
//
// returnData = communicationManager.setBasalProfile(profile);
// }
}
break;
default: {
LOG.warn("This commandType is not supported (yet) - {}.", commandType);
invalid = true;
}
}
if (returnData == null) {
if (!invalid)
errorDescription = communicationManager.getErrorResponse();
received = true;
} else {
received = true;
}
}
private TempBasalPair getTBRSettings() {
TempBasalPair tempBasalPair = new TempBasalPair(
getDoubleFromParameters(0), //
false, //
getIntegerFromParameters(1));
return tempBasalPair;
}
private Float getFloatFromParameters(int index) {
return (Float) parameters[index];
}
public Double getDoubleFromParameters(int index) {
return (Double) parameters[index];
}
public Integer getIntegerFromParameters(int index) {
return (Integer) parameters[index];
}
public Object getResult() {
return returnData;
}
public boolean isReceived() {
return (returnData != null || errorDescription != null);
}
public boolean haveData() {
return (returnData != null);
}
public void postProcess(MedtronicUIPostprocessor postprocessor) {
EventMedtronicDeviceStatusChange statusChange;
LOG.warn("@@@ In execute. {}", commandType);
// should never happen
if (invalid) {
statusChange = new EventMedtronicDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating, "Unsupported command in MedtronicUITask");
MainApp.bus().post(statusChange);
}
if (errorDescription != null) {
statusChange = new EventMedtronicDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating, errorDescription);
MainApp.bus().post(statusChange);
}
if (returnData != null) {
postprocessor.postProcessData(this);
}
MedtronicUtil.getPumpStatus().setLastCommunicationToNow();
MedtronicUtil.setCurrentCommand(null);
}
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data;
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import org.joda.time.Instant;
import org.slf4j.Logger;
@ -66,11 +66,11 @@ public class BasalProfile {
LOG.error("setRawData: buffer is null!");
return false;
}
int len = Math.min(MAX_RAW_DATA_SIZE, data.length);
mRawData = new byte[len];
System.arraycopy(data, 0, mRawData, 0, len);
//int len = Math.min(MAX_RAW_DATA_SIZE, data.length);
mRawData = data;
//System.arraycopy(data, 0, mRawData, 0, len);
if (DEBUG_BASALPROFILE) {
LOG.debug(String.format("setRawData: copied raw data buffer of %d bytes.", len));
LOG.debug(String.format("setRawData: copied raw data buffer of %d bytes.", data.length));
}
return true;
}
@ -79,7 +79,7 @@ public class BasalProfile {
public void dumpBasalProfile() {
LOG.debug("Basal Profile entries:");
List<BasalProfileEntry> entries = getEntries();
for(int i = 0; i < entries.size(); i++) {
for (int i = 0; i < entries.size(); i++) {
BasalProfileEntry entry = entries.get(i);
String startString = entry.startTime.toString("HH:mm");
LOG.debug(String.format("Entry %d, rate=%.3f (0x%02X), start=%s (0x%02X)", i + 1, entry.rate, entry.rate_raw, startString, entry.startTime_raw));
@ -91,7 +91,7 @@ public class BasalProfile {
public String getBasalProfileAsString() {
StringBuffer sb = new StringBuffer("Basal Profile entries:\n");
List<BasalProfileEntry> entries = getEntries();
for(int i = 0; i < entries.size(); i++) {
for (int i = 0; i < entries.size(); i++) {
BasalProfileEntry entry = entries.get(i);
String startString = entry.startTime.toString("HH:mm");
@ -195,7 +195,7 @@ public class BasalProfile {
List<Byte> outData = new ArrayList<>();
for(BasalProfileEntry profileEntry : listEntries) {
for (BasalProfileEntry profileEntry : listEntries) {
byte[] strokes = MedtronicUtil.getBasalStrokes(profileEntry.rate, true);
@ -234,7 +234,7 @@ public class BasalProfile {
if (entries.isEmpty()) {
LOG.error("testParser: failed");
} else {
for(int i = 0; i < entries.size(); i++) {
for (int i = 0; i < entries.size(); i++) {
BasalProfileEntry e = entries.get(i);
LOG.debug(String.format("testParser entry #%d: rate: %.2f, start %d:%d", i, e.rate, e.startTime.getHourOfDay(), e.startTime.getMinuteOfHour()));
}
@ -243,6 +243,52 @@ public class BasalProfile {
}
public Double[] getProfilesByHour() {
List<BasalProfileEntry> entries = getEntries();
Double[] basalByHour = new Double[24];
for (int i = 0; i < entries.size(); i++) {
BasalProfileEntry current = entries.get(i);
int currentTime = (current.startTime_raw % 2 == 0) ?
current.startTime_raw : current.startTime_raw - 1;
currentTime = (currentTime * 30) / 60;
int lastHour = 0;
if ((i + 1) == entries.size()) {
lastHour = 24;
} else {
BasalProfileEntry basalProfileEntry = entries.get(i + 1);
int rawTime = (basalProfileEntry.startTime_raw % 2 == 0) ?
basalProfileEntry.startTime_raw : basalProfileEntry.startTime_raw - 1;
lastHour = (rawTime * 30) / 60;
}
//System.out.println("Current time: " + currentTime + " Next Time: " + lastHour);
for (int j = currentTime; j < lastHour; j++) {
basalByHour[j] = current.rate;
}
}
// StringBuilder sb = new StringBuilder();
//
// for (int i = 0; i < 24; i++) {
// sb.append("" + i + "=" + basalByHour[i]);
// sb.append("\n");
// }
//
// System.out.println("Basal Profile: \n" + sb.toString());
return basalByHour;
}
public byte[] getRawData() {
return this.mRawData;
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data;
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import org.joda.time.LocalTime;

View file

@ -0,0 +1,28 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BatteryType;
/**
* Created by andy on 6/14/18.
*/
public class BatteryStatusDTO {
public BatteryStatusType batteryStatusType;
public double voltage;
public int getCalculatedPercent(BatteryType batteryType) {
double percent = (voltage - batteryType.lowVoltage) / (batteryType.highVoltage - batteryType.lowVoltage);
return (int) (percent * 100.0d);
}
public enum BatteryStatusType {
Normal,
Low,
Unknown
}
}

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpBolusType;
/**
* Application: GGC - GNU Gluco Control

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
/**
* Created by andy on 6/2/18.
*/
@Deprecated
public class PumpTimeStampedRecord {
protected LocalDateTime localDateTime;

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.data;
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -27,7 +27,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.utils.StringUtil;
* <p>
* Author: Andy {andy@atech-software.com}
*/
@Deprecated
public class TemporaryBasalRateDTO extends PumpTimeStampedRecord {
private Float amount;

View file

@ -182,7 +182,10 @@ public enum MedtronicCommandType implements Serializable //, MinimedCommandTypeI
// READ_CURRENT_CBG_PAGE : 0xCD
// };
;
// Fake Commands
CancelTBR(),;
public byte commandCode = 0;
private int recordLength = 64;
@ -214,12 +217,17 @@ public enum MedtronicCommandType implements Serializable //, MinimedCommandTypeI
mapByCode = new HashMap<>();
for(MedtronicCommandType medtronicCommandType : values()) {
for (MedtronicCommandType medtronicCommandType : values()) {
mapByCode.put(medtronicCommandType.getCommandCode(), medtronicCommandType);
}
}
MedtronicCommandType() {
// this is for "fake" commands needed by AAPS MedtronicUITask
}
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, MinimedCommandParameterType parameterType) {
this(code, description, targetType, devices, parameterType, 64, 1, 0, 0, 0, 0);
}
@ -283,7 +291,7 @@ public enum MedtronicCommandType implements Serializable //, MinimedCommandTypeI
private static HashMap<MedtronicDeviceType, String> getDeviceTypesArray(MedtronicDeviceType... types) {
HashMap<MedtronicDeviceType, String> hashMap = new HashMap<MedtronicDeviceType, String>();
for(MedtronicDeviceType type : types) {
for (MedtronicDeviceType type : types) {
hashMap.put(type, null);
}
@ -294,7 +302,7 @@ public enum MedtronicCommandType implements Serializable //, MinimedCommandTypeI
private static byte[] getByteArray(int... data) {
byte[] array = new byte[data.length];
for(int i = 0; i < data.length; i++) {
for (int i = 0; i < data.length; i++) {
array[i] = (byte) data[i];
}

View file

@ -76,7 +76,7 @@ public enum MedtronicDeviceType {
mapByDescription = new HashMap<>();
for(MedtronicDeviceType minimedDeviceType : values()) {
for (MedtronicDeviceType minimedDeviceType : values()) {
if (!minimedDeviceType.isFamily) {
mapByDescription.put(minimedDeviceType.pumpModel, minimedDeviceType);
@ -104,7 +104,7 @@ public enum MedtronicDeviceType {
public static boolean isSameDevice(MedtronicDeviceType deviceWeCheck, MedtronicDeviceType deviceSources) {
if (deviceSources.isFamily) {
for(MedtronicDeviceType mdt : deviceSources.familyMembers) {
for (MedtronicDeviceType mdt : deviceSources.familyMembers) {
if (mdt == deviceWeCheck)
return true;
}
@ -148,4 +148,8 @@ public enum MedtronicDeviceType {
public static boolean isLargerFormat(MedtronicDeviceType model) {
return isSameDevice(model, Medtronic_523andHigher);
}
public int getBolusStrokes() {
return (isLargerFormat(this)) ? 40 : 10;
}
}

View file

@ -0,0 +1,11 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
/**
* Created by andy on 6/14/18.
*/
public enum MedtronicUITaskType {
GetStatus;
}

View file

@ -1,4 +1,4 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
import java.util.HashMap;
@ -42,7 +42,7 @@ public enum PumpBolusType //implements CodeEnumWithTranslation
private static boolean translated;
static {
for(PumpBolusType pbt : values()) {
for (PumpBolusType pbt : values()) {
codeMapping.put(pbt.code, pbt);
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
/**
* Created by andy on 6/11/18.
*/
public enum PumpDeviceState {
NeverContacted, //
Sleeping, //
WakingUp, //
Active, //
ErrorWhenCommunicating, //
TimeoutWhenCommunicating, //
ProblemContacting, //
InvalidConfiguration;
Integer resourceId = null;
PumpDeviceState() {
}
PumpDeviceState(int resourceId) {
this.resourceId = resourceId;
}
}

View file

@ -78,7 +78,7 @@ public class MedtronicPumpDriver extends VirtualPumpDriver /*implements PumpInte
if (Config.logPumpComm)
LOG.debug("Setting temp basal absolute: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
getPumpStatusData().setLastDataTimeToNow();
getPumpStatusData().setLastCommunicationToNow();
return result;
}

View file

@ -4,7 +4,9 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.driver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
@ -13,8 +15,14 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
/**
@ -23,8 +31,6 @@ import info.nightscout.utils.SP;
public class MedtronicPumpStatus extends PumpStatus {
//private static MedtronicPumpStatus medtronicPumpStatus = new MedtronicPumpStatus();
private static Logger LOG = LoggerFactory.getLogger(MedtronicPumpStatus.class);
public String errorDescription = null;
@ -37,40 +43,48 @@ public class MedtronicPumpStatus extends PumpStatus {
private String[] frequencies;
private boolean isFrequencyUS = false;
public boolean inPreInit = true;
String regexMac = "([\\da-fA-F]{1,2}(?:\\:|$)){6}";
String regexSN = "[0-9]{6}";
private Map<String, PumpType> medtronicPumpMap = null;
// statuses
public RileyLinkServiceState rileyLinkServiceState = RileyLinkServiceState.NotStarted;
public RileyLinkError rileyLinkError;
public PumpDeviceState pumpDeviceState = PumpDeviceState.NeverContacted;
// fixme
public long getTimeIndex() {
return (long) Math.ceil(time.getTime() / 60000d);
}
// public long getTimeIndex() {
// return (long) Math.ceil(time.getTime() / 60000d);
// }
//
//
// public void setTimeIndex(long timeIndex) {
// this.timeIndex = timeIndex;
// }
//
//
// public long timeIndex;
//
// public Date time;
public void setTimeIndex(long timeIndex) {
this.timeIndex = timeIndex;
}
public long timeIndex;
public Date time;
public double remainUnits = 0;
//public double remainingUnits = 0;
public int remainBattery = 0;
public double currentBasal = 0;
public int tempBasalInProgress = 0;
public int tempBasalRatio = 0;
public double tempBasalAmount = 0.0d;
public int tempBasalRemainMin = 0;
public Date tempBasalStart;
public Date last_bolus_time;
public double last_bolus_amount = 0;
//public Date last_bolus_time; in main class
//public double last_bolus_amount = 0;
// fixme
@ -113,20 +127,15 @@ public class MedtronicPumpStatus extends PumpStatus {
}
boolean serialChanged = false;
boolean rileyLinkAddressChanged = false;
public void verifyConfiguration() {
try {
// FIXME don't reload information several times
if (this.medtronicPumpMap == null) createMedtronicPumpMap();
this.errorDescription = null;
this.serialNumber = null;
this.pumpType = null;
this.pumpFrequency = null;
this.rileyLinkAddress = null;
this.maxBolus = null;
this.maxBasal = null;
if (this.medtronicPumpMap == null)
createMedtronicPumpMap();
String serialNr = SP.getString(MedtronicConst.Prefs.PumpSerial, null);
@ -139,7 +148,10 @@ public class MedtronicPumpStatus extends PumpStatus {
this.errorDescription = MainApp.gs(R.string.medtronic_error_serial_invalid);
return;
} else {
this.serialNumber = serialNr;
if (!serialNr.equals(this.serialNumber)) {
this.serialNumber = serialNr;
serialChanged = true;
}
}
}
@ -158,10 +170,10 @@ public class MedtronicPumpStatus extends PumpStatus {
} else {
this.pumpType = medtronicPumpMap.get(pumpTypePart);
RileyLinkUtil.setPumpStatus(this);
if (pumpTypePart.startsWith("7")) this.reservoirFullUnits = "300";
else this.reservoirFullUnits = "180";
if (pumpTypePart.startsWith("7"))
this.reservoirFullUnits = "300";
else
this.reservoirFullUnits = "176";
}
}
@ -178,11 +190,14 @@ public class MedtronicPumpStatus extends PumpStatus {
} else {
this.pumpFrequency = pumpFrequency;
this.isFrequencyUS = pumpFrequency.equals(frequencies[0]);
RileyLinkUtil.setRileyLinkTargetFrequency(this.isFrequencyUS ? //
RileyLinkTargetFrequency.Medtronic_US : RileyLinkTargetFrequency.Medtronic_WorldWide);
}
}
String rileyLinkAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, null);
String rileyLinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, null);
if (rileyLinkAddress == null) {
this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid);
@ -191,7 +206,10 @@ public class MedtronicPumpStatus extends PumpStatus {
if (!rileyLinkAddress.matches(regexMac)) {
this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid);
} else {
this.rileyLinkAddress = rileyLinkAddress;
if (!rileyLinkAddress.equals(this.rileyLinkAddress)) {
this.rileyLinkAddress = rileyLinkAddress;
rileyLinkAddressChanged = true;
}
}
}
@ -212,12 +230,29 @@ public class MedtronicPumpStatus extends PumpStatus {
SP.putString(MedtronicConst.Prefs.MaxBasal, "35");
}
startService();
} catch (Exception ex) {
this.errorDescription = ex.getMessage();
LOG.error("Error on Verification: " + ex.getMessage(), ex);
}
}
private boolean startService() {
if (serialChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
MedtronicUtil.getMedtronicService().setPumpIDString(this.serialNumber); // short operation
serialChanged = false;
}
if (rileyLinkAddressChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
MedtronicUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkNewAddressSet);
rileyLinkAddressChanged = false;
}
return (rileyLinkAddressChanged == false && serialChanged == false);
}
public String getErrorInfo() {
verifyConfiguration();
@ -232,4 +267,22 @@ public class MedtronicPumpStatus extends PumpStatus {
}
public boolean setNotInPreInit() {
this.inPreInit = false;
return startService();
}
public double getBasalProfileForHour() {
if (basalsByHour != null) {
GregorianCalendar c = new GregorianCalendar();
int hour = c.get(Calendar.HOUR_OF_DAY);
return basalsByHour[hour];
}
return 0;
}
}

View file

@ -0,0 +1,53 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.events;
import info.nightscout.androidaps.events.Event;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
/**
* Created by andy on 04.06.2018.
*/
public class EventMedtronicDeviceStatusChange extends Event {
public RileyLinkServiceState rileyLinkServiceState;
public RileyLinkError rileyLinkError;
public PumpDeviceState pumpDeviceState;
public String errorDescription;
// public EventMedtronicDeviceStatusChange(RileyLinkServiceState rileyLinkServiceState, PumpDeviceState pumpDeviceState) {
// this.rileyLinkServiceState = rileyLinkServiceState;
// this.pumpDeviceState = pumpDeviceState;
// }
public EventMedtronicDeviceStatusChange(RileyLinkServiceState rileyLinkServiceState) {
this(rileyLinkServiceState, null);
}
public EventMedtronicDeviceStatusChange(RileyLinkServiceState rileyLinkServiceState, RileyLinkError rileyLinkError) {
this.rileyLinkServiceState = rileyLinkServiceState;
this.rileyLinkError = rileyLinkError;
}
public EventMedtronicDeviceStatusChange(PumpDeviceState pumpDeviceState) {
this.pumpDeviceState = pumpDeviceState;
}
public EventMedtronicDeviceStatusChange(PumpDeviceState pumpDeviceState, String errorDescription) {
this.pumpDeviceState = pumpDeviceState;
this.errorDescription = errorDescription;
}
@Override
public String toString() {
return "EventMedtronicDeviceStatusChange [" +
"rileyLinkServiceState=" + rileyLinkServiceState +
", rileyLinkError=" + rileyLinkError +
", pumpDeviceState=" + pumpDeviceState +
']';
}
}

View file

@ -5,5 +5,5 @@ import info.nightscout.androidaps.events.Event;
/**
* Created by andy on 04.06.2018.
*/
public class EventMedtronicNewStatus extends Event {
public class EventMedtronicPumpValuesChanged extends Event {
}

View file

@ -1,9 +0,0 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.events;
import info.nightscout.androidaps.events.Event;
/**
* Created by andy on 04.06.2018.
*/
public class EventMedtronicRileyLinkStatusChange extends Event {
}

View file

@ -34,8 +34,10 @@ import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.Page;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
/**
@ -67,7 +69,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
super(MainApp.instance().getApplicationContext());
instance = this;
LOG.debug("RileyLinkMedtronicService newly constructed");
RileyLinkUtil.setRileyLinkService(this);
MedtronicUtil.setMedtronicService(this);
pumpStatus = (MedtronicPumpStatus) MedtronicPumpPlugin.getPlugin().getPumpStatusData();
}
@ -236,7 +238,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
setPumpIDString(SP.getString(MedtronicConst.Prefs.PumpSerial, "000000"));
// get most recently used RileyLink address
rileyLinkServiceData.rileylinkAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, "");
rileyLinkServiceData.rileylinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, "");
rileyLinkBLE = new RileyLinkBLE(this.context); // or this
rfspy = new RFSpy(rileyLinkBLE);
@ -244,7 +246,6 @@ public class RileyLinkMedtronicService extends RileyLinkService {
RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE);
// init rileyLinkCommunicationManager
pumpCommunicationManager = new MedtronicCommunicationManager(context, rfspy, rileyLinkTargetFrequency);
medtronicCommunicationManager = (MedtronicCommunicationManager) pumpCommunicationManager;
@ -261,10 +262,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
}
/* private functions */
private void setPumpIDString(String pumpID) {
public void setPumpIDString(String pumpID) {
if (pumpID.length() != 6) {
LOG.error("setPumpIDString: invalid pump id string: " + pumpID);
return;
@ -272,9 +270,6 @@ public class RileyLinkMedtronicService extends RileyLinkService {
byte[] pumpIDBytes = ByteUtil.fromHexString(pumpID);
//SP.putString(MedtronicConst.Prefs.PumpSerial, pumpIDString);
if (pumpIDBytes == null) {
LOG.error("Invalid pump ID? " + ByteUtil.shortHexString(pumpIDBytes));
@ -294,38 +289,18 @@ public class RileyLinkMedtronicService extends RileyLinkService {
LOG.info("Using pump ID " + pumpID);
rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes);
return;
}
MedtronicUtil.setPumpDeviceState(PumpDeviceState.InvalidConfiguration);
//LOG.info("setPumpIDString: saved pumpID " + idString);
}
private void reportPumpFound() {
//rileyLinkIPCConnection.sendMessage(RT2Const.IPC.MSG_PUMP_pumpFound);
}
// public void setCurrentTask(ServiceTask task) {
// if (currentTask == null) {
// currentTask = task;
// } else {
// LOG.error("setCurrentTask: Cannot replace current task");
// }
// }
//
//
// public void finishCurrentTask(ServiceTask task) {
// if (task != currentTask) {
// LOG.error("finishCurrentTask: task does not match");
// }
// // hack to force deep copy of transport contents
// ServiceTransport transport = task.getServiceTransport().clone();
//
// if (transport.hasServiceResult()) {
// sendServiceTransportResponse(transport, transport.getServiceResult());
// }
// currentTask = null;
// }
/* private functions */
public void handleIncomingServiceTransport(Intent intent) {
@ -467,7 +442,6 @@ public class RileyLinkMedtronicService extends RileyLinkService {
public void connect(String reason) {
//bluetoothInit(); // this starts chain-loading connection
}

View file

@ -14,14 +14,13 @@ public class MedtronicConst {
public static final String PumpSerial = PrefPrefix + "serial";
public static final String PumpType = PrefPrefix + "pump_type";
public static final String PumpFrequency = PrefPrefix + "frequency";
public static final String RileyLinkAddress = PrefPrefix + "rileylink_mac";
public static final String MaxBolus = PrefPrefix + "max_bolus";
public static final String MaxBasal = PrefPrefix + "max_basal";
public static final String FirstPumpStart = Prefix + "first_pump_use";
public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime";
public static final String LastGoodPumpFrequency = Prefix + "LastGoodPumpFrequency";
}

View file

@ -8,22 +8,32 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService;
/**
* Created by andy on 5/9/18.
*/
public class MedtronicUtil {
public class MedtronicUtil extends RileyLinkUtil {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicUtil.class);
private static MedtronicDeviceType deviceType;
private static boolean lowLevelDebug = true;
private static PumpDeviceState pumpDeviceState;
private static MedtronicDeviceType medtronicPumpModel;
private static RileyLinkMedtronicService medtronicService;
private static MedtronicPumpStatus medtronicPumpStatus;
private static MedtronicCommandType currentCommand;
public static LocalTime getTimeFrom30MinInterval(int interval) {
@ -68,7 +78,7 @@ public class MedtronicUtil {
byte[] array = new byte[data.size()];
for(int i = 0; i < data.size(); i++) {
for (int i = 0; i < data.size(); i++) {
array[i] = data.get(i);
}
@ -103,7 +113,7 @@ public class MedtronicUtil {
public static byte[] getBolusStrokes(double amount) {
return getStrokes(amount, 10, false);
return getStrokes(amount, medtronicPumpModel.getBolusStrokes(), false);
}
@ -117,7 +127,7 @@ public class MedtronicUtil {
int strokes = getStrokesInt(amount, strokesPerUnit);
return getByteArrayFromUnsignedShort(strokes, false);
return getByteArrayFromUnsignedShort(strokes, returnFixedSize);
}
@ -183,7 +193,7 @@ public class MedtronicUtil {
} else {
sendPayloadBuffer.put((byte) parameters.length); // size
for(byte val : parameters) {
for (byte val : parameters) {
sendPayloadBuffer.put(val);
}
}
@ -203,14 +213,6 @@ public class MedtronicUtil {
// FIXME
public static MedtronicDeviceType getDeviceType() {
return deviceType;
}
public static void setDeviceType(MedtronicDeviceType deviceType) {
MedtronicUtil.deviceType = deviceType;
}
public static boolean isLowLevelDebug() {
@ -221,4 +223,67 @@ public class MedtronicUtil {
public static void setLowLevelDebug(boolean lowLevelDebug) {
MedtronicUtil.lowLevelDebug = lowLevelDebug;
}
public static void setPumpDeviceState(PumpDeviceState pumpDeviceState) {
MedtronicUtil.pumpDeviceState = pumpDeviceState;
MainApp.bus().post(new EventMedtronicDeviceStatusChange(pumpDeviceState));
}
public static PumpDeviceState getPumpDeviceState() {
return pumpDeviceState;
}
// TODO MOVE
public static boolean isModelSet() {
return MedtronicUtil.medtronicPumpModel != null;
}
public static void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) {
if (medtronicPumpModel != null && medtronicPumpModel != MedtronicDeviceType.Unknown_Device) {
MedtronicUtil.medtronicPumpModel = medtronicPumpModel;
}
}
public static MedtronicDeviceType getMedtronicPumpModel() {
return MedtronicUtil.medtronicPumpModel;
}
public static MedtronicCommunicationManager getMedtronicCommunicationManager() {
return (MedtronicCommunicationManager) RileyLinkUtil.rileyLinkCommunicationManager;
}
public static RileyLinkMedtronicService getMedtronicService() {
return MedtronicUtil.medtronicService;
}
public static void setMedtronicService(RileyLinkMedtronicService medtronicService) {
MedtronicUtil.medtronicService = medtronicService;
}
public static void setPumpStatus(MedtronicPumpStatus medtronicPumpStatus) {
MedtronicUtil.medtronicPumpStatus = medtronicPumpStatus;
}
public static MedtronicPumpStatus getPumpStatus() {
return MedtronicUtil.medtronicPumpStatus;
}
public static void setCurrentCommand(MedtronicCommandType currentCommand) {
MedtronicUtil.currentCommand = currentCommand;
}
public static MedtronicCommandType getCurrectCommand() {
return MedtronicUtil.currentCommand;
}
public static boolean isSame(Double d1, Double d2) {
double diff = d1 - d2;
return (Math.abs(diff) <= 0.000001);
}
}

View file

@ -110,7 +110,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
public void connect(String reason) {
if (!Config.NSCLIENT && !Config.G5UPLOADER)
NSUpload.uploadDeviceStatus();
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
}
@Override
@ -123,12 +123,12 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
@Override
public void getPumpStatus() {
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
}
@Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
// Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile();
PumpEnactResult result = new PumpEnactResult();
result.success = true;
@ -185,7 +185,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
if (Config.logPumpComm)
LOG.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo);
return result;
}
@ -215,7 +215,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
if (Config.logPumpComm)
LOG.debug("Setting temp basal absolute: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
return result;
}
@ -244,7 +244,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
if (Config.logPumpComm)
LOG.debug("Settings temp basal percent: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
return result;
}
@ -269,7 +269,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
if (Config.logPumpComm)
LOG.debug("Setting extended bolus: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
return result;
}
@ -289,7 +289,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
LOG.debug("Canceling temp basal: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
}
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
return result;
}
@ -309,7 +309,7 @@ public class VirtualPumpDriver extends PumpDriverAbstract {
if (Config.logPumpComm)
LOG.debug("Canceling extended basal: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastDataTimeToNow();
pumpStatusData.setLastCommunicationToNow();
return result;
}

View file

@ -15,6 +15,7 @@
android:layout_above="@+id/medtronic_buttons"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -30,7 +31,7 @@
android:visibility="gone">
<TextView
android:id="@+id/overview_pumpstatus"
android:id="@+id/overview_pump_medtronic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
@ -58,10 +59,10 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/danar_bluetooth_status"
android:text="@string/rileylink_status"
android:textSize="14sp" />
<TextView
@ -75,7 +76,7 @@
android:textSize="14sp" />
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/medtronic_btconnection"
android:id="@+id/medtronic_rl_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
@ -83,7 +84,55 @@
android:paddingLeft="5dp"
android:text="{fa-bluetooth-b}"
android:textColor="@android:color/white"
android:textSize="20dp" />
android:textSize="14sp" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="5dp"
android:background="@color/listdelimiter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/medtronic_pump_status"
android:textSize="14sp" />
<TextView
android:layout_width="5dp"
android:layout_height="wrap_content"
android:layout_weight="0"
android:gravity="center_horizontal"
android:paddingEnd="2dp"
android:paddingStart="2dp"
android:text=":"
android:textSize="14sp" />
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/medtronic_pump_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:paddingLeft="5dp"
android:text="{fa-bluetooth-b}"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
@ -112,7 +161,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/pump_battery_label"
@ -129,14 +178,15 @@
android:textSize="14sp" />
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/medtronic_battery"
android:id="@+id/medtronic_pumpstate_battery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:paddingLeft="5dp"
android:textColor="@android:color/white"
android:textSize="20dp" />
android:text=""
android:textSize="14sp" />
</LinearLayout>
@ -158,7 +208,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/pump_lastconnection_label"
@ -203,7 +253,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/pump_lastbolus_label"
@ -249,7 +299,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/pump_basebasalrate_label"
@ -294,7 +344,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/pump_tempbasal_label"
@ -340,7 +390,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/pump_reservoir_label"
@ -368,51 +418,6 @@
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginBottom="5dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="5dp"
android:background="@color/listdelimiter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/danar_iob_label"
android:textSize="14sp" />
<TextView
android:layout_width="5dp"
android:layout_height="wrap_content"
android:layout_weight="0"
android:gravity="center_horizontal"
android:paddingEnd="2dp"
android:paddingStart="2dp"
android:text=":"
android:textSize="14sp" />
<TextView
android:id="@+id/medtronic_iob"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="start"
android:paddingLeft="5dp"
android:textColor="@android:color/white"
android:textSize="14sp" />
</LinearLayout>
<View
android:layout_width="fill_parent"
@ -431,7 +436,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_weight="1.5"
android:gravity="end"
android:paddingRight="5dp"
android:text="@string/medtronic_errors"

View file

@ -1101,9 +1101,28 @@
<string name="rileylink_last_used_frequency">Last used frequency</string>
<string name="rileylink_last_device_contact">Last device contact</string>
<string name="rileylink_settings_tab1">Settings</string>
<string name="rileylink_settings_tab2">History</string>
<string name="rileylink_status">RileyLink Status</string>
<string name="medtronic_pump_status">Pump Status</string>
<string name="rileylink_state_bt_init">Bluetooth Initializing…</string>
<string name="rileylink_state_bt_error">Bluetooth Error</string>
<string name="rileylink_state_bt_ready">Bluetooth Ready</string>
<string name="rileylink_state_not_started">Not Started</string>
<string name="rileylink_state_rl_init">RileyLink Initialization…</string>
<string name="rileylink_state_rl_error">RileyLink Error</string>
<string name="rileylink_state_pc_tune_up">Tunning up RileyLink and Pump</string>
<string name="rileylink_state_pc_error">Problem connecting to Pump</string>
<string name="rileylink_state_connected">Connected</string>
<string name="rileylink_error_not_rl">Device is not RileyLink</string>
<string name="rileylink_error_unreachable">RileyLink unreachable</string>
<string name="rileylink_error_bt_disabled">Bluetooth disabled</string>
<string name="rileylink_error_no_bt_adapter">No Bluetooth Adapter</string>
<string name="rileylink_error_tuneup_failed">TuneUp Failed</string>
<string name="rileylink_error_pump_unreachable">Pump unreachable</string>
<string name="rileylink_error_pod_unreachable">Pod unreachable</string>
<string name="medtronic_cmd_profile_not_set">Remote Basal profile setting is not supported. Please modify Basal profile on your pump manually.</string>
</resources>

View file

@ -53,7 +53,7 @@
android:defaultValue="xx:xx:xx:xx:xx:xx"
android:editable="false"
android:inputType="textFilter"
android:key="pref_medtronic_rileylink_mac"
android:key="pref_rileylink_mac_address"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/rileylink_mac_address" />

View file

@ -0,0 +1,54 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data.dto;
import junit.framework.Assert;
import org.junit.Test;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/**
* Created by andy on 6/16/18.
*/
public class BasalProfileUTest {
@Test
public void getProfilesByHour() throws Exception {
BasalProfile basalProfile = new BasalProfile();
byte[] data = { //
0x48, 0x00, 0x00, 0x40, 0x00, 0x02, 0x38, 0x00, 0x04, 0x3A, 0x00, 0x06, 0x32, 0x00, 0x0C, 0x26, 0x00, //
0x10, 0x2E, 0x00, 0x14, 0x32, 0x00, 0x18, 0x26, 0x00, 0x1A, 0x1A, 0x00, 0x20, 0x14, 0x00, 0x2A, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
basalProfile.setRawData(data);
Double[] profilesByHour = basalProfile.getProfilesByHour();
Assert.assertTrue(MedtronicUtil.isSame(1.8d, profilesByHour[0]));
Assert.assertTrue(MedtronicUtil.isSame(1.6d, profilesByHour[1]));
Assert.assertTrue(MedtronicUtil.isSame(1.4d, profilesByHour[2]));
Assert.assertTrue(MedtronicUtil.isSame(1.45d, profilesByHour[3]));
Assert.assertTrue(MedtronicUtil.isSame(1.45d, profilesByHour[4]));
Assert.assertTrue(MedtronicUtil.isSame(1.45d, profilesByHour[5]));
Assert.assertTrue(MedtronicUtil.isSame(1.25d, profilesByHour[6]));
Assert.assertTrue(MedtronicUtil.isSame(1.25d, profilesByHour[7]));
Assert.assertTrue(MedtronicUtil.isSame(0.95d, profilesByHour[8]));
Assert.assertTrue(MedtronicUtil.isSame(0.95d, profilesByHour[9]));
Assert.assertTrue(MedtronicUtil.isSame(1.15d, profilesByHour[10]));
Assert.assertTrue(MedtronicUtil.isSame(1.15d, profilesByHour[11]));
Assert.assertTrue(MedtronicUtil.isSame(1.25d, profilesByHour[12]));
Assert.assertTrue(MedtronicUtil.isSame(0.95d, profilesByHour[13]));
Assert.assertTrue(MedtronicUtil.isSame(0.95d, profilesByHour[14]));
Assert.assertTrue(MedtronicUtil.isSame(0.95d, profilesByHour[15]));
Assert.assertTrue(MedtronicUtil.isSame(0.65d, profilesByHour[16]));
Assert.assertTrue(MedtronicUtil.isSame(0.65d, profilesByHour[17]));
Assert.assertTrue(MedtronicUtil.isSame(0.65d, profilesByHour[18]));
Assert.assertTrue(MedtronicUtil.isSame(0.65d, profilesByHour[19]));
Assert.assertTrue(MedtronicUtil.isSame(0.65d, profilesByHour[20]));
Assert.assertTrue(MedtronicUtil.isSame(0.5d, profilesByHour[21]));
Assert.assertTrue(MedtronicUtil.isSame(0.5d, profilesByHour[22]));
Assert.assertTrue(MedtronicUtil.isSame(0.5d, profilesByHour[23]));
}
}