From 318436f4176d5dc0171b3df1326443b0b98ee9b1 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Thu, 26 Jul 2018 16:31:23 +0100 Subject: [PATCH] - some changes from RileyLinkAAPS project: - refactored RfSpy and underlaying classes so that we can read Version (which is not encoded and has no CRC) - added functionality to be able to recover RL if BT is disabled and re-enabled - some minor refactorings here and there - TBR enabled - Bolus delivery - Medtronic Pump Plugin is working (able to deliver TBRs and Bolus), there are still a lot of things to work on but we have base implementation here... --- .../info/nightscout/androidaps/MainApp.java | 48 ++- .../PumpCommon/PumpPluginAbstract.java | 8 + .../plugins/PumpCommon/defs/PumpType.java | 13 +- .../dialog/RileyLinkSettingsTab1.java | 5 +- .../RileyLinkCommunicationManager.java | 82 ++---- .../hw/rileylink/RileyLinkConst.java | 17 +- .../hw/rileylink/RileyLinkUtil.java | 34 +-- .../PumpCommon/hw/rileylink/ble/RFSpy.java | 86 +++--- .../PumpCommon/hw/rileylink/ble/RFTools.java | 28 +- .../hw/rileylink/ble/RileyLinkBLE.java | 13 +- .../hw/rileylink/ble/data/GattAttributes.java | 19 +- .../hw/rileylink/ble/data/RFSpyResponse.java | 21 +- .../hw/rileylink/ble/data/RLMessage.java | 2 + .../hw/rileylink/ble/data/RadioResponse.java | 40 ++- .../hw/rileylink/ble/defs/RFSpyCommand.java | 18 +- .../hw/rileylink/ble/defs/RLMessage.java | 10 - .../ble/defs/RileyLinkTargetDevice.java | 11 - .../ble/defs/RileyLinkTargetFrequency.java | 12 +- .../hw/rileylink/defs/RileyLinkError.java | 2 +- .../rileylink/defs/RileyLinkServiceState.java | 2 +- .../rileylink/defs/RileyLinkTargetDevice.java | 15 +- .../rileylink/service/RileyLinkService.java | 144 ++++----- .../service/RileyLinkServiceData.java | 6 + .../tasks/DiscoverGattServicesTask.java | 12 + .../tasks/InitializePumpManagerTask.java | 4 +- .../service/tasks/ServiceTaskExecutor.java | 4 + .../service/tasks/WakeAndTuneTask.java | 4 +- .../PumpMedtronic/MedtronicFragment.java | 45 ++- .../PumpMedtronic/MedtronicPumpPlugin.java | 277 ++++++++++-------- .../comm/MedtronicCommunicationManager.java | 56 ++++ .../comm/message/MedtronicConverter.java | 12 +- .../comm/message/PumpMessage.java | 4 +- .../comm/ui/MedtronicUIPostprocessor.java | 43 ++- .../comm/ui/MedtronicUITask.java | 3 +- .../defs/MedtronicCommandType.java | 1 + .../driver/MedtronicPumpStatus.java | 20 +- .../service/RileyLinkMedtronicService.java | 16 +- .../PumpMedtronic/util/MedtronicConst.java | 8 +- .../main/res/layout/medtronic_fragment.xml | 7 +- app/src/main/res/values/strings.xml | 56 ++-- 40 files changed, 682 insertions(+), 526 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index e2dc53d79d..c7ea215d19 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -1,11 +1,16 @@ package info.nightscout.androidaps; import android.app.Application; +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.SystemClock; import android.support.annotation.Nullable; import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; import com.crashlytics.android.Crashlytics; import com.crashlytics.android.answers.Answers; @@ -47,13 +52,13 @@ import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.OpenAPSMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSSMB.OpenAPSSMBPlugin; import info.nightscout.androidaps.plugins.Overview.OverviewPlugin; -import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Persistentnotification.PersistentNotificationPlugin; import info.nightscout.androidaps.plugins.ProfileLocal.LocalProfilePlugin; import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin; import info.nightscout.androidaps.plugins.ProfileSimple.SimpleProfilePlugin; import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin; import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; @@ -100,6 +105,7 @@ public class MainApp extends Application { private static NSAlarmReceiver alarmReciever = new NSAlarmReceiver(); private static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver(); private LocalBroadcastManager lbm; + private BroadcastReceiver btReceiver; // used for RileyLink (Medtronic and Omnipod) public static boolean devBranch; public static boolean engineeringMode; @@ -137,6 +143,8 @@ public class MainApp extends Application { registerLocalBroadcastReceiver(); + setBTReceiver(); + if (pluginsList == null) { pluginsList = new ArrayList<>(); // Register all tabs in app here @@ -240,6 +248,37 @@ public class MainApp extends Application { lbm.registerReceiver(ackAlarmReciever, new IntentFilter(Intents.ACTION_ACK_ALARM)); } + private void setBTReceiver() { + + // RileyLink framework needs to know, when BT was reconnected, so that we can reconnect to RL device + btReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); + switch (state) { + case BluetoothAdapter.STATE_OFF: + case BluetoothAdapter.STATE_TURNING_OFF: + case BluetoothAdapter.STATE_TURNING_ON: + break; + + case BluetoothAdapter.STATE_ON: + Log.v("MainApp", "Bluetooth on"); + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothReconnected); + break; + } + } + } + }; + + // Register for broadcasts on BluetoothAdapter state change + IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); + registerReceiver(btReceiver, filter); + + } + private void startKeepAliveService() { if (keepAliveReceiver == null) { keepAliveReceiver = new KeepAliveReceiver(); @@ -404,5 +443,10 @@ public class MainApp extends Application { sDatabaseHelper.close(); sDatabaseHelper = null; } + + if (btReceiver != null) { + unregisterReceiver(btReceiver); + } } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/PumpPluginAbstract.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/PumpPluginAbstract.java index ca1799d139..fae1d634f6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/PumpPluginAbstract.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/PumpPluginAbstract.java @@ -466,6 +466,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter bolusingEvent.percent = 100; MainApp.bus().post(bolusingEvent); + LOG.debug("deliverTreatment: Carb only treatment."); + return new PumpEnactResult().success(true).enacted(true) .bolusDelivered(0d).carbsDelivered(detailedBolusInfo.carbs) .comment(MainApp.gs(R.string.virtualpump_resultok)); @@ -483,6 +485,12 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter protected abstract void triggerUIChange(); + public PumpEnactResult getOperationNotSupportedWithCustomText(int resourceId) { + return new PumpEnactResult() + .success(false).enacted(false).comment(MainApp.gs(resourceId)); + } + + // Profile interface // @Nullable diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java index 440bb0a63e..0fbc5663e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java @@ -84,25 +84,24 @@ public enum PumpType { 0.05f, 0.05f, null, PumpCapability.VirtualPump), // Medtronic - Minimed_512_712("Medtronic 512/712", 0.05f, null, // + Medtronic_512_712("Medtronic 512/712", 0.05f, null, // new DoseSettings(0.05f, 30, 8 * 60, 0.05f), // PumpTempBasalType.Absolute, // new DoseSettings(0.05f, 30, 24 * 60, 0f, 35f), // 0.05f, 0.05f, null, PumpCapability.VirtualPump), // TODO - Minimed_515_715("Medtronic 515/715", Minimed_512_712), - Minimed_522_722("Medtronic 522/722", Minimed_512_712), - Minimed_523_723("Medtronic 523/723", Minimed_512_712), + Medtronic_515_715("Medtronic 515/715", Medtronic_512_712), + Medtronic_522_722("Medtronic 522/722", Medtronic_512_712), - Minimed_553_753_Revel("Medtronic 553/753 (Revel)", 0.05f, null, // + Medtronic_523_723_Revel("Medtronic 553/753 (Revel)", 0.05f, null, // new DoseSettings(0.05f, 30, 8 * 60, 0.05f), // PumpTempBasalType.Absolute, // new DoseSettings(0.05f, 30, 24 * 60, 0f, 35f), // 0.025f, 0.025f, DoseStepSize.MedtronicVeoBasal, PumpCapability.VirtualPump), // - Minimed_554_754_Veo("Medtronic 554/754 (Veo)", Minimed_553_753_Revel), // TODO + Medtronic_554_754_Veo("Medtronic 554/754 (Veo)", Medtronic_523_723_Revel), // TODO - Minimed_640G("Medtronic 640G", 0.025f, null, // + Medtronic_640G("Medtronic 640G", 0.025f, null, // new DoseSettings(0.05f, 30, 8 * 60, 0.05f), // PumpTempBasalType.Absolute, // new DoseSettings(0.05f, 30, 24 * 60, 0f, 35f), // diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java index 79fa03509f..207255f395 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/dialog/RileyLinkSettingsTab1.java @@ -9,9 +9,10 @@ import android.widget.TextView; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetDevice; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData; import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus; +import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil; /** * Created by andy on 5/19/18. @@ -92,7 +93,7 @@ public class RileyLinkSettingsTab1 extends Fragment implements RefreshableInterf this.connectionError.setText(rileyLinkServiceData.errorCode == null ? "-" : rileyLinkServiceData.errorCode.name()); - this.medtronicPumpStatus = RileyLinkUtil.getPumpStatus(); + this.medtronicPumpStatus = MedtronicUtil.getPumpStatus(); if (medtronicPumpStatus != null) { this.deviceType.setText(RileyLinkTargetDevice.MedtronicPump.name()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java index c7bbc9903d..531957a39e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkCommunicationManager.java @@ -10,18 +10,16 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.FrequencyScanResults; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.FrequencyTrial; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioPacket; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioResponse; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessage; 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.hw.rileylink.defs.RileyLinkError; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; 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; @@ -66,26 +64,29 @@ public abstract class RileyLinkCommunicationManager { protected abstract void configurePumpSpecificSettings(); - protected PumpMessage sendAndListen(RLMessage msg) { - return sendAndListen(msg, 4000); // 2000 - } + // protected PumpMessage sendAndListen(RLMessage msg) { + // return sendAndListen(msg, 4000); // 2000 + // } private int timeoutCount = 0; // All pump communications go through this function. - protected PumpMessage sendAndListen(RLMessage msg, int timeout_ms) { + protected E sendAndListen(RLMessage msg, int timeout_ms, Class clazz) { if (showPumpMessages) { LOG.info("Sent:" + ByteUtil.shortHexString(msg.getTxData())); } RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), timeout_ms); - PumpMessage rval = new PumpMessage(rfSpyResponse.getRadioResponse().getPayload()); - if (rval.isValid()) { + + E response = createResponseMessage(rfSpyResponse.getRadioResponse().getPayload(), clazz); + + //PumpMessage rval = new PumpMessage(resp.getRadioResponse().getPayload()); + if (response.isValid()) { // Mark this as the last time we heard from the pump. - rememberLastGoodPumpCommunicationTime(); + rememberLastGoodDeviceCommunicationTime(); } else { LOG.warn("Response is invalid. !!! - ", rfSpyResponse.wasInterrupted(), rfSpyResponse.wasTimeout()); @@ -95,7 +96,7 @@ public abstract class RileyLinkCommunicationManager { if (timeoutCount >= 5) { RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.NoContactWithDevice); timeoutCount = 0; - tuneForPump(); + tuneForDevice(); //RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_quickTune); } } @@ -105,48 +106,19 @@ public abstract class RileyLinkCommunicationManager { if (showPumpMessages) { LOG.info("Received:" + ByteUtil.shortHexString(rfSpyResponse.getRadioResponse().getPayload())); } - return rval; + return response; } - // /** - // * For set commands we use this method (it just sends data and returns ACK or NAK) - // * - // * @param msg - // * @param timeoutMs - // * @return - // */ - // protected PumpMessage send(RLMessage msg, int timeoutMs) { - // - // // FIXME untested - // if (showPumpMessages) { - // LOG.info("Sent:" + ByteUtil.shortHexString(msg.getTxData())); - // } - // - // RFSpyResponse resp = rfspy.transmit(new RadioPacket(msg.getTxData())); - // PumpMessage rval = new PumpMessage(resp.getRadioResponse().getPayload()); - // if (rval.isValid()) { - // // Mark this as the last time we heard from the pump. - // rememberLastGoodPumpCommunicationTime(); - // } else { - // LOG.warn("Response is invalid. !!!"); - // } - // - // if (showPumpMessages) { - // LOG.info("Received:" + ByteUtil.shortHexString(resp.getRadioResponse().getPayload())); - // } - // return rval; - // } + public abstract E createResponseMessage(byte[] payload, Class clazz); public void wakeUp(boolean force) { wakeUp(receiverDeviceAwakeForMinutes, force); - - } - long nextWakeUpRequired = 0L; + private long nextWakeUpRequired = 0L; public int getNotConnectedCount() { @@ -200,20 +172,24 @@ public abstract class RileyLinkCommunicationManager { } - public double tuneForPump() { - return scanForPump(scanFrequencies); + public double tuneForDevice() { + return scanForDevice(scanFrequencies); } /** * If user changes pump and one pump is running in US freq, and other in WW, then previously set frequency would be invalid, - * so we would need to retune. This checks that saved frequency is corrent range. + * so we would need to retune. This checks that saved frequency is correct range. * * @param frequency * @return */ public boolean isValidFrequency(double frequency) { - return (this.scanFrequencies[0] <= frequency && this.scanFrequencies[scanFrequencies.length - 1] >= frequency); + if (scanFrequencies.length == 1) { + return RileyLinkUtil.isSame(scanFrequencies[0], frequency); + } else { + return (this.scanFrequencies[0] <= frequency && this.scanFrequencies[scanFrequencies.length - 1] >= frequency); + } } @@ -226,7 +202,7 @@ public abstract class RileyLinkCommunicationManager { // FIXME sorting, and time display - public double scanForPump(double[] frequencies) { + public double scanForDevice(double[] frequencies) { LOG.info("Scanning for receiver ({})", receiverDeviceID); wakeUp(receiverDeviceAwakeForMinutes, false); FrequencyScanResults results = new FrequencyScanResults(); @@ -241,7 +217,7 @@ public abstract class RileyLinkCommunicationManager { 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, 1500, (byte) 0); + RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 0, (byte) 0, (byte) 0, rfspy.EXPECTED_MAX_BLUETOOTH_LATENCY_MS, (byte) 0); if (resp.wasTimeout()) { LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]); } else if (resp.looksLikeRadioPacket()) { @@ -370,18 +346,18 @@ public abstract class RileyLinkCommunicationManager { } - private void rememberLastGoodPumpCommunicationTime() { + protected void rememberLastGoodDeviceCommunicationTime() { lastGoodReceiverCommunicationTime = System.currentTimeMillis(); - SP.putLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, lastGoodReceiverCommunicationTime); - MedtronicUtil.getPumpStatus().setLastCommunicationToNow(); + SP.putLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, lastGoodReceiverCommunicationTime); + pumpStatus.setLastCommunicationToNow(); } private long getLastGoodReceiverCommunicationTime() { // If we have a value of zero, we need to load from prefs. if (lastGoodReceiverCommunicationTime == 0L) { - lastGoodReceiverCommunicationTime = SP.getLong(MedtronicConst.Statistics.LastGoodPumpCommunicationTime, 0L); + lastGoodReceiverCommunicationTime = SP.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); // Might still be zero, but that's fine. } double minutesAgo = (System.currentTimeMillis() - lastGoodReceiverCommunicationTime) / (1000.0 * 60.0); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java index 0817a3bb2f..4066e5aaa2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkConst.java @@ -12,9 +12,10 @@ public class RileyLinkConst { public static final String RileyLinkReady = Prefix + "RileyLink_Ready"; public static final String RileyLinkGattFailed = Prefix + "RileyLink_Gatt_Failed"; - public static final String RileyLinkError = Prefix + "RileyLink_Ready"; + //public static final String RileyLinkError = Prefix + "RileyLink_Ready"; public static final String BluetoothConnected = Prefix + "Bluetooth_Connected"; + public static final String BluetoothReconnected = Prefix + "Bluetooth_Reconnected"; public static final String BluetoothDisconnected = Prefix + "Bluetooth_Disconnected"; public static final String RileyLinkDisconnected = Prefix + "RileyLink_Disconnected"; @@ -24,6 +25,15 @@ public class RileyLinkConst { public static final String INTENT_NEW_pumpIDKey = Prefix + "INTENT_NEW_pumpIDKey"; } + public class Prefs { + + public static final String PrefPrefix = "pref_rileylink_"; + public static final String RileyLinkAddress = PrefPrefix + "mac_address"; + + public static final String LastGoodDeviceCommunicationTime = Prefix + "lastGoodDeviceCommunicationTime"; + public static final String LastGoodDeviceFrequency = Prefix + "LastGoodDeviceFrequency"; + } + public class IPC { // needs to br renamed (and maybe removed) public static final String MSG_PUMP_quickTune = Prefix + "MSG_PUMP_quickTune"; @@ -34,9 +44,4 @@ 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"; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java index 4bd9f7052c..00d012ca36 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/RileyLinkUtil.java @@ -23,7 +23,6 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.S import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; 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; @@ -46,7 +45,7 @@ public class RileyLinkUtil { //private static RileyLinkIPCConnection rileyLinkIPCConnection; private static MedtronicDeviceType medtronicPumpModel; private static RileyLinkTargetFrequency rileyLinkTargetFrequency; - private static MedtronicPumpStatus pumpStatus; + //private static MedtronicPumpStatus pumpStatus; // BAD dependencies in Classes: RileyLinkService // Broadcasts: RileyLinkBLE, RileyLinkService, @@ -109,32 +108,11 @@ public class RileyLinkUtil { } -// public static void setMedtronicPumpStatus(MedtronicPumpStatus medtronicPumpStatus) { -// -// RileyLinkUtil.medtronicPumpStatus = medtronicPumpStatus; -// } - - // public static void addHistoryEntry(RLHistoryItem rlHistoryItem) { - // historyRileyLink.add(rlHistoryItem); - // } - - -// public static MedtronicPumpStatus getMedtronicPumpStatus() { -// -// return RileyLinkUtil.medtronicPumpStatus; -// } - - public static boolean hasPumpBeenTunned() { return RileyLinkUtil.rileyLinkServiceData.tuneUpDone; } - public static void tuneUpPump() { - RileyLinkUtil.rileyLinkService.doTunePump(); // FIXME thread - } - - public static void setRileyLinkService(RileyLinkService rileyLinkService) { RileyLinkUtil.rileyLinkService = rileyLinkService; } @@ -156,7 +134,7 @@ public class RileyLinkUtil { public static boolean sendNotification(ServiceNotification notification, Integer clientHashcode) { - return rileyLinkService.sendNotification(notification, clientHashcode); + return RileyLinkUtil.rileyLinkService.sendNotification(notification, clientHashcode); } @@ -211,7 +189,11 @@ public class RileyLinkUtil { return RileyLinkUtil.rileyLinkTargetFrequency; } - public static MedtronicPumpStatus getPumpStatus() { - return RileyLinkUtil.pumpStatus; + + public static boolean isSame(Double d1, Double d2) { + double diff = d1 - d2; + + return (Math.abs(diff) <= 0.000001); } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java index ea46a06931..5077f93e3d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFSpy.java @@ -36,7 +36,6 @@ public class RFSpy { private RileyLinkBLE rileyLinkBle; private RFSpyReader reader; - //private int previousRegion = 0; private RileyLinkTargetFrequency selectedTargetFrequency; private UUID radioServiceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO); @@ -47,7 +46,6 @@ public class RFSpy { public RFSpy(RileyLinkBLE rileyLinkBle) { this.rileyLinkBle = rileyLinkBle; - //this.rileyLinkBle.setRFSpy(this); reader = new RFSpyReader(rileyLinkBle); } @@ -74,9 +72,34 @@ public class RFSpy { public int notConnectedCount = 0; + // This gets the version from the BLE113, not from the CC1110. + // I.e., this gets the version from the BLE interface, not from the radio. + public String getVersion() { + BLECommOperationResult result = rileyLinkBle.readCharacteristic_blocking(radioServiceUUID, radioVersionUUID); + if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { + return StringUtil.fromBytes(result.value); + } else { + LOG.error("getVersion failed with code: " + result.resultCode); + return "(null)"; + } + } + + public String getRadioVersion() { + RFSpyResponse resp = writeToData(RFSpyCommand.GetVersion, null, EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + if (resp == null) { + LOG.error("getRadioVersion returned null"); + return "(null)"; + } else { + return StringUtil.fromBytes(resp.getRadioResponse().decodedPayload); + } + } + // The caller has to know how long the RFSpy will be busy with what was sent to it. - private RFSpyResponse writeToData(byte[] bytes, int responseTimeout_ms) { + private RFSpyResponse writeToData(RFSpyCommand command, byte[] body, int responseTimeout_ms) { + + byte[] bytes = getCommandArray(command, body); + SystemClock.sleep(100); // FIXME drain read queue? byte[] junkInBuffer = reader.poll(0); @@ -96,7 +119,7 @@ public class RFSpy { SystemClock.sleep(100); //Log.i(TAG,ThreadUtil.sig()+String.format(" writeToData:(timeout %d) %s",(responseTimeout_ms),ByteUtil.shortHexString(prepended))); byte[] rawResponse = reader.poll(responseTimeout_ms); - RFSpyResponse resp = new RFSpyResponse(rawResponse); + RFSpyResponse resp = new RFSpyResponse(command, rawResponse); if (rawResponse == null) { LOG.error("writeToData: No response from RileyLink"); notConnectedCount++; @@ -108,11 +131,13 @@ public class RFSpy { notConnectedCount++; } else if (resp.isOK()) { LOG.warn("writeToData: RileyLink reports OK"); + resetNotConnectedCount(); } else { if (resp.looksLikeRadioPacket()) { RadioResponse radioResp = resp.getRadioResponse(); byte[] responsePayload = radioResp.getPayload(); LOG.info("writeToData: decoded radio response is " + ByteUtil.shortHexString(responsePayload)); + resetNotConnectedCount(); } //Log.i(TAG, "writeToData: raw response is " + ByteUtil.shortHexString(rawResponse)); } @@ -120,10 +145,15 @@ public class RFSpy { return resp; } + private void resetNotConnectedCount() { + this.notConnectedCount = 0; + } + private byte[] getByteArray(byte... input) { return input; } + private byte[] getCommandArray(RFSpyCommand command, byte[] body) { int bodyLength = body == null ? 0 : body.length; @@ -141,36 +171,6 @@ public class RFSpy { } - // This gets the version from the BLE113, not from the CC1110. - // I.e., this gets the version from the BLE interface, not from the radio. - public String getVersion() { - BLECommOperationResult result = rileyLinkBle.readCharacteristic_blocking(radioServiceUUID, radioVersionUUID); - if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) { - return StringUtil.fromBytes(result.value); - } else { - LOG.error("getVersion failed with code: " + result.resultCode); - return "(null)"; - } - } - - public RFSpyResponse getRadioVersion() { - RFSpyResponse resp = writeToData(getCommandArray(RFSpyCommand.GetVersion, null), EXPECTED_MAX_BLUETOOTH_LATENCY_MS); - if (resp == null) { - LOG.error("getRadioVersion returned null"); - } - /* - Log.d(TAG,"checking response count"); - BLECommOperationResult checkRC = rileyLinkBle.readCharacteristic_blocking(radioServiceUUID,responseCountUUID); - if (checkRC.resultCode == BLECommOperationResult.RESULT_SUCCESS) { - Log.d(TAG,"Response count is: " + ByteUtil.shortHexString(checkRC.value)); - } else { - LOG.error("Error getting response count, code is " + checkRC.resultCode); - } - */ - return resp; - } - - public RFSpyResponse transmit(RadioPacket radioPacket) { return transmit(radioPacket, (byte) 0, (byte) 0, (byte) 0xFF); @@ -179,16 +179,16 @@ public class RFSpy { public RFSpyResponse transmit(RadioPacket radioPacket, byte sendChannel, byte repeatCount, byte delay_ms) { // append checksum, encode data, send it. - byte[] fullPacket = ByteUtil.concat(getCommandArray(RFSpyCommand.Send, getByteArray(sendChannel, repeatCount, delay_ms)), radioPacket.getEncoded()); - RFSpyResponse response = writeToData(fullPacket, delay_ms + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + byte[] fullPacket = ByteUtil.concat(getByteArray(sendChannel, repeatCount, delay_ms), radioPacket.getEncoded()); + RFSpyResponse response = writeToData(RFSpyCommand.Send, fullPacket, delay_ms + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); return response; } public RFSpyResponse receive(byte listenChannel, int timeout_ms, byte retryCount) { int receiveDelay = timeout_ms * (retryCount + 1); - byte[] listen = getCommandArray(RFSpyCommand.GetPacket, getByteArray(listenChannel, (byte) ((timeout_ms >> 24) & 0x0FF), (byte) ((timeout_ms >> 16) & 0x0FF), (byte) ((timeout_ms >> 8) & 0x0FF), (byte) (timeout_ms & 0x0FF), retryCount)); - return writeToData(listen, receiveDelay); + byte[] listen = getByteArray(listenChannel, (byte) ((timeout_ms >> 24) & 0x0FF), (byte) ((timeout_ms >> 16) & 0x0FF), (byte) ((timeout_ms >> 8) & 0x0FF), (byte) (timeout_ms & 0x0FF), retryCount); + return writeToData(RFSpyCommand.GetPacket, listen, receiveDelay); } @@ -201,15 +201,15 @@ public class RFSpy { int sendDelay = repeatCount * delay_ms; int receiveDelay = timeout_ms * (retryCount + 1); - byte[] sendAndListen = getCommandArray(RFSpyCommand.SendAndListen, getByteArray(sendChannel, repeatCount, delay_ms, listenChannel, (byte) ((timeout_ms >> 24) & 0x0FF), (byte) ((timeout_ms >> 16) & 0x0FF), (byte) ((timeout_ms >> 8) & 0x0FF), (byte) (timeout_ms & 0x0FF), (byte) retryCount)); + byte[] sendAndListen = getByteArray(sendChannel, repeatCount, delay_ms, listenChannel, (byte) ((timeout_ms >> 24) & 0x0FF), (byte) ((timeout_ms >> 16) & 0x0FF), (byte) ((timeout_ms >> 8) & 0x0FF), (byte) (timeout_ms & 0x0FF), (byte) retryCount); byte[] fullPacket = ByteUtil.concat(sendAndListen, pkt.getEncoded()); - return writeToData(fullPacket, sendDelay + receiveDelay + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + return writeToData(RFSpyCommand.SendAndListen, fullPacket, sendDelay + receiveDelay + EXPECTED_MAX_BLUETOOTH_LATENCY_MS); } public RFSpyResponse updateRegister(CC111XRegister reg, int val) { - byte[] updateRegisterPkt = getCommandArray(RFSpyCommand.UpdateRegister, getByteArray(reg.value, (byte) val)); - RFSpyResponse resp = writeToData(updateRegisterPkt, EXPECTED_MAX_BLUETOOTH_LATENCY_MS); + byte[] updateRegisterPkt = getByteArray(reg.value, (byte) val); + RFSpyResponse resp = writeToData(RFSpyCommand.UpdateRegister, updateRegisterPkt, EXPECTED_MAX_BLUETOOTH_LATENCY_MS); return resp; } @@ -233,7 +233,6 @@ public class RFSpy { switch (frequency) { case Medtronic_WorldWide: { - //updateRegister(CC111X_MDMCFG4, (byte) 0x59); setRXFilterMode(RXFilterMode.Wide); //updateRegister(CC111X_MDMCFG3, (byte) 0x66); //updateRegister(CC111X_MDMCFG2, (byte) 0x33); @@ -244,7 +243,6 @@ public class RFSpy { break; case Medtronic_US: { - //updateRegister(CC111X_MDMCFG4, (byte) 0x99); setRXFilterMode(RXFilterMode.Narrow); //updateRegister(CC111X_MDMCFG3, (byte) 0x66); //updateRegister(CC111X_MDMCFG2, (byte) 0x33); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java index 8a216f6553..45d401f3c0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RFTools.java @@ -23,24 +23,8 @@ public class RFTools { to communicate with a Medtronic pump. */ - public static byte[] CodeSymbols = { - 0x15, - 0x31, - 0x32, - 0x23, - 0x34, - 0x25, - 0x26, - 0x16, - 0x1a, - 0x19, - 0x2a, - 0x0b, - 0x2c, - 0x0d, - 0x0e, - 0x1c - }; + public static byte[] CodeSymbols = {0x15, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x16, 0x1a, 0x19, 0x2a, 0x0b, 0x2c, 0x0d, 0x0e, 0x1c}; + public static byte[] appendChecksum(final byte[] input) { if (input == null) { @@ -285,15 +269,15 @@ public class RFTools { return toHexString(array, 0, array.length); } - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; + + private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + public static String toHexString(byte[] array, int offset, int length) { char[] buf = new char[length * 2]; int bufIndex = 0; - for (int i = offset; i < offset + length; i++) { + for(int i = offset; i < offset + length; i++) { byte b = array[i]; buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java index 090e40fbb3..a955a210fe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/RileyLinkBLE.java @@ -35,7 +35,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.utils.ThreadUtil; /** * Created by geoff on 5/26/16. - * Added: State handling, configuration of RF for different configuration ranges, connection handling - Andy + * Added: State handling, configuration of RF for different configuration ranges, connection handling */ public class RileyLinkBLE { @@ -134,8 +134,13 @@ public class RileyLinkBLE { LOG.warn("onConnectionStateChange " + getGattStatusMessage(status) + " " + stateMessage); } - if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) { - RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothConnected); + if (newState == BluetoothProfile.STATE_CONNECTED) { + if (status == BluetoothGatt.GATT_SUCCESS) { + RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.BluetoothConnected); + } else { + LOG.debug("BT State connected, GATT status {} ({})", status, getGattStatusMessage(status)); + } + } else if ((newState == BluetoothProfile.STATE_CONNECTING) || // (newState == BluetoothProfile.STATE_DISCONNECTING)) { //LOG.debug("We are in {} state.", status == BluetoothProfile.STATE_CONNECTING ? "Connecting" : "Disconnecting"); @@ -227,7 +232,7 @@ public class RileyLinkBLE { if (rileyLinkFound) { mIsConnected = true; RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkReady); - //RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_BLE_RileyLinkReady), null); + //RileyLinkUtil.sendNotification(new ServiceNotification(RileyLinkConst.Intents.RileyLinkReady), null); } else { mIsConnected = false; RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkError, RileyLinkError.DeviceIsNotRileyLink); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/GattAttributes.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/GattAttributes.java index ce65241abb..62238c8c42 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/GattAttributes.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/GattAttributes.java @@ -10,7 +10,7 @@ import java.util.UUID; public class GattAttributes { // NOTE: these uuid strings must be lower case! - private static Map attributes; + public static String PREFIX = "0000"; public static String SUFFIX = "-0000-1000-8000-00805f9b34fb"; public static String SERVICE_GAP = PREFIX + "1800" + SUFFIX; @@ -30,6 +30,8 @@ public class GattAttributes { public static String CHARA_RADIO_VERSION = "30d99dc9-7c91-4295-a051-0a104d238cf2"; public static String CHARA_RADIO_LED_MODE = "c6d84241-f1a7-4f9c-a25f-fce16732f14e"; + private static Map attributes; + private static Map attributesRileyLinkSpecific; // table of names for uuids static { @@ -49,6 +51,16 @@ public class GattAttributes { attributes.put(CHARA_RADIO_TIMER_TICK, "Timer Tick"); attributes.put(CHARA_RADIO_VERSION, "Version"); // firmwareVersion attributes.put(CHARA_RADIO_LED_MODE, "Led Mode"); + + attributesRileyLinkSpecific = new HashMap<>(); + + attributesRileyLinkSpecific.put(SERVICE_RADIO, "Radio Interface"); // a + attributesRileyLinkSpecific.put(CHARA_RADIO_CUSTOM_NAME, "Custom Name"); + attributesRileyLinkSpecific.put(CHARA_RADIO_DATA, "Data"); + attributesRileyLinkSpecific.put(CHARA_RADIO_RESPONSE_COUNT, "Response Count"); + attributesRileyLinkSpecific.put(CHARA_RADIO_TIMER_TICK, "Timer Tick"); + attributesRileyLinkSpecific.put(CHARA_RADIO_VERSION, "Version"); // firmwareVersion + attributesRileyLinkSpecific.put(CHARA_RADIO_LED_MODE, "Led Mode"); } @@ -68,10 +80,9 @@ public class GattAttributes { } - // TODO check if service is rileylink + // we check for specific UUID (Radio ones, because thoose seem to be unique public static boolean isRileyLink(UUID uuid) { - return attributes.containsKey(uuid.toString()); - //return true; + return attributesRileyLinkSpecific.containsKey(uuid.toString()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RFSpyResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RFSpyResponse.java index 6d8e1f1e6b..acc0c879f3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RFSpyResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RFSpyResponse.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RFSpyCommand; + /** * Created by geoff on 5/26/16. */ @@ -9,33 +11,46 @@ public class RFSpyResponse { // 0xcc == zero-data protected byte[] raw; protected RadioResponse radioResponse; + private RFSpyCommand command; public RFSpyResponse() { init(new byte[0]); } + public RFSpyResponse(byte[] bytes) { init(bytes); } + + public RFSpyResponse(RFSpyCommand command, byte[] rawResponse) { + + this.command = command; + init(rawResponse); + } + + public void init(byte[] bytes) { if (bytes == null) { raw = new byte[0]; } else { raw = bytes; } + if (looksLikeRadioPacket()) { - radioResponse = new RadioResponse(raw); + radioResponse = new RadioResponse(command, raw); } else { radioResponse = new RadioResponse(); } } + public RadioResponse getRadioResponse() { return radioResponse; } + public boolean wasTimeout() { if ((raw.length == 1) || (raw.length == 2)) { if (raw[0] == (byte) 0xaa) { @@ -45,6 +60,7 @@ public class RFSpyResponse { return false; } + public boolean wasInterrupted() { if ((raw.length == 1) || (raw.length == 2)) { if (raw[0] == (byte) 0xbb) { @@ -54,6 +70,7 @@ public class RFSpyResponse { return false; } + public boolean isOK() { if ((raw.length == 1) || (raw.length == 2)) { if (raw[0] == (byte) 0x01) { @@ -63,6 +80,7 @@ public class RFSpyResponse { return false; } + public boolean looksLikeRadioPacket() { if (raw.length > 2) { return true; @@ -70,6 +88,7 @@ public class RFSpyResponse { return false; } + public byte[] getRaw() { return raw; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RLMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RLMessage.java index 71ac60daf5..1d2ed3cde3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RLMessage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RLMessage.java @@ -7,4 +7,6 @@ public interface RLMessage { byte[] getTxData(); + boolean isValid(); + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java index a904d4994b..e589eff120 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/data/RadioResponse.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFTools; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RFSpyCommand; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC; @@ -19,6 +20,7 @@ public class RadioResponse { public int responseNumber; public byte[] decodedPayload = new byte[0]; public byte receivedCRC; + private RFSpyCommand command; public RadioResponse() { @@ -29,8 +31,21 @@ public class RadioResponse { init(rxData); } + public RadioResponse(RFSpyCommand command, byte[] raw) { + + this.command = command; + init(raw); + } + public boolean isValid() { + + if (command!=null && !command.isEncoded()) + { + return true; + } + + if (!decodedOK) { return false; } @@ -55,14 +70,25 @@ public class RadioResponse { responseNumber = rxData[1]; byte[] encodedPayload = ByteUtil.substring(rxData, 2, rxData.length - 2); try { - byte[] decodeThis = RFTools.decode4b6b(encodedPayload); - decodedOK = true; - decodedPayload = ByteUtil.substring(decodeThis, 0, decodeThis.length - 1); - byte calculatedCRC = CRC.crc8(decodedPayload); - receivedCRC = decodeThis[decodeThis.length - 1]; - if (receivedCRC != calculatedCRC) { - LOG.error("RadioResponse: CRC mismatch, calculated 0x%02x, received 0x%02x", calculatedCRC, receivedCRC); + + boolean isEncoded = command==null || command.isEncoded(); + + if (isEncoded) { + byte[] decodeThis = RFTools.decode4b6b(encodedPayload); + decodedOK = true; + decodedPayload = ByteUtil.substring(decodeThis, 0, decodeThis.length - 1); + byte calculatedCRC = CRC.crc8(decodedPayload); + receivedCRC = decodeThis[decodeThis.length - 1]; + if (receivedCRC != calculatedCRC) { + LOG.error(String.format("RadioResponse: CRC mismatch, calculated 0x%02x, received 0x%02x", calculatedCRC, receivedCRC)); + } } + else { + decodedOK = true; + decodedPayload = encodedPayload; + } + + //byte[] decodeThis = RFTools.decode4b6b(encodedPayload); } catch (NumberFormatException e) { decodedOK = false; LOG.error("Failed to decode radio data: " + ByteUtil.shortHexString(encodedPayload)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java index 50d5ee014e..fd035eaeb7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RFSpyCommand.java @@ -7,7 +7,7 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; public enum RFSpyCommand { GetState(1), // - GetVersion(2), // + GetVersion(2, false), // GetPacket(3), // aka Listen, receive Send(4), // SendAndListen(5), // @@ -17,10 +17,26 @@ public enum RFSpyCommand { ; public byte code; + private boolean encoded = true; RFSpyCommand(int code) { this.code = (byte) code; } + + RFSpyCommand(int code, boolean encoded) { + this.code = (byte) code; + this.encoded = encoded; + } + + + public boolean isEncoded() { + return encoded; + } + + + public void setEncoded(boolean encoded) { + this.encoded = encoded; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java deleted file mode 100644 index dc8907745a..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RLMessage.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; - -/** - * Created by andy on 5/6/18. - */ -public interface RLMessage { - - byte[] getTxData(); - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java deleted file mode 100644 index 3a0ac72dd0..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetDevice.java +++ /dev/null @@ -1,11 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs; - -/** - * Created by andy on 5/19/18. - */ - -public enum RileyLinkTargetDevice { - MedtronicPump, // - Omnipod, // - ; -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java index 2194080f44..b7d535f942 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/ble/defs/RileyLinkTargetFrequency.java @@ -8,7 +8,7 @@ public enum RileyLinkTargetFrequency { Medtronic_WorldWide(868.25, 868.65, 0.05), // Medtronic_US(916.45, 916.80, 0.05), // - Omnipod(416.00, 417.00, 0.05), // + Omnipod(433.91, 433.91, 0.00), // ; double minFrequency; @@ -24,7 +24,17 @@ public enum RileyLinkTargetFrequency { public double[] getScanFrequencies() { + + if (maxFrequency == minFrequency) + { + double freq[] = new double[1]; + freq[0] = minFrequency; + + return freq; + } + double diff = maxFrequency - minFrequency; + int count = (int) (diff / step); double freq[] = new double[count]; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java index 534d8bf1ee..3ec19a44e3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkError.java @@ -20,7 +20,7 @@ public enum RileyLinkError { DeviceIsNotRileyLink(R.string.rileylink_error_not_rl), // // Device - TuneUpOfPumpFailed(R.string.rileylink_error_tuneup_failed), // + TuneUpOfDeviceFailed(R.string.rileylink_error_tuneup_failed), // NoContactWithDevice(R.string.rileylink_error_pump_unreachable, R.string.rileylink_error_pod_unreachable), // ; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java index dacc31d206..06570d51cc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkServiceState.java @@ -22,7 +22,7 @@ public enum RileyLinkServiceState { RileyLinkReady(R.string.rileylink_state_connected), // (OK) if tunning was already done we go to PumpConnectorReady // Tunning - TuneUpPump(R.string.rileylink_state_pc_tune_up), // (S) + TuneUpDevice(R.string.rileylink_state_pc_tune_up), // (S) PumpConnectorError(R.string.rileylink_state_pc_error), // either TuneUp Error or pump couldn't not be contacted error PumpConnectorReady(R.string.rileylink_state_connected), // (OK) RileyLink Ready for Pump Communication diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java index 950e102edb..b6320e79c0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/defs/RileyLinkTargetDevice.java @@ -5,7 +5,18 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs; */ public enum RileyLinkTargetDevice { - MedtronicPump, // - Omnipod, // + MedtronicPump(true), // + Omnipod(false), // ; + + private boolean tuneUpEnabled; + + RileyLinkTargetDevice(boolean tuneUpEnabled) { + + this.tuneUpEnabled = tuneUpEnabled; + } + + public boolean isTuneUpEnabled() { + return tuneUpEnabled; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java index 6c340845fb..e4f53b3bca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkService.java @@ -17,10 +17,10 @@ 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.RFSpy; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse; 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.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceNotification; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport; @@ -28,14 +28,12 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks. import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.InitializePumpManagerTask; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTask; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor; -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; +//import static info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.; + /** * Created by andy on 5/6/18. @@ -54,7 +52,7 @@ public abstract class RileyLinkService extends Service { //protected boolean needBluetoothPermission = true; //protected RileyLinkIPCConnection rileyLinkIPCConnection; protected Context context; - public RileyLinkCommunicationManager pumpCommunicationManager; + //public RileyLinkCommunicationManager pumpCommunicationManager; protected BroadcastReceiver mBroadcastReceiver; protected RileyLinkServiceData rileyLinkServiceData; @@ -121,16 +119,6 @@ public abstract class RileyLinkService extends Service { //rileyLinkIPCConnection = new RileyLinkIPCConnection(context); // TODO We might be able to remove this -- Andy //RileyLinkUtil.setRileyLinkIPCConnection(rileyLinkIPCConnection); - // // get most recently used RileyLink address - // rileyLinkServiceData.rileylinkAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, ""); - // - // rileyLinkBLE = new RileyLinkBLE(this); - // rfspy = new RFSpy(context, rileyLinkBLE); - // rfspy.startReader(); - // - // RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); - - loadPumpCommunicationManager(); mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -145,44 +133,16 @@ public abstract class RileyLinkService extends Service { if (action == null) { LOG.error("onReceive: null action"); } else { + if (action.equals(RileyLinkConst.Intents.BluetoothConnected)) { - LOG.warn("serviceLocal.bluetooth_connected"); //rileyLinkIPCConnection.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_FindingRileyLink), null); ServiceTaskExecutor.startTask(new DiscoverGattServicesTask()); - // If this is successful, - // We will get a broadcast of RT2Const.serviceLocal.BLE_services_discovered } else if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) { if (bluetoothAdapter.isEnabled()) { RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothReady, RileyLinkError.RileyLinkUnreachable); } else { RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); } - - } 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); - - switch (state) { - case BluetoothAdapter.STATE_OFF: { - LOG.debug("Bluetooth OFF"); - //RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled); - } - break; - - - case BluetoothAdapter.STATE_ON: { - LOG.debug("Bluetooth ON"); - //setButtonText("Bluetooth on"); - } - break; - - case BluetoothAdapter.STATE_TURNING_OFF: - case BluetoothAdapter.STATE_TURNING_ON: - break; - } } else if (action.equals(RileyLinkConst.Intents.RileyLinkReady)) { LOG.warn("MedtronicConst.Intents.RileyLinkReady"); // FIXME @@ -190,43 +150,50 @@ public abstract class RileyLinkService extends Service { rileyLinkBLE.enableNotifications(); rfspy.startReader(); // call startReader from outside? - LOG.debug("RfSpy version (BLE113): " + rfspy.getVersion()); + String data = rfspy.getVersion(); + LOG.debug("RfSpy version (BLE113): " + data); + rileyLinkServiceData.versionBLE113 = data; - RFSpyResponse radioVersion = rfspy.getRadioVersion(); - - byte[] response = radioVersion.getRadioResponse().decodedPayload; - - LOG.debug("Response: " + HexDump.toHexStringDisplayable(response)); - - LOG.debug("RfSpy Radio version (CC110): " + StringUtil.fromBytes(radioVersion.getRadioResponse().decodedPayload)); + data = rfspy.getRadioVersion(); + LOG.debug("RfSpy Radio version (CC110): " + data); + rileyLinkServiceData.versionCC110 = data; ServiceTask task = new InitializePumpManagerTask(); ServiceTaskExecutor.startTask(task); LOG.info("Announcing RileyLink open For business"); - } /*else if (action.equals(RT2Const.serviceLocal.ipcBound)) { - // If we still need permission for bluetooth, ask now. - // FIXME removed Andy - doesn't do anything - // if (needBluetoothPermission) { - // sendBLERequestForAccess(); - // } - - }*/ /*else if (RT2Const.IPC.MSG_BLE_accessGranted.equals(action)) { - //initializeLeAdapter(); - //bluetoothInit(); - } else if (RT2Const.IPC.MSG_BLE_accessDenied.equals(action)) { - LOG.error("BLE_Access_Denied recived. Stoping the service."); - stopSelf(); // This will stop the service. - } */ else if (action.equals(RileyLinkConst.IPC.MSG_PUMP_tunePump)) { - doTunePump(); + } else if (action.equals(RileyLinkConst.Intents.BluetoothReconnected)) { + LOG.debug("Reconnecting Bluetooth"); + //rileyLinkIPCConnection.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_FindingRileyLink), null); + bluetoothInit(); + ServiceTaskExecutor.startTask(new DiscoverGattServicesTask(true)); + } else if (action.equals(RileyLinkConst.IPC.MSG_PUMP_tunePump)) { + if (getRileyLinkTargetDevice().isTuneUpEnabled()) { + doTuneUpDevice(); + } } else if (action.equals(RileyLinkConst.IPC.MSG_PUMP_quickTune)) { - doTunePump(); - } else if (RileyLinkConst.Intents.RileyLinkNewAddressSet.equals(action)) { - reconfigureRileyLink(MedtronicUtil.getPumpStatus().rileyLinkAddress); + if (getRileyLinkTargetDevice().isTuneUpEnabled()) { + doTuneUpDevice(); + } } else if (action.startsWith("MSG_PUMP_")) { handlePumpSpecificIntents(intent); } else if (RileyLinkConst.IPC.MSG_ServiceCommand.equals(action)) { handleIncomingServiceTransport(intent); - } /*else if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) { + } else if (action.equals(RileyLinkConst.Intents.RileyLinkNewAddressSet)) { + String RileylinkBLEAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, ""); + if (RileylinkBLEAddress.equals("")) { + LOG.error("No Rileylink BLE Address saved in app"); + } else { + //showBusy("Configuring Service", 50); + //rileyLinkBLE.findRileyLink(RileylinkBLEAddress); + reconfigureRileyLink(RileylinkBLEAddress); + //MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress); + } + } + + + + + /*else if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) { Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey); if (bundle != null) { ServiceTransport transport = new ServiceTransport(bundle); @@ -280,20 +247,16 @@ 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.BluetoothReconnected); intentFilter.addAction(RileyLinkConst.Intents.RileyLinkNewAddressSet); - - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); //intentFilter.addAction(RT2Const.serviceLocal.ipcBound); //intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessGranted); //intentFilter.addAction(RT2Const.IPC.MSG_BLE_accessDenied); //intentFilter.addAction(RT2Const.IPC.MSG_BLE_useThisDevice); intentFilter.addAction(RileyLinkConst.IPC.MSG_PUMP_tunePump); - intentFilter.addAction(RileyLinkConst.IPC.MSG_PUMP_quickTune); - //intentFilter.addAction(RT2Const.IPC.MSG_PUMP_useThisAddress); intentFilter.addAction(RileyLinkConst.IPC.MSG_ServiceCommand); - //intentFilter.addAction(RT2Const.serviceLocal.INTENT_sessionCompleted); + //intentFilter.addAction(RileyLinkConst.serviceLocal.INTENT_sessionCompleted); addPumpSpecificIntents(intentFilter); @@ -303,12 +266,12 @@ public abstract class RileyLinkService extends Service { } + public abstract RileyLinkCommunicationManager getDeviceCommunicationManager(); + public abstract void addPumpSpecificIntents(IntentFilter intentFilter); public abstract void handlePumpSpecificIntents(Intent intent); - public abstract void loadPumpCommunicationManager(); - public abstract void handleIncomingServiceTransport(Intent intent); @@ -444,14 +407,14 @@ public abstract class RileyLinkService extends Service { // FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc. - public void doTunePump() { + public void doTuneUpDevice() { - RileyLinkUtil.setServiceState(RileyLinkServiceState.TuneUpPump); + RileyLinkUtil.setServiceState(RileyLinkServiceState.TuneUpDevice); double lastGoodFrequency = 0.0d; if (rileyLinkServiceData.lastGoodFrequency == null) { - lastGoodFrequency = SP.getDouble(MedtronicConst.Statistics.LastGoodPumpFrequency, 0.0d); + lastGoodFrequency = SP.getDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, 0.0d); } else { lastGoodFrequency = rileyLinkServiceData.lastGoodFrequency; } @@ -460,21 +423,21 @@ public abstract class RileyLinkService extends Service { if ((lastGoodFrequency > 0.0d) && getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) { LOG.info("Checking for pump near last saved frequency of {}MHz", lastGoodFrequency); // we have an old frequency, so let's start there. - newFrequency = pumpCommunicationManager.quickTuneForPump(lastGoodFrequency); + newFrequency = getDeviceCommunicationManager().quickTuneForPump(lastGoodFrequency); if (newFrequency == 0.0) { // quick scan failed to find pump. Try full scan LOG.warn("Failed to find pump near last saved frequency, doing full scan"); - newFrequency = pumpCommunicationManager.tuneForPump(); + newFrequency = getDeviceCommunicationManager().tuneForDevice(); } } else { LOG.warn("No saved frequency for pump, doing full scan."); // we don't have a saved frequency, so do the full scan. - newFrequency = pumpCommunicationManager.tuneForPump(); + newFrequency = getDeviceCommunicationManager().tuneForDevice(); } if ((newFrequency != 0.0) && (newFrequency != lastGoodFrequency)) { LOG.info("Saving new pump frequency of {}MHz", newFrequency); - SP.putDouble(MedtronicConst.Statistics.LastGoodPumpFrequency, newFrequency); + SP.putDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, newFrequency); rileyLinkServiceData.lastGoodFrequency = newFrequency; rileyLinkServiceData.tuneUpDone = true; rileyLinkServiceData.lastTuneUpTime = System.currentTimeMillis(); @@ -484,7 +447,7 @@ public abstract class RileyLinkService extends Service { if (newFrequency == 0.0d) { // error tuning pump, pump not present ?? - RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.TuneUpOfPumpFailed); + RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.TuneUpOfDeviceFailed); } } @@ -492,4 +455,9 @@ public abstract class RileyLinkService extends Service { public void disconnectRileyLink() { this.rileyLinkBLE.disconnect(); } + + + public RileyLinkTargetDevice getRileyLinkTargetDevice() { + return this.rileyLinkServiceData.targetDevice; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java index 8fdb18a22d..53d83caf43 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/RileyLinkServiceData.java @@ -4,6 +4,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLink import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState; + /** * Created by andy on 16/05/2018. */ @@ -17,6 +18,11 @@ public class RileyLinkServiceData { public long lastTuneUpTime = 0L; public Double lastGoodFrequency; + // bt version + public String versionBLE113; + // radio version + public String versionCC110; + public RileyLinkTargetDevice targetDevice; // Medtronic Pump diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java index e051fbdb97..e1d5b28167 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/DiscoverGattServicesTask.java @@ -7,12 +7,24 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; */ public class DiscoverGattServicesTask extends ServiceTask { + public boolean needToConnect = false; + + public DiscoverGattServicesTask() { } + public DiscoverGattServicesTask(boolean needToConnect) { + this.needToConnect = needToConnect; + } + + @Override public void run() { + + if (needToConnect) + RileyLinkUtil.getRileyLinkBLE().connectGatt(); + RileyLinkUtil.getRileyLinkBLE().discoverServices(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java index cedee7f70a..354d3284e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/InitializePumpManagerTask.java @@ -7,7 +7,6 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; 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.PumpCommon.hw.rileylink.service.data.ServiceTransport; -import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst; import info.nightscout.utils.SP; /** @@ -34,7 +33,7 @@ public class InitializePumpManagerTask extends ServiceTask { public void run() { // FIXME - double lastGoodFrequency = SP.getDouble(MedtronicConst.Statistics.LastGoodPumpFrequency, 0.0); + double lastGoodFrequency = SP.getDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, 0.0d); if ((lastGoodFrequency > 0.0d) && RileyLinkUtil.getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) { @@ -55,7 +54,6 @@ public class InitializePumpManagerTask extends ServiceTask { //RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_note_Idle), null); } else { RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump); - } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java index 58705a5a0d..bdecb72294 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/ServiceTaskExecutor.java @@ -20,6 +20,10 @@ public class ServiceTaskExecutor extends ThreadPoolExecutor { instance = new ServiceTaskExecutor(); } + public static ServiceTaskExecutor getInstance() { + return instance; + } + private ServiceTaskExecutor() { super(1, 1, 10000, TimeUnit.MILLISECONDS, taskQueue); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java index 07cb1a7f62..c593d097ab 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/hw/rileylink/service/tasks/WakeAndTuneTask.java @@ -7,7 +7,6 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtron * Created by geoff on 7/16/16. */ public class WakeAndTuneTask extends PumpTask { - private static final String TAG = "WakeAndTuneTask"; public WakeAndTuneTask() { @@ -21,8 +20,7 @@ public class WakeAndTuneTask extends PumpTask { @Override public void run() { - //RileyLinkMedtronicService.getInstance().pumpCommunicationManager.wakeup(6); - RileyLinkMedtronicService.getInstance().pumpCommunicationManager.tuneForPump(); + RileyLinkMedtronicService.getInstance().doTuneUpDevice(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java index 96514e7acd..9094ec30e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicFragment.java @@ -7,11 +7,11 @@ 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; +import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; @@ -39,8 +39,6 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil; 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.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.defs.MedtronicCommandType; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState; import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus; @@ -48,6 +46,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDev 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.Callback; import info.nightscout.androidaps.queue.events.EventQueueChanged; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -105,6 +104,9 @@ public class MedtronicFragment extends SubscriberFragment { @BindView(R.id.medtronic_pump_status) IconTextView pumpStatusIconView; + @BindView(R.id.medtronic_refresh) + Button refreshButton; + public MedtronicFragment() { } @@ -148,14 +150,20 @@ public class MedtronicFragment extends SubscriberFragment { @OnClick(R.id.medtronic_history) void onHistoryClick() { - startActivity(new Intent(getContext(), DanaRHistoryActivity.class)); + //startActivity(new Intent(getContext(), DanaRHistoryActivity.class)); } - @OnClick(R.id.medtronic_viewprofile) - void onViewProfileClick() { - FragmentManager manager = getFragmentManager(); - ProfileViewDialog profileViewDialog = new ProfileViewDialog(); - profileViewDialog.show(manager, "ProfileViewDialog"); + @OnClick(R.id.medtronic_refresh) + void onRefreshClick() { + refreshButton.setEnabled(false); + MedtronicPumpPlugin.getPlugin().resetStatusState(); + + ConfigBuilderPlugin.getCommandQueue().readStatus("Clicked refresh", new Callback() { + @Override + public void run() { + refreshButton.setEnabled(true); + } + }); } @OnClick(R.id.medtronic_stats) @@ -163,12 +171,6 @@ public class MedtronicFragment extends SubscriberFragment { startActivity(new Intent(getContext(), RileylinkSettingsActivity.class)); } - /*@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) { @@ -188,20 +190,7 @@ public class MedtronicFragment extends SubscriberFragment { public void run() { 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}"); } } ); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java index a49007c90b..bb268d2f30 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/MedtronicPumpPlugin.java @@ -18,14 +18,20 @@ 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.db.Source; +import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventRefreshOverview; 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.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.PumpCommon.PumpPluginAbstract; import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUIComm; import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUITask; import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair; @@ -37,6 +43,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPum 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.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.utils.SP; /** @@ -52,7 +59,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter protected static MedtronicPumpPlugin plugin = null; private MedtronicPumpStatus pumpStatusLocal = null; private MedtronicUIComm medtronicUIComm = new MedtronicUIComm(); - boolean firstRun = true; + + // variables for handling statuses and history + private boolean firstRun = true; + private boolean relevantConfigurationChangeFound = false; + private boolean hasBasalProfileChanged = false; + private boolean isBasalProfileInvalid = false; + private Map statusRefreshMap = new HashMap<>(); + public static MedtronicPumpPlugin getPlugin() { if (plugin == null) @@ -79,11 +93,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter .pluginName(R.string.medtronic_name) // .shortName(R.string.medtronic_name_short) // .preferencesId(R.xml.pref_medtronic), // - PumpType.Minimed_512_712 // we default to most basic model, correct model from config is loaded later + PumpType.Medtronic_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) { @@ -96,47 +108,34 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter RileyLinkMedtronicService.LocalBinder mLocalBinder = (RileyLinkMedtronicService.LocalBinder) service; medtronicService = mLocalBinder.getServiceInstance(); - //pumpStatusLocal.setNotInPreInit(); + new Thread(() -> { - new Thread(new Runnable() { - @Override - public void run() { + for (int i = 0; i < 20; i++) { + SystemClock.sleep(5000); - 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; - } + if (MedtronicUtil.getPumpStatus() != null) { + LOG.debug("Starting Medtronic-RileyLink service"); + if (MedtronicUtil.getPumpStatus().setNotInPreInit()) { + break; } } } }).start(); } }; - - } @Override public void initPumpStatusData() { - 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) @@ -148,7 +147,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter pumpDescription.isExtendedBolusCapable = false; pumpDescription.isSetBasalProfileCapable = false; - // unchangable pumpDescription.tempBasalStyle = PumpDescription.PERCENT; pumpDescription.tempDurationStep15mAllowed = false; @@ -159,9 +157,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter pumpDescription.supportsTDDs = true; pumpDescription.needsManualTDDLoad = false; - - //pumpStatusLocal.setNotInPreInit(); - // set first Medtronic Pump Start if (!SP.contains(MedtronicConst.Statistics.FirstPumpStart)) { SP.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis()); @@ -185,7 +180,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter }).start(); - //pumpStatusLocal.setNotInPreInit(); } @@ -210,12 +204,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter return false; } - // we don't loadTDD - @Override - public PumpEnactResult loadTDDs() { - return OPERATION_NOT_SUPPORTED; - } - // Pump Plugin @@ -223,18 +211,22 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter return medtronicService != null; } + public boolean isInitialized() { return isServiceSet() && medtronicService.isInitialized(); } + // FIXME public boolean isSuspended() { return isServiceSet() && medtronicService.isSuspended(); } + public boolean isBusy() { return isServiceSet() && medtronicService.isBusy(); } + public boolean isConnected() { return isServiceSet() && medtronicService.isInitialized(); } @@ -249,31 +241,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } - public void connect(String 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) { - // see comment in connect - } - - - public void stopConnecting() { - // see comment in connect - } - - // FIXME @Override public void getPumpStatus() { - if (this.pumpStatusLocal == null) { - // FIXME I don't know why this happens - LOG.debug("getPumpStatus: reset pumpStatusLocal "); - this.pumpStatusLocal = MedtronicUtil.getPumpStatus(); - } + getMDTPumpStatus(); + if (firstRun) { initializePump(true); @@ -281,24 +253,20 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter refreshAnyStatusThatNeedsToBeRefreshed(); } - - //LOG.debug("getPumpStatus: {}", this.pumpStatusLocal); - //LOG.debug("getPumpStatus: {}", MedtronicUtil.getPumpStatus()); - - //getMDTPumpStatus().setLastCommunicationToNow(); - MainApp.bus().post(new EventMedtronicPumpValuesChanged()); } + public void resetStatusState() { + firstRun = true; + } + private void refreshAnyStatusThatNeedsToBeRefreshed() { if (!doWeHaveAnyStatusNeededRefereshing()) { return; } - // TODO - boolean resetTime = false; for (Map.Entry refreshType : statusRefreshMap.entrySet()) { @@ -321,21 +289,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } break; } - - } - - } if (resetTime) pumpStatusLocal.setLastCommunicationToNow(); - //LOG.error("MedtronicPumpPlugin::refreshAnyStatusThatNeedsToBeRefreshed NOT IMPLEMENTED."); } - Map statusRefreshMap = new HashMap<>(); - private boolean doWeHaveAnyStatusNeededRefereshing() { @@ -351,7 +312,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter private void initializePump(boolean realInit) { - LOG.error("MedtronicPumpPlugin::initializePump NOT fully IMPLEMENTED."); + LOG.error("initializePump - start"); getMDTPumpStatus(); @@ -360,13 +321,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel); } else { if (pumpStatusLocal.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) { - // TODO error + LOG.warn("Configured pump is not the same as one detected."); + Notification notification = new Notification(Notification.MEDTRONIC_PUMP_ALARM, MainApp.gs(R.string.medtronic_error_pump_type_set_differs_from_detected), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); } } + // TODO this call might need to do deeper call (several pages) // pump history handling - special, updates every 5 minutes ??? readPumpHistory(); - //scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory); // TODO rewrite reading of data to be done in background or different thread perhaps ?? @@ -375,14 +338,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter medtronicUIComm.executeCommand(MedtronicCommandType.GetRemainingInsulin); scheduleNextRefresh(MedtronicStatusRefreshType.RemainingInsulin, 10); - // TODO remaining power (1h) + // remaining power (1h) medtronicUIComm.executeCommand(MedtronicCommandType.GetBatteryStatus); scheduleNextRefresh(MedtronicStatusRefreshType.BatteryStatus, 20); // configuration (once and then if history shows config changes) medtronicUIComm.executeCommand(MedtronicCommandType.getSettings(MedtronicUtil.getMedtronicPumpModel())); - // TODO time (1h) + // time (1h) medtronicUIComm.executeCommand(MedtronicCommandType.RealTimeClock); scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 30); @@ -390,18 +353,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD); - //if () - // TODO handle if tunning was needed (more than 5 timeouts) int errorCount = medtronicUIComm.getInvalidResponsesCount(); if (errorCount >= 5) { LOG.error("Number of error counts was 5 or more. Starting tunning."); - medtronicUIComm.startTunning(); + ServiceTaskExecutor.startTask(new WakeAndTuneTask()); return; } - pumpStatusLocal.setLastCommunicationToNow(); this.firstRun = false; @@ -411,13 +371,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter @Override public boolean isThisProfileSet(Profile profile) { - // FIXME refactor this, reread profile only if history says that profile has changed... This will - // delay change of profile. - if (!isConnected()) { return true; } + if (!hasBasalProfileChanged && getMDTPumpStatus().basalsByHour != null) { + return (!isBasalProfileInvalid); + } + MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD); boolean invalid = false; @@ -457,6 +418,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter LOG.debug("Basal profile NO DATA"); } + isBasalProfileInvalid = invalid; + return (!invalid); } @@ -478,7 +441,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter private MedtronicPumpStatus getMDTPumpStatus() { if (pumpStatusLocal == null) { - LOG.warn("Reset Pump Status Local"); + // FIXME I don't know why this happens + LOG.warn("!!!! Reset Pump Status Local"); pumpStatusLocal = MedtronicUtil.getPumpStatus(); } @@ -497,15 +461,25 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter LOG.error("MedtronicPumpPlugin::deliverBolus Not fully implemented - Just base command."); + // TODO should wait and display bolus delivery MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.SetBolus, detailedBolusInfo.insulin); Boolean response = (Boolean) responseTask.returnData; // TODO display bolus - // TODO change remaining insulin + + if (response) { + // FIXME this needs to be fixed to read info from history + boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo); + + getMDTPumpStatus().reservoirRemainingUnits -= detailedBolusInfo.insulin; // we subtract insulin, exact amount will be visible with next remainingInsulin update. + + incrementStatistics(detailedBolusInfo.isSMB ? MedtronicConst.Statistics.SMBBoluses : MedtronicConst.Statistics.StandardBoluses); + } readPumpHistory(); + return new PumpEnactResult().success(response).enacted(response); @@ -624,10 +598,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } } - @Override - public void stopBolusDelivering() { + + private void incrementStatistics(String statsKey) { + long currentCount = SP.getLong(statsKey, 0L); + currentCount++; + SP.putLong(statsKey, currentCount); } + // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged), // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed @Override @@ -647,15 +625,24 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter // TODO translate return new PumpEnactResult().success(false).enacted(false).comment("Couldn't read current TBR."); } else { - LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute: Current Basal: " + tbrCurrent.getDurationMinutes() + tbrCurrent.getInsulinRate()); + LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute: Current Basal: duration: {} min, rate={}", tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate()); } // FIXME doesn't work correctly. Read current TBR first if (!enforceNew) { if (MedtronicUtil.isSame(tbrCurrent.getInsulinRate(), absoluteRate)) { - LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - No enforceNew and same rate. Exiting."); - return new PumpEnactResult().success(true).enacted(false); + + boolean sameRate = true; + if (MedtronicUtil.isSame(0.0d, absoluteRate) && durationInMinutes > 0) { + // if rate is 0.0 and duration>0 then the rate is not the same + sameRate = false; + } + + if (sameRate) { + LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - No enforceNew and same rate. Exiting."); + return new PumpEnactResult().success(true).enacted(false); + } } // if not the same rate, we cancel and start new } @@ -685,24 +672,42 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter Boolean response = (Boolean) responseTask.returnData; + LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - setTBR. Response: " + response); + if (response) { // FIXME put this into UIPostProcessor pumpStatusLocal.tempBasalStart = new Date(); pumpStatusLocal.tempBasalAmount = absoluteRate; pumpStatusLocal.tempBasalLength = durationInMinutes; + + // FIXME should be read from history + TemporaryBasal tempStart = new TemporaryBasal() + .date(System.currentTimeMillis()) + .duration(durationInMinutes) + .absolute(absoluteRate) + .source(Source.USER); + TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStart); + + incrementStatistics(MedtronicConst.Statistics.TBRsSet); } - readPumpHistory(); + readPumpHistory(); // TODO maybe this is not needed here + + MainApp.bus().post(new EventRefreshOverview("TBR")); + triggerUIChange(); return new PumpEnactResult().success(response).enacted(response); } + private void readPumpHistory() { LOG.error("MedtronicPumpPlugin::readPumpHistory NOT IMPLEMENTED."); - // TODO implement logic here - boolean relevantConfigurationChangeFound = false; + // TODO implement logic here fror config changes + relevantConfigurationChangeFound = false; + // TODO implement logic to see if Basalrates changed from last time + hasBasalProfileChanged = true; // TODO reset next refresh date, also set refreshdate if configuration changed scheduleNextRefresh(MedtronicStatusRefreshType.PumpHistory); @@ -719,6 +724,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter scheduleNextRefresh(refreshType, 0); } + private void scheduleNextRefresh(MedtronicStatusRefreshType refreshType, int additionalTimeInMinutes) { switch (refreshType) { @@ -749,6 +755,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter return System.currentTimeMillis() + getTimeInMs(minutes); } + private long getTimeInMs(int minutes) { return minutes * 60 * 1000L; } @@ -757,10 +764,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter // TODO @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT IMPLEMENTED."); + LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT IMPLEMENTED YET."); - return null; - //return OPERATION_NOT_YET_SUPPORTED; + return OPERATION_NOT_YET_SUPPORTED; } @@ -769,6 +775,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter if (responseTask.hasData()) { TempBasalPair tbr = (TempBasalPair) responseTask.returnData; + + // we sometimes get rate returned even if TBR is no longer running + if (tbr.getDurationMinutes() == 0) { + tbr.setInsulinRate(0.0d); + } + return tbr; } else { return null; @@ -779,8 +791,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter @Override public PumpEnactResult cancelTempBasal(boolean enforceNew) { - LOG.error("MedtronicPumpPlugin::cancelTempBasal Not fully implemented - Just base command."); - + LOG.info("cancelTempBasal - started"); TempBasalPair tbrCurrent = readTBR(); @@ -803,7 +814,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } else { LOG.info("MedtronicPumpPlugin::cancelTempBasal - Cancel TBR failed."); - } readPumpHistory(); @@ -812,30 +822,59 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter } - // 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.warn("MedtronicPumpPlugin::setNewBasalProfile NOT IMPLEMENTED."); + LOG.warn("MedtronicPumpPlugin::setNewBasalProfile NOT IMPLEMENTED YET."); return new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(R.string.medtronic_cmd_profile_not_set)); } + // OPERATIONS not supported by Pump or Plugin + + @Override + public PumpEnactResult cancelExtendedBolus() { + LOG.warn("cancelExtendedBolus - operation not supported."); + + return getOperationNotSupportedWithCustomText(R.string.medtronic_cmd_cancel_bolus_not_supported); + } + + + @Override + public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { + LOG.error("setTempBasalPercent NOT IMPLEMENTED."); + // we will never come here unless somebody has played with configuration in PumpType + return OPERATION_NOT_SUPPORTED; + } + + + // we don't loadTDD + @Override + public PumpEnactResult loadTDDs() { + return OPERATION_NOT_SUPPORTED; + } + + + public void connect(String 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) { + // see comment in connect + } + + + public void stopConnecting() { + // see comment in connect + } + + + @Override + public void stopBolusDelivering() { + // Medtronic doesn't have Bolus cancel, so we fake it. + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java index 760c2f3aa3..aaf6d0146e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/MedtronicCommunicationManager.java @@ -13,6 +13,7 @@ import java.util.Map; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager; import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage; 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; @@ -70,6 +71,13 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager } + @Override + public E createResponseMessage(byte[] payload, Class clazz) { + PumpMessage pumpMessage = new PumpMessage(payload); + return (E) pumpMessage; + } + + // FIXME must not call getPumpModel !!!!!!!!!!!!! @Override public boolean tryToConnectToDevice() { @@ -455,6 +463,17 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // } + protected PumpMessage sendAndListen(RLMessage msg) { + return sendAndListen(msg, 4000); // 2000 + } + + + // All pump communications go through this function. + protected PumpMessage sendAndListen(RLMessage msg, int timeout_ms) { + return sendAndListen(msg, timeout_ms, PumpMessage.class); + } + + private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType) { return sendAndGetResponseWithCheck(commandType, null); @@ -703,6 +722,43 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager // TODO generateRawData (check if it works correctly) and test public Boolean setBasalProfile(BasalProfile basalProfile) { + + // [RileyLinkDevice] ======================== Save Basal Profile =========================== + // [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 1 bytes), 0, 0.180000, 3) + // [PeripheralManager+RileyLink] RL Send: 19050000000000000000b4030000a9659a6b19b199c555b2c000 + // [PeripheralManager+RileyLink] RL Recv(single): bb + // [PeripheralManager+RileyLink] RileyLink response: PacketResponse(code: RileyLinkBLEKit.ResponseCode.commandInterrupted, packet: nil) + // [PeripheralManager+RileyLink] RL Recv(single): dd0dbca9659a6b19b156655534d500 + // [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 65 bytes), 0, 0.180000, 3) + // [PeripheralManager+RileyLink] RL Send: 79050000000000000000b4030000a9659a6b19b199c571c9a555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555556000 + // 2018-06-30 15:03:13.333962-0500 Loop[24609:13622692] [PeripheralManager+RileyLink] RL Recv(single): dd10bda9659a6b19b156655534d500 + // 2018-06-30 15:03:13.334927-0500 Loop[24609:13622484] [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 65 bytes), 0, 0.180000, 3) + // 2018-06-30 15:03:13.337923-0500 Loop[24609:13622484] [PeripheralManager+RileyLink] RL Send: 79050000000000000000b4030000a9659a6b19b199c5725555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555ac000 + // 2018-06-30 15:03:14.114024-0500 Loop[24609:13622486] [PeripheralManager+RileyLink] RL Recv(single): dd0ebea9659a6b19b156655534d500 + // 2018-06-30 15:03:14.115017-0500 Loop[24609:13622484] [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 65 bytes), 0, 0.180000, 3) + // 2018-06-30 15:03:14.117600-0500 Loop[24609:13622484] [PeripheralManager+RileyLink] RL Send: 79050000000000000000b4030000a9659a6b19b199c6a355555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555570e000 + // 2018-06-30 15:03:15.644502-0500 Loop[24609:13622692] [PeripheralManager+RileyLink] RL Recv(single): dd0ebfa9659a6b19b156655534d500 + // 2018-06-30 15:03:15.645388-0500 Loop[24609:13622484] [RileyLinkDevice] ------------------------ Save Basal Profile --------------------------- + + + // 2018-06-30 15:03:12.167767-0500 Loop[24609:13622484] [RileyLinkDevice] ======================== Save Basal Profile =========================== + // 2018-06-30 15:03:12.168652-0500 Loop[24609:13622484] [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 1 bytes), 0, 0.180000, 3) + // 2018-06-30 15:03:12.169518-0500 Loop[24609:13622484] [PeripheralManager+RileyLink] RL Send: 19050000000000000000b4030000a9659a6b19b199c555b2c000 + // 2018-06-30 15:03:12.463546-0500 Loop[24609:13622486] [PeripheralManager+RileyLink] RL Recv(single): bb + // 2018-06-30 15:03:12.463954-0500 Loop[24609:13622486] [PeripheralManager+RileyLink] RileyLink response: PacketResponse(code: RileyLinkBLEKit.ResponseCode.commandInterrupted, packet: nil) + // 2018-06-30 15:03:12.554051-0500 Loop[24609:13622486] [PeripheralManager+RileyLink] RL Recv(single): dd0dbca9659a6b19b156655534d500 + // 2018-06-30 15:03:12.555175-0500 Loop[24609:13622484] [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 65 bytes), 0, 0.180000, 3) + // 2018-06-30 15:03:12.557953-0500 Loop[24609:13622484] [PeripheralManager+RileyLink] RL Send: 79050000000000000000b4030000a9659a6b19b199c571c9a555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555556000 + // 2018-06-30 15:03:13.333962-0500 Loop[24609:13622692] [PeripheralManager+RileyLink] RL Recv(single): dd10bda9659a6b19b156655534d500 + // 2018-06-30 15:03:13.334927-0500 Loop[24609:13622484] [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 65 bytes), 0, 0.180000, 3) + // 2018-06-30 15:03:13.337923-0500 Loop[24609:13622484] [PeripheralManager+RileyLink] RL Send: 79050000000000000000b4030000a9659a6b19b199c5725555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555ac000 + // 2018-06-30 15:03:14.114024-0500 Loop[24609:13622486] [PeripheralManager+RileyLink] RL Recv(single): dd0ebea9659a6b19b156655534d500 + // 2018-06-30 15:03:14.115017-0500 Loop[24609:13622484] [PumpMessageSender] getResponse(PumpMessage(carelink, setBasalProfileStandard, 3 bytes, 65 bytes), 0, 0.180000, 3) + // 2018-06-30 15:03:14.117600-0500 Loop[24609:13622484] [PeripheralManager+RileyLink] RL Send: 79050000000000000000b4030000a9659a6b19b199c6a355555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555570e000 + // 2018-06-30 15:03:15.644502-0500 Loop[24609:13622692] [PeripheralManager+RileyLink] RL Recv(single): dd0ebfa9659a6b19b156655534d500 + // 2018-06-30 15:03:15.645388-0500 Loop[24609:13622484] [RileyLinkDevice] ------------------------ Save Basal Profile --------------------------- + + //byte[] body = basalProfile.generateRawData(); byte[] body = new byte[]{32, 0, 0, 38, 0, 13, 44, 0, 19, 38, 0, 28}; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java index 10e1f0c200..f301ac7a5d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/MedtronicConverter.java @@ -171,11 +171,17 @@ public class MedtronicConverter { protected Float decodeRemainingInsulin(byte[] rawData) { - //float value = MedtronicUtil.makeUnsignedShort(rawData[0], rawData[1]) / 10.0f; + int startIdx = 0; - float value = ByteUtil.toInt(rawData[0], rawData[1]) / 10.0f; + int strokes = pumpModel.getBolusStrokes(); - System.out.println("Remaining insulin: " + value); + if (strokes == 40) { + startIdx = 2; + } + + float value = ByteUtil.toInt(rawData[startIdx], rawData[startIdx + 1]) / (1.0f * strokes); + + LOG.debug("Remaining insulin: " + value); return value; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java index 573930343f..660209195f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/message/PumpMessage.java @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.comm.message; import android.util.Log; -import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessage; +import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage; import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil; import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump; import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType; @@ -111,7 +111,7 @@ public class PumpMessage implements RLMessage { // check Old Way boolean oldWay = false; - for(int i = (length + 1); i < data.length; i++) { + for (int i = (length + 1); i < data.length; i++) { if (data[i] != 0x00) { oldWay = true; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUIPostprocessor.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUIPostprocessor.java index c2a89e2439..e62987021f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUIPostprocessor.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUIPostprocessor.java @@ -65,8 +65,6 @@ public class MedtronicUIPostprocessor { case RealTimeClock: { processTime(uiTask); - - } break; @@ -83,8 +81,8 @@ public class MedtronicUIPostprocessor { case PumpModel: { if (pumpStatus.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) { - // TODO error - LOG.error("Configured pump is different then pump detected !!"); + LOG.warn("Configured pump is different then pump detected !"); + sendNotification(R.string.medtronic_error_pump_type_set_differs_from_detected, Notification.NORMAL); } } break; @@ -122,16 +120,21 @@ public class MedtronicUIPostprocessor { if (diff >= 10 * 60 * 1000) { LOG.debug("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")"); - Notification notification = new Notification(Notification.MEDTRONIC_PUMP_ALARM, MainApp.gs(R.string.combo_notification_check_time_date), Notification.URGENT); - MainApp.bus().post(new EventNewNotification(notification)); + sendNotification(R.string.combo_notification_check_time_date, Notification.URGENT); } else if (diff >= 4 * 60 * 1000) { LOG.debug("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")"); - Notification notification = new Notification(Notification.MEDTRONIC_PUMP_ALARM, MainApp.gs(R.string.combo_notification_check_time_date), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); + sendNotification(R.string.combo_notification_check_time_date, Notification.NORMAL); } } + + private void sendNotification(int resourceId, int notificationUrgencyType) { + Notification notification = new Notification(Notification.MEDTRONIC_PUMP_ALARM, MainApp.gs(resourceId), notificationUrgencyType); + MainApp.bus().post(new EventNewNotification(notification)); + } + + private void postProcessSettings(MedtronicUITask uiTask) { Map settings = (Map) uiTask.returnData; @@ -141,18 +144,15 @@ public class MedtronicUIPostprocessor { // check profile if (!"Yes".equals(settings.get("PCFG_BASAL_PROFILES_ENABLED").value)) { - - //Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.gs(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); - //MainApp.bus().post(new EventNewNotification(notification)); - // TODO profile not enabled LOG.error("Basal profiles are not enabled on pump."); + sendNotification(R.string.medtronic_error_pump_basal_profiles_not_enabled, Notification.URGENT); + } else { checkValue = settings.get("PCFG_ACTIVE_BASAL_PROFILE"); if (!"STD".equals(checkValue.value)) { - // TODO wrong profile LOG.error("Basal profile set on pump is incorrect (must be STD)."); - + sendNotification(R.string.medtronic_error_pump_incorrect_basal_profile_selected, Notification.URGENT); } } @@ -161,8 +161,8 @@ public class MedtronicUIPostprocessor { checkValue = settings.get("PCFG_TEMP_BASAL_TYPE"); if (!"Units".equals(checkValue.value)) { - // TODO wrong TBR type LOG.error("Wrong TBR type set on pump (must be Absolute)."); + sendNotification(R.string.medtronic_error_pump_wrong_tbr_type_set, Notification.URGENT); } // MAXes @@ -170,26 +170,17 @@ public class MedtronicUIPostprocessor { checkValue = settings.get("PCFG_MAX_BOLUS"); if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBolus)) { - // TODO wrong max Bolus type LOG.error("Wrong Max Bolus set on Pump (must be {}).", pumpStatus.maxBolus); + sendNotification(R.string.medtronic_error_pump_wrong_max_bolus_set, Notification.NORMAL); } checkValue = settings.get("PCFG_MAX_BASAL"); - double maxSet = Double.parseDouble(checkValue.value); - if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBasal)) { - // TODO wrong max Bolus type LOG.error("Wrong Max Basal set on Pump (must be {}).", pumpStatus.maxBasal); + sendNotification(R.string.medtronic_error_pump_wrong_max_basal_set, Notification.NORMAL); } - - //addSettingToMap("PCFG_MAX_BOLUS", "" + decodeMaxBolus(rd), PumpConfigurationGroup.Bolus, map); - //addSettingToMap("PCFG_MAX_BASAL", "" + decodeBasalInsulin(ByteUtil.makeUnsignedShort(rd[getSettingIndexMaxBasal()], rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal, map); - //addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal, map); - //addSettingToMap("PCFG_ACTIVE_BASAL_PROFILE", patt, PumpConfigurationGroup.Basal, map); - //addSettingToMap("PCFG_TEMP_BASAL_TYPE", rd[14] != 0 ? "Percent" : "Units", PumpConfigurationGroup.Basal, map); - } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUITask.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUITask.java index a04348c798..113910eba5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUITask.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/comm/ui/MedtronicUITask.java @@ -27,10 +27,9 @@ public class MedtronicUITask { boolean invalid = false; public MedtronicUITask(MedtronicCommandType commandType) { - this(commandType, null); + this.commandType = commandType; } - public MedtronicUITask(MedtronicCommandType commandType, Object... parameters) { this.commandType = commandType; this.parameters = parameters; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java index aeeca6f9b9..f450632b18 100755 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/defs/MedtronicCommandType.java @@ -61,6 +61,7 @@ public enum MedtronicCommandType implements Serializable //, MinimedCommandTypeI RealTimeClock(112, "Real Time Clock", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 7), // 0x70 GetBatteryStatus(0x72, "Get Battery Status", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // + // GetBattery((byte) 0x72), // GetRemainingInsulin(0x73, "Read Remaining Insulin", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2), // 115 diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java index dbb82a1d70..726e893d46 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/driver/MedtronicPumpStatus.java @@ -120,17 +120,17 @@ public class MedtronicPumpStatus extends PumpStatus { private void createMedtronicPumpMap() { medtronicPumpMap = new HashMap<>(); - medtronicPumpMap.put("512", PumpType.Minimed_512_712); - medtronicPumpMap.put("712", PumpType.Minimed_512_712); - medtronicPumpMap.put("515", PumpType.Minimed_515_715); - medtronicPumpMap.put("715", PumpType.Minimed_515_715); + medtronicPumpMap.put("512", PumpType.Medtronic_512_712); + medtronicPumpMap.put("712", PumpType.Medtronic_512_712); + medtronicPumpMap.put("515", PumpType.Medtronic_515_715); + medtronicPumpMap.put("715", PumpType.Medtronic_515_715); - medtronicPumpMap.put("522", PumpType.Minimed_522_722); - medtronicPumpMap.put("722", PumpType.Minimed_522_722); - medtronicPumpMap.put("523", PumpType.Minimed_523_723); - medtronicPumpMap.put("723", PumpType.Minimed_523_723); - medtronicPumpMap.put("554", PumpType.Minimed_554_754_Veo); - medtronicPumpMap.put("754", PumpType.Minimed_554_754_Veo); + medtronicPumpMap.put("522", PumpType.Medtronic_522_722); + medtronicPumpMap.put("722", PumpType.Medtronic_522_722); + medtronicPumpMap.put("523", PumpType.Medtronic_523_723_Revel); + medtronicPumpMap.put("723", PumpType.Medtronic_523_723_Revel); + medtronicPumpMap.put("554", PumpType.Medtronic_554_754_Veo); + medtronicPumpMap.put("754", PumpType.Medtronic_554_754_Veo); frequencies = new String[2]; frequencies[0] = MainApp.gs(R.string.medtronic_pump_frequency_us); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java index af00dd3c48..36396c2c79 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/service/RileyLinkMedtronicService.java @@ -19,6 +19,7 @@ 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.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager; 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.RFSpy; @@ -196,11 +197,6 @@ public class RileyLinkMedtronicService extends RileyLinkService { } } - @Override - public void loadPumpCommunicationManager() { - - } - @Override public void onConfigurationChanged(Configuration newConfig) { @@ -246,22 +242,20 @@ public class RileyLinkMedtronicService extends RileyLinkService { RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE); - // init rileyLinkCommunicationManager - pumpCommunicationManager = new MedtronicCommunicationManager(context, rfspy, rileyLinkTargetFrequency); - medtronicCommunicationManager = (MedtronicCommunicationManager) pumpCommunicationManager; + // init rileyLinkCommunicationManager + medtronicCommunicationManager = new MedtronicCommunicationManager(context, rfspy, rileyLinkTargetFrequency); // FIXME remove //pumpHistoryManager = new PumpHistoryManager(getApplicationContext()); } - - public MedtronicCommunicationManager getMedtronicCommunicationManager() { + @Override + public RileyLinkCommunicationManager getDeviceCommunicationManager() { return this.medtronicCommunicationManager; } - public void setPumpIDString(String pumpID) { if (pumpID.length() != 6) { LOG.error("setPumpIDString: invalid pump id string: " + pumpID); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java index 4e431caf5f..8dab2e52b8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMedtronic/util/MedtronicConst.java @@ -20,11 +20,11 @@ public class MedtronicConst { public class Statistics { - public static final String StatsPrefix = "medtronic_"; + static final String StatsPrefix = "medtronic_"; - static final String TBRsSet = StatsPrefix + "tbrs_set"; - static final String StandardBoluses = StatsPrefix + "std_boluses_delivered"; - static final String SMBBoluses = StatsPrefix + "smb_boluses_delivered"; + public static final String TBRsSet = StatsPrefix + "tbrs_set"; + public static final String StandardBoluses = StatsPrefix + "std_boluses_delivered"; + public static final String SMBBoluses = StatsPrefix + "smb_boluses_delivered"; public static final String FirstPumpStart = Prefix + "first_pump_use"; public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime"; diff --git a/app/src/main/res/layout/medtronic_fragment.xml b/app/src/main/res/layout/medtronic_fragment.xml index f9f950c693..ca0afed2be 100644 --- a/app/src/main/res/layout/medtronic_fragment.xml +++ b/app/src/main/res/layout/medtronic_fragment.xml @@ -489,16 +489,17 @@ android:layout_height="wrap_content" android:orientation="horizontal"> +