- removed code that sends wakeup on every command
- added checking if device is present
- fixed reading data when no data present (PostProcessingUI)
- work done on showing hardware in configuration (added RileyLinkSelectPreference)
- fixing configuration (in wizard)
This commit is contained in:
Andy Rozman 2018-10-20 13:24:36 +01:00
parent 70065c1343
commit ca536ee97e
38 changed files with 1281 additions and 1333 deletions

View file

@ -71,7 +71,7 @@ android {
targetSdkVersion 25
multiDexEnabled true
versionCode 1500
version "2.0g-medtronic"
version "2.0g-medtronic-0.3-snapshot"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
@ -109,7 +109,7 @@ android {
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
appIcon: "@mipmap/ic_launcher",
appIcon : "@mipmap/ic_launcher",
appIconRound: "@mipmap/ic_launcher_round"
]
}
@ -119,7 +119,7 @@ android {
resValue "string", "app_name", "AndroidAPS"
versionName version
manifestPlaceholders = [
appIcon: "@mipmap/blueowl",
appIcon : "@mipmap/blueowl",
appIconRound: "@null"
]
}
@ -129,7 +129,7 @@ android {
resValue "string", "app_name", "NSClient"
versionName version + "-nsclient"
manifestPlaceholders = [
appIcon: "@mipmap/yellowowl",
appIcon : "@mipmap/yellowowl",
appIconRound: "@null"
]
}
@ -139,7 +139,7 @@ android {
resValue "string", "app_name", "NSClient2"
versionName version + "-nsclient"
manifestPlaceholders = [
appIcon: "@mipmap/yellowowl",
appIcon : "@mipmap/yellowowl",
appIconRound: "@null"
]
}
@ -154,7 +154,7 @@ android {
unitTests.includeAndroidResources = true
}
useLibrary "org.apache.http.legacy"
useLibrary "org.apache.http.legacy"
}
allprojects {

View file

@ -31,8 +31,8 @@ import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityOref0Plugin;
@ -46,10 +46,11 @@ import info.nightscout.utils.LocaleHelper;
import info.nightscout.utils.OKDialog;
import info.nightscout.utils.SP;
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
MyPreferenceFragment myPreferenceFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -61,6 +62,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
MainApp.bus().post(new EventPreferenceChange(key));
@ -68,41 +70,47 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
String lang = sharedPreferences.getString("language", "en");
LocaleHelper.setLocale(getApplicationContext(), lang);
MainApp.bus().post(new EventRefreshGui(true));
//recreate() does not update language so better close settings
// recreate() does not update language so better close settings
finish();
}
if (key.equals("short_tabtitles")) {
MainApp.bus().post(new EventRefreshGui());
}
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning), null);
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens))
&& SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity),
MainApp.gs(R.string.sensitivity_warning), null);
}
updatePrefSummary(myPreferenceFragment.getPreference(key));
}
private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference) {
ListPreference listPref = (ListPreference) pref;
ListPreference listPref = (ListPreference)pref;
pref.setSummary(listPref.getEntry());
}
if (pref instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) pref;
EditTextPreference editTextPref = (EditTextPreference)pref;
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
pref.setSummary("******");
} else if (pref.getKey().equals(MainApp.gs(R.string.key_danars_name))) {
pref.setSummary(SP.getString(R.string.key_danars_name, ""));
} else if (editTextPref.getText() != null) {
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
((EditTextPreference)pref).setDialogMessage(editTextPref.getDialogMessage());
pref.setSummary(editTextPref.getText());
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && TextUtils.isEmpty(editTextPref.getText().trim())) {
} else if (pref.getKey().contains("smscommunicator_allowednumbers")
&& TextUtils.isEmpty(editTextPref.getText().trim())) {
pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
}
}
}
public static void initSummary(Preference p) {
if (p instanceof PreferenceGroup) {
PreferenceGroup pGrp = (PreferenceGroup) p;
PreferenceGroup pGrp = (PreferenceGroup)p;
for (int i = 0; i < pGrp.getPreferenceCount(); i++) {
initSummary(pGrp.getPreference(i));
}
@ -112,19 +120,23 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
public static class MyPreferenceFragment extends PreferenceFragment {
private Integer id;
@Override
public void setArguments(Bundle args) {
super.setArguments(args);
id = args.getInt("id");
}
void addPreferencesFromResourceIfEnabled(PluginBase p, PluginType type) {
if (p.isEnabled(type) && p.getPreferencesId() != -1)
addPreferencesFromResource(p.getPreferencesId());
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -156,7 +168,8 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
}
addPreferencesFromResourceIfEnabled(SensitivityAAPSPlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityWeightedAveragePlugin.getPlugin(),
PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref0Plugin.getPlugin(), PluginType.SENSITIVITY);
addPreferencesFromResourceIfEnabled(SensitivityOref1Plugin.getPlugin(), PluginType.SENSITIVITY);
@ -170,9 +183,9 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(MedtronicPumpPlugin.getPlugin(), PluginType.PUMP);
if (DanaRPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRSPlugin.getPlugin().isEnabled(PluginType.PROFILE)) {
|| DanaRKoreanPlugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRv2Plugin.getPlugin().isEnabled(PluginType.PROFILE)
|| DanaRSPlugin.getPlugin().isEnabled(PluginType.PROFILE)) {
addPreferencesFromResource(R.xml.pref_danarprofile);
}
}
@ -181,8 +194,6 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResourceIfEnabled(VirtualPumpPlugin.getPlugin(), PluginType.PUMP);
}
addPreferencesFromResourceIfEnabled(InsulinOrefFreePeakPlugin.getPlugin(), PluginType.INSULIN);
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
@ -198,12 +209,14 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
initSummary(getPreferenceScreen());
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("id", id);
}
public Preference getPreference(String key) {
return findPreference(key);
}

View file

@ -1,9 +1,5 @@
package info.nightscout.androidaps.plugins.Overview.notifications;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
@ -20,6 +16,7 @@ import info.nightscout.utils.SP;
*/
public class Notification {
public static final int URGENT = 0;
public static final int NORMAL = 1;
public static final int LOW = 2;
@ -68,9 +65,9 @@ public class Notification {
public static final int NSMALFUNCTION = 40;
public static final int NEWVERSIONDETECTED = 41;
public static final int SENDLOGFILES = 42;
public static final int RILEYLINK_CONNECTION = 43;
public static final int MEDTRONIC_PUMP_ALARM = 44;
public int id;
public Date date;
public String text;
@ -79,9 +76,12 @@ public class Notification {
public NSAlarm nsAlarm = null;
public Integer soundId = null;
public Notification() {
}
public Notification(int id, Date date, String text, int level, Date validTo) {
this.id = id;
this.date = date;
@ -90,6 +90,7 @@ public class Notification {
this.validTo = validTo;
}
public Notification(int id, String text, int level, int validMinutes) {
this.id = id;
this.date = new Date();
@ -98,6 +99,7 @@ public class Notification {
this.validTo = new Date(System.currentTimeMillis() + validMinutes * 60 * 1000L);
}
public Notification(int id, String text, int level) {
this.id = id;
this.date = new Date();
@ -106,27 +108,32 @@ public class Notification {
this.validTo = new Date(0);
}
public Notification(int id) {
this.id = id;
this.date = new Date();
this.validTo = new Date(0);
}
public Notification text(String text) {
this.text = text;
return this;
}
public Notification level(int level) {
this.level = level;
return this;
}
public Notification sound(int soundId) {
this.soundId = soundId;
return this;
}
public Notification(NSAlarm nsAlarm) {
this.date = new Date();
this.validTo = new Date(0);
@ -142,32 +149,41 @@ public class Notification {
this.id = NSALARM;
this.level = NORMAL;
this.text = nsAlarm.getTile();
if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false))
if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh()
&& SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData()
&& SP.getBoolean(R.string.key_nsalarm_staledata, false))
this.soundId = R.raw.alarm;
break;
case 2:
this.id = NSURGENTALARM;
this.level = URGENT;
this.text = nsAlarm.getTile();
if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false))
if (isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh()
&& SP.getBoolean(R.string.key_nsalarm_urgent_high, false))
this.soundId = R.raw.urgentalarm;
break;
}
}
public boolean isEnabled() {
if (nsAlarm == null)
return true;
if (level == ANNOUNCEMENT)
return true;
if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_staledata, false)) {
if (level == NORMAL && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_low, false) || isAlarmForHigh()
&& SP.getBoolean(R.string.key_nsalarm_high, false) || isAlarmForStaleData()
&& SP.getBoolean(R.string.key_nsalarm_staledata, false)) {
return true;
}
if (level == URGENT && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false) || isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false) || isAlarmForStaleData() && SP.getBoolean(R.string.key_nsalarm_urgent_staledata, false))
if (level == URGENT && isAlarmForLow() && SP.getBoolean(R.string.key_nsalarm_urgent_low, false)
|| isAlarmForHigh() && SP.getBoolean(R.string.key_nsalarm_urgent_high, false) || isAlarmForStaleData()
&& SP.getBoolean(R.string.key_nsalarm_urgent_staledata, false))
return true;
return false;
}
boolean isAlarmForLow() {
BgReading bgReading = MainApp.getDbHelper().lastBg();
if (bgReading == null)
@ -180,6 +196,7 @@ public class Notification {
return false;
}
boolean isAlarmForHigh() {
BgReading bgReading = MainApp.getDbHelper().lastBg();
if (bgReading == null)
@ -192,11 +209,13 @@ public class Notification {
return false;
}
public static boolean isAlarmForStaleData(){
public static boolean isAlarmForStaleData() {
long snoozedTo = SP.getLong("snoozedTo", 0L);
if(snoozedTo != 0L){
if(System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) {
//log.debug("Alarm is snoozed for next "+(SP.getLong("snoozedTo", 0L)-System.currentTimeMillis())/1000+" seconds");
if (snoozedTo != 0L) {
if (System.currentTimeMillis() < SP.getLong("snoozedTo", 0L)) {
// log.debug("Alarm is snoozed for next "+(SP.getLong("snoozedTo",
// 0L)-System.currentTimeMillis())/1000+" seconds");
return false;
}
}
@ -204,24 +223,26 @@ public class Notification {
if (bgReading == null)
return false;
long bgReadingAgo = System.currentTimeMillis() - bgReading.date;
int bgReadingAgoMin = (int) (bgReadingAgo / (1000 * 60));
int bgReadingAgoMin = (int)(bgReadingAgo / (1000 * 60));
// Added for testing
// bgReadingAgoMin = 20;
boolean openAPSEnabledAlerts = NSSettingsStatus.getInstance().openAPSEnabledAlerts();
//log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin);
//log.debug("Stale alarm snoozed to: "+(System.currentTimeMillis() - snoozedTo)/60000L);
// log.debug("bgReadingAgoMin value is:"+bgReadingAgoMin);
// log.debug("Stale alarm snoozed to: "+(System.currentTimeMillis() - snoozedTo)/60000L);
Double threshold = NSSettingsStatus.getInstance().getThreshold("alarmTimeagoWarnMins");
//log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts);
// if no thresshold from Ns get it loccally
if(threshold == null) threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue,15D);
// No threshold of OpenAPS Alarm so using the one for BG
// Added OpenAPSEnabledAlerts to alarm check
if((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false))||(bgReadingAgoMin > threshold && openAPSEnabledAlerts)){
// log.debug("OpenAPS Alerts enabled: "+openAPSEnabledAlerts);
// if no thresshold from Ns get it loccally
if (threshold == null)
threshold = SP.getDouble(R.string.key_nsalarm_staledatavalue, 15D);
// No threshold of OpenAPS Alarm so using the one for BG
// Added OpenAPSEnabledAlerts to alarm check
if ((bgReadingAgoMin > threshold && SP.getBoolean(R.string.key_nsalarm_staledata, false))
|| (bgReadingAgoMin > threshold && openAPSEnabledAlerts)) {
return true;
}
//snoozing for threshold
SP.putLong("snoozedTo", (long) (bgReading.date + (threshold * 1000 * 60L)));
//log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds");
// snoozing for threshold
SP.putLong("snoozedTo", (long)(bgReading.date + (threshold * 1000 * 60L)));
// log.debug("New bg data is available Alarm is snoozed for next "+threshold*1000*60+" seconds");
return false;
}
}

View file

@ -27,11 +27,10 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpDriverState;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpCommon.driver.PumpDriverInterface;
import info.nightscout.androidaps.plugins.Treatments.Treatment;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
@ -47,17 +46,20 @@ import info.nightscout.utils.DecimalFormatter;
public abstract class PumpPluginAbstract extends PluginBase implements PumpInterface, ConstraintsInterface {
protected static final PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult().success(false)
.enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump));
.enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump_driver));
protected static final PumpEnactResult OPERATION_NOT_YET_SUPPORTED = new PumpEnactResult().success(false)
.enacted(false).comment(MainApp.gs(R.string.pump_operation_not_yet_supported_by_pump));
// protected PumpStatus pumpStatusData;
private static final Logger LOG = LoggerFactory.getLogger(PumpPluginAbstract.class);
protected PumpDescription pumpDescription = new PumpDescription();
protected PumpDriverInterface pumpDriver;
// protected PumpDriverInterface pumpDriver;
protected PumpStatus pumpStatus;
protected String internalName;
protected ServiceConnection serviceConnection = null;
protected boolean serviceRunning = false;
protected boolean isInitialized = false;
protected PumpDriverState pumpState = PumpDriverState.NotInitialized;
protected boolean displayConnectionMessages = false;
// protected PumpPluginAbstract(PumpDriverInterface pumpDriverInterface, //
@ -77,15 +79,13 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
// );
// }
protected PumpPluginAbstract(PumpDriverInterface pumpDriverInterface, //
String internalName, //
PluginDescription pluginDescription, PumpType pumpType //
) {
protected PumpPluginAbstract(PluginDescription pluginDescription, PumpType pumpType) {
super(pluginDescription);
LOG.error("After super called.");
this.pumpDriver = pumpDriverInterface;
// this.pumpDriver = pumpDriverInterface;
this.internalName = internalName;
LOG.error("Before Init Pump Statis Data called.");
@ -98,7 +98,10 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
LOG.error("Before pumpDriver");
this.pumpDriver.initDriver(this.pumpStatus, this.pumpDescription);
// this.pumpDriver.initDriver(this.pumpStatus, this.pumpDescription);
// initPumpStatusData();
}
@ -157,101 +160,126 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public PumpStatus getPumpStatusData() {
return pumpDriver.getPumpStatusData();
return pumpStatus;
}
public boolean isInitialized() {
return pumpDriver.isInitialized();
return pumpState != PumpDriverState.NotInitialized;
}
public boolean isSuspended() {
return pumpDriver.isSuspended();
return pumpState == PumpDriverState.Suspended;
}
public boolean isBusy() {
return pumpDriver.isBusy();
return pumpState == PumpDriverState.Busy;
}
public boolean isConnected() {
return pumpDriver.isConnected();
if (displayConnectionMessages)
LOG.warn("isConnected [PumpPluginAbstract].");
return PumpDriverState.isConnected(pumpState);
}
public boolean isConnecting() {
return pumpDriver.isConnecting();
if (displayConnectionMessages)
LOG.warn("isConnecting [PumpPluginAbstract].");
return pumpState == PumpDriverState.Connecting;
}
public void connect(String reason) {
pumpDriver.connect(reason);
if (displayConnectionMessages)
LOG.warn("connect (reason={}) [PumpPluginAbstract] - Not implemented.", reason);
}
public void disconnect(String reason) {
pumpDriver.disconnect(reason);
if (displayConnectionMessages)
LOG.warn("disconnect (reason={}) [PumpPluginAbstract] - Not implemented.", reason);
}
public void stopConnecting() {
pumpDriver.stopConnecting();
if (displayConnectionMessages)
LOG.warn("stopConnecting [PumpPluginAbstract] - Not implemented.");
}
@Override
public boolean isHandshakeInProgress() {
if (displayConnectionMessages)
LOG.warn("isHandshakeInProgress [PumpPluginAbstract] - Not implemented.");
return false;
}
@Override
public void finishHandshaking() {
if (displayConnectionMessages)
LOG.warn("finishHandshaking [PumpPluginAbstract] - Not implemented.");
}
public void getPumpStatus() {
pumpDriver.getPumpStatus();
LOG.warn("getPumpStatus [PumpPluginAbstract] - Not implemented.");
}
// Upload to pump new basal profile
public PumpEnactResult setNewBasalProfile(Profile profile) {
return pumpDriver.setNewBasalProfile(profile);
LOG.warn("setNewBasalProfile [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public boolean isThisProfileSet(Profile profile) {
return pumpDriver.isThisProfileSet(profile);
LOG.warn("isThisProfileSet [PumpPluginAbstract] - Not implemented.");
return true;
}
public long lastDataTime() {
return pumpDriver.lastDataTime();
LOG.warn("lastDataTime [PumpPluginAbstract].");
return pumpStatus.lastConnection;
}
public double getBaseBasalRate() {
return pumpDriver.getBaseBasalRate();
LOG.warn("getBaseBasalRate [PumpPluginAbstract] - Not implemented.");
return 0.0d;
} // base basal rate, not temp basal
// public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
// return pumpDriver.deliverTreatment(detailedBolusInfo);
// }
public void stopBolusDelivering() {
pumpDriver.stopBolusDelivering();
LOG.warn("stopBolusDelivering [PumpPluginAbstract] - Not implemented.");
}
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
return pumpDriver.setTempBasalAbsolute(absoluteRate, durationInMinutes, profile, enforceNew);
LOG.warn("setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
return pumpDriver.setTempBasalPercent(percent, durationInMinutes, profile, enforceNew);
LOG.warn("setTempBasalPercent [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
return pumpDriver.setExtendedBolus(insulin, durationInMinutes);
LOG.warn("setExtendedBolus [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@ -259,13 +287,14 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
// when the cancel request is requested by the user (forced), the pump should always do a real cancel
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
return pumpDriver.cancelTempBasal(enforceNew);
LOG.warn("cancelTempBasal [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public PumpEnactResult cancelExtendedBolus() {
LOG.warn("deviceID [PumpPluginAbstract] - Not implemented.");
return OPERATION_NOT_YET_SUPPORTED;
LOG.warn("cancelExtendedBolus [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@ -298,67 +327,11 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
@Override
public PumpEnactResult loadTDDs() {
return this.pumpDriver.loadTDDs();
LOG.warn("loadTDDs [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
// Constraints interface
// @Override
// public boolean isLoopEnabled() {
// return true;
// }
//
// @Override
// public boolean isClosedModeEnabled() {
// return true;
// }
//
// @Override
// public boolean isAutosensModeEnabled() {
// return true;
// }
//
// @Override
// public boolean isAMAModeEnabled() {
// return true;
// }
//
// @Override
// public boolean isSMBModeEnabled() {
// return true;
// }
//
// @Override
// public Double applyBasalConstraints(Double absoluteRate) {
// this.pumpStatus.constraintBasalRateAbsolute = absoluteRate;
// return absoluteRate;
// }
//
// @Override
// public Integer applyBasalConstraints(Integer percentRate) {
// this.pumpStatus.constraintBasalRatePercent = percentRate;
// return percentRate;
// }
//
// @Override
// public Double applyBolusConstraints(Double insulin) {
// this.pumpStatus.constraintBolus = insulin;
// return insulin;
// }
//
// @Override
// public Integer applyCarbsConstraints(Integer carbs) {
// this.pumpStatus.constraintCarbs = carbs;
// return carbs;
// }
//
// @Override
// public Double applyMaxIOBConstraints(Double maxIob) {
// this.pumpStatus.constraintMaxIob = maxIob;
// return maxIob;
// }
@Override
public JSONObject getJSONStatus(Profile profile, String profileName) {
@ -483,23 +456,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
protected abstract void triggerUIChange();
public PumpEnactResult getOperationNotSupportedWithCustomText(int resourceId) {
public static PumpEnactResult getOperationNotSupportedWithCustomText(int resourceId) {
return new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(resourceId));
}
// Profile interface
// @Nullable
// public ProfileStore getProfile() {
// return this.pumpStatus.profileStore;
// }
//
// public String getUnits() {
// return this.pumpStatus.units;
// }
//
// public String getProfileName() {
// return this.pumpStatus.activeProfileName;
// }
}

View file

@ -18,6 +18,8 @@ public abstract class PumpStatus {
// connection
public LocalDateTime lastDataTime;
public long lastConnection = 0L;
public long previousConnection = 0L; // here should be stored last connection of previous session (so needs to be
// read before lastConnection is modified for first time).
// last bolus
public Date lastBolusTime;

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.PumpCommon.defs;
/**
* Created by andy on 10/15/18.
*/
public enum PumpDriverState {
NotInitialized, //
Connecting, //
Initialized, //
Busy, //
Suspended, //
;
public static boolean isConnected(PumpDriverState pumpState) {
return pumpState == Initialized || pumpState == Busy || pumpState == Suspended;
}
}

View file

@ -21,6 +21,7 @@ import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@ -36,19 +37,23 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.GattAttributes;
import info.nightscout.androidaps.plugins.PumpCommon.utils.LocationHelper;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPumpConfigurationChanged;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
// IMPORTANT: This activity needs to be called from RileyLinkSelectPreference (see pref_medtronic.xml as example)
public class RileyLinkBLEScanActivity extends AppCompatActivity {
private static final Logger LOG = LoggerFactory.getLogger(RileyLinkBLEScanActivity.class);
@ -85,38 +90,36 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity {
mLeDeviceListAdapter = new LeDeviceListAdapter();
listBTScan = (ListView)findViewById(R.id.rileylink_listBTScan);
listBTScan.setAdapter(mLeDeviceListAdapter);
listBTScan.setOnItemClickListener(new AdapterView.OnItemClickListener() {
listBTScan.setOnItemClickListener((parent, view, position, id) -> {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView textview = (TextView)view.findViewById(R.id.rileylink_device_address);
String bleAddress = textview.getText().toString();
SP.putString(RileyLinkConst.Prefs.RileyLinkAddress, bleAddress);
// Context applicationContext = MainApp.instance().getApplicationContext();
// applicationContext.get
// RileyLinkBLEScanActivity.this.findPreference("pref_key");
// EditTextPreference viewById =
// (EditTextPreference)super.findPreference(R.id.rileylink_mac_address_mdt);
// //Notify that we have a new rileylinkAddressKey
// RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_rileylinkAddressKey);
//
// LOG.debug("New rileylinkAddressKey: " + bleAddress);
//
// //Notify that we have a new pumpIDKey
// RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.INTENT_NEW_pumpIDKey);
finish();
// stop scanning if still active
if (mScanning) {
mScanning = false;
mLEScanner.stopScan(mScanCallback2);
}
TextView textview = (TextView)view.findViewById(R.id.rileylink_device_address);
String bleAddress = textview.getText().toString();
SP.putString(RileyLinkConst.Prefs.RileyLinkAddress, bleAddress);
RileyLinkUtil.getRileyLinkSelectPreference().setSummary(bleAddress);
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
pumpStatus.verifyConfiguration(); // force reloading of address
MainApp.bus().post(new EventMedtronicPumpConfigurationChanged());
// RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkNewAddressSet);
finish();
});
toolbarBTScan = (Toolbar)findViewById(R.id.rileylink_toolbarBTScan);
toolbarBTScan.setTitle(R.string.rileylink_scanner_title);
setSupportActionBar(toolbarBTScan);
// TODO remove snackbar, stop needs to be on same button as start
snackbar = Snackbar.make(findViewById(R.id.RileyLinkScan), "Scanning...", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("STOP", new View.OnClickListener() {
@ -179,7 +182,9 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Will request that GPS be enabled for devices running Marshmallow or newer.
LocationHelper.requestLocationForBluetooth(this);
if (!isLocationEnabled(this)) {
LocationHelper.requestLocationForBluetooth(this);
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
@ -198,6 +203,20 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity {
}
public boolean isLocationEnabled(Context context) {
final LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if (manager != null
&& (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) || manager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
return true;
}
// otherwise return false
return false;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@ -304,6 +323,9 @@ public class RileyLinkBLEScanActivity extends AppCompatActivity {
private void scanLeDevice(final boolean enable) {
// FIXME
if (enable) {
mLeDeviceListAdapter.clear();

View file

@ -1,61 +0,0 @@
package info.nightscout.androidaps.plugins.PumpCommon.driver;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
/**
* Created by andy on 4/28/18.
*/
public abstract class PumpDriverAbstract implements PumpDriverInterface {
protected static final PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult().success(false)
.enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump));
protected static final PumpEnactResult OPERATION_NOT_YET_SUPPORTED = new PumpEnactResult().success(false)
.enacted(false).comment(MainApp.gs(R.string.pump_operation_not_yet_supported_by_pump));
protected PumpDescription pumpDescription;
protected PumpStatus pumpStatusData;
protected PumpDriverAbstract() {
}
public void initDriver(PumpStatus pumpStatus, PumpDescription pumpDescription) {
this.pumpDescription = pumpDescription;
this.pumpStatusData = pumpStatus;
}
@Override
public String deviceID() {
return null;
}
@Override
public PumpStatus getPumpStatusData() {
return this.pumpStatusData;
}
@Override
public PumpDescription getPumpDescription() {
return pumpDescription;
}
// @Override
// public Date lastDataTime() {
// if (this.pumpStatusData == null || this.pumpStatusData.lastDataTime == null) {
// return new Date();
// }
//
// return this.pumpStatusData.lastDataTime.toDate();
// }
}

View file

@ -1,18 +0,0 @@
package info.nightscout.androidaps.plugins.PumpCommon.driver;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
/**
* Created by andy on 4/28/18.
*/
public interface PumpDriverInterface extends PumpInterface {
void initDriver(PumpStatus pumpStatus, PumpDescription pumpDescription);
PumpStatus getPumpStatusData();
}

View file

@ -75,12 +75,12 @@ public abstract class RileyLinkCommunicationManager {
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.
rememberLastGoodDeviceCommunicationTime();
} else {
LOG.warn("Response is invalid. !!! - ", rfSpyResponse.wasInterrupted(), rfSpyResponse.wasTimeout());
LOG.warn("Response is invalid ! [interrupted={}, timeout={}]", rfSpyResponse.wasInterrupted(),
rfSpyResponse.wasTimeout());
if (rfSpyResponse.wasTimeout()) {
timeoutCount++;
@ -98,6 +98,7 @@ public abstract class RileyLinkCommunicationManager {
if (showPumpMessages) {
LOG.info("Received:" + ByteUtil.shortHexString(rfSpyResponse.getRadioResponse().getPayload()));
}
return response;
}

View file

@ -29,7 +29,7 @@ public class RileyLinkConst {
public class Prefs {
public static final String PrefPrefix = "pref_rileylink_";
public static final String RileyLinkAddress = PrefPrefix + "mac_address";
public static final String RileyLinkAddress = PrefPrefix + "mac_address"; // pref_rileylink_mac_address
public static final String LastGoodDeviceCommunicationTime = Prefix + "lastGoodDeviceCommunicationTime";
public static final String LastGoodDeviceFrequency = Prefix + "LastGoodDeviceFrequency";

View file

@ -29,6 +29,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.S
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult;
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.PumpCommon.ui.RileyLinkSelectPreference;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
@ -56,6 +57,7 @@ public class RileyLinkUtil {
// Broadcasts: RileyLinkBLE, RileyLinkService,
private static RileyLinkTargetDevice targetDevice;
private static RileyLinkEncodingType encoding;
private static RileyLinkSelectPreference rileyLinkSelectPreference;
public static void setContext(Context contextIn) {
@ -278,4 +280,16 @@ public class RileyLinkUtil {
RileyLinkUtil.targetDevice = targetDevice;
}
public static void setRileyLinkSelectPreference(RileyLinkSelectPreference rileyLinkSelectPreference) {
RileyLinkUtil.rileyLinkSelectPreference = rileyLinkSelectPreference;
}
public static RileyLinkSelectPreference getRileyLinkSelectPreference() {
return rileyLinkSelectPreference;
}
}

View file

@ -81,20 +81,7 @@ public class RFSpy {
// Here should go generic RL initialisation + protocol adjustments depending on
// firmware version
public void initializeRileyLink() {
// We have to call raw version of communication to get firmware version
// So that we can adjust other commands accordingly afterwords
byte[] getVersionRaw = getByteArray(RileyLinkCommandType.GetVersion.code);
byte[] response = writeToDataRaw(getVersionRaw, 5000);
if (response != null) { // && response[0] == (byte) 0xDD) {
// This throws an exception if version not supported, we should treat exceptions somehow
// and show "Not supported firmware" message in UI
RileyLinkFirmwareVersion version = RileyLinkFirmwareVersion.getByVersionString(StringUtil
.fromBytes(response));
this.firmwareVersion = version;
}
firmwareVersion = getFirmwareVersion();
bleVersion = getVersion();
}
@ -119,6 +106,31 @@ public class RFSpy {
}
public RileyLinkFirmwareVersion getFirmwareVersion() {
for (int i = 0; i < 5; i++) {
// We have to call raw version of communication to get firmware version
// So that we can adjust other commands accordingly afterwords
byte[] getVersionRaw = getByteArray(RileyLinkCommandType.GetVersion.code);
byte[] response = writeToDataRaw(getVersionRaw, 5000);
if (response != null) { // && response[0] == (byte) 0xDD) {
String versionString = StringUtil.fromBytes(response);
RileyLinkFirmwareVersion version = RileyLinkFirmwareVersion.getByVersionString(StringUtil
.fromBytes(response));
LOG.trace("Firmware Version string: {}, resolved to {}.", versionString, version);
if (version != RileyLinkFirmwareVersion.UnknownVersion)
return version;
SystemClock.sleep(1000);
}
}
return RileyLinkFirmwareVersion.UnknownVersion;
}
private byte[] writeToDataRaw(byte[] bytes, int responseTimeout_ms) {
SystemClock.sleep(100);
// FIXME drain read queue?

View file

@ -6,42 +6,20 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs;
public enum RileyLinkTargetFrequency {
Medtronic_WorldWide(868.25, 868.65, 0.05), //
Medtronic_US(916.45, 916.80, 0.05), //
Omnipod(433.91, 433.91, 0.00), //
Medtronic_WorldWide(868.25, 868.3, 868.35, 868.4, 868.45, 868.5, 868.55, 868.6, 868.65), //
Medtronic_US(916.45, 916.5, 916.55, 916.6, 916.65, 916.7, 916.75, 916.8), //
Omnipod(433.91), //
;
double minFrequency;
double maxFrequency;
double step;
double[] frequencies;
RileyLinkTargetFrequency(double minFrequency, double maxFrequency, double step) {
this.minFrequency = minFrequency;
this.maxFrequency = maxFrequency;
this.step = step;
RileyLinkTargetFrequency(double... frequencies) {
this.frequencies = frequencies;
}
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];
for (int i = 0; i < count; i++) {
freq[i] = (minFrequency + (i * step));
}
return freq;
return frequencies;
}
}

View file

@ -58,7 +58,7 @@ public enum RileyLinkServiceState {
public static boolean isReady(RileyLinkServiceState serviceState) {
return (serviceState == RileyLinkReady || serviceState == PumpConnectorReady);
return (/* serviceState == RileyLinkReady || */serviceState == PumpConnectorReady);
}
@ -79,7 +79,8 @@ public enum RileyLinkServiceState {
return (this == RileyLinkServiceState.BluetoothInitializing || //
// this == RileyLinkServiceState.BluetoothError || //
this == RileyLinkServiceState.BluetoothReady || //
this == RileyLinkServiceState.RileyLinkInitializing //
this == RileyLinkServiceState.RileyLinkInitializing || //
this == RileyLinkReady
// this == RileyLinkServiceState.RileyLinkError
);
}

View file

@ -11,7 +11,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
import android.support.v4.content.LocalBroadcastManager;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager;
@ -40,22 +39,24 @@ import info.nightscout.utils.SP;
*/
public abstract class RileyLinkService extends Service {
protected static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock";
private static final Logger LOG = LoggerFactory.getLogger(RileyLinkService.class);
protected static volatile PowerManager.WakeLock lockStatic = null;
// Our hardware/software connection
public RileyLinkBLE rileyLinkBLE; // android-bluetooth management
protected BluetoothAdapter bluetoothAdapter;
protected RFSpy rfspy; // interface for RL xxx Mhz radio.
// protected boolean needBluetoothPermission = true;
// protected RileyLinkIPCConnection rileyLinkIPCConnection;
protected Context context;
// public RileyLinkCommunicationManager pumpCommunicationManager;
protected BroadcastReceiver mBroadcastReceiver;
protected RileyLinkServiceData rileyLinkServiceData;
protected RileyLinkTargetFrequency rileyLinkTargetFrequency;
// protected static final String WAKELOCKNAME = "com.gxwtech.roundtrip2.RoundtripServiceWakeLock";
// protected static volatile PowerManager.WakeLock lockStatic = null;
// Our hardware/software connection
// protected boolean needBluetoothPermission = true;
// protected RileyLinkIPCConnection rileyLinkIPCConnection;
// public RileyLinkCommunicationManager pumpCommunicationManager;
public RileyLinkService(Context context) {
super();
this.context = context;
@ -68,6 +69,9 @@ public abstract class RileyLinkService extends Service {
}
/**
* Get Encoding for RileyLink communication
*/
public abstract RileyLinkEncodingType getEncoding();
@ -102,7 +106,6 @@ public abstract class RileyLinkService extends Service {
super.onDestroy();
LOG.error("I die! I die!");
// FIXME this might not work
if (rileyLinkBLE != null) {
rileyLinkBLE.disconnect(); // dispose of Gatt (disconnect and close)
rileyLinkBLE = null;
@ -122,131 +125,126 @@ public abstract class RileyLinkService extends Service {
@Override
public void onReceive(Context context, Intent intent) {
/*
* here we can listen for local broadcasts, then send ourselves
* a specific intent to deal with them, if we wish
*/
if (intent == null) {
LOG.error("onReceive: received null intent");
return;
}
String action = intent.getAction();
if (action == null) {
LOG.error("onReceive: null action");
} else {
String action = intent.getAction();
if (action == null) {
LOG.error("onReceive: null action");
} else {
if (action.equals(RileyLinkConst.Intents.BluetoothConnected)) {
// rileyLinkIPCConnection.sendNotification(new
// ServiceNotification(RT2Const.IPC.MSG_note_FindingRileyLink), null);
ServiceTaskExecutor.startTask(new DiscoverGattServicesTask());
} 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(RileyLinkConst.Intents.RileyLinkReady)) {
LOG.warn("MedtronicConst.Intents.RileyLinkReady");
// FIXME
// rileyLinkIPCConnection.sendNotification(new
// ServiceNotification(RT2Const.IPC.MSG_note_WakingPump), null);
rileyLinkBLE.enableNotifications();
rfspy.startReader(); // call startReader from outside?
rfspy.initializeRileyLink();
String bleVersion = rfspy.getBLEVersionCached();
RileyLinkFirmwareVersion rlVersion = rfspy.getRLVersionCached();
LOG.debug("RfSpy version (BLE113): " + bleVersion);
rileyLinkServiceData.versionBLE113 = bleVersion;
LOG.debug("RfSpy Radio version (CC110): " + rlVersion.name());
rileyLinkServiceData.versionCC110 = rlVersion;
ServiceTask task = new InitializePumpManagerTask();
ServiceTaskExecutor.startTask(task);
LOG.info("Announcing RileyLink open For business");
} 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)) {
if (getRileyLinkTargetDevice().isTuneUpEnabled()) {
doTuneUpDevice();
}
} else if (action.startsWith("MSG_PUMP_")) {
handlePumpSpecificIntents(intent);
} else if (RileyLinkConst.IPC.MSG_ServiceCommand.equals(action)) {
handleIncomingServiceTransport(intent);
} 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 (action.equals(RileyLinkConst.Intents.RileyLinkDisconnect)) {
disconnectRileyLink();
if (action.equals(RileyLinkConst.Intents.BluetoothConnected)) {
// rileyLinkIPCConnection.sendNotification(new
// ServiceNotification(RT2Const.IPC.MSG_note_FindingRileyLink), null);
ServiceTaskExecutor.startTask(new DiscoverGattServicesTask());
} else if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkError,
RileyLinkError.RileyLinkUnreachable);
} else {
RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError,
RileyLinkError.BluetoothDisabled);
}
} else if (action.equals(RileyLinkConst.Intents.RileyLinkReady)) {
LOG.warn("BroadcastReceive: RileyLink Ready");
/*
* else if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) {
* Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey);
* if (bundle != null) {
* ServiceTransport transport = new ServiceTransport(bundle);
* //rileyLinkIPCConnection.sendTransport(transport, transport.getSenderHashcode());
* //RileyLinkUtil.send
* } else {
* LOG.error("sessionCompleted: no bundle!");
* }
* }
*/
rileyLinkBLE.enableNotifications();
rfspy.startReader(); // call startReader from outside?
/*
* else
*
* if (case RT2Const.local.INTENT_serviceConnected:
* case RT2Const.local.INTENT_NEW_rileylinkAddressKey:
* showIdle();
* /**
* Client MUST send a "UseThisRileylink" message because it asserts that
* the user has given explicit permission to use bluetooth.
*
* We can change the format so that it is a simple "bluetooth OK" message,
* rather than an explicit address of a Rileylink, and the Service can
* use the last known good value. But the kick-off of bluetooth ops must
* come from an Activity.
*/
/*
* String RileylinkBLEAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, "");
* if (RileylinkBLEAddress.equals("")) {
* // TODO: 11/07/2016 @TIM UI message for user
* Log.e(TAG, "No Rileylink BLE Address saved in app");
* } else {
* //showBusy("Configuring Service", 50);
* MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress);
* }
* break;
* case RT2Const.local.INTENT_NEW_pumpIDKey:
* MainApp.getServiceClientConnection().sendPUMP_useThisDevice(SP.getString(MedtronicConst.Prefs.
* PumpSerial, ""));
* break;
*/
rfspy.initializeRileyLink();
String bleVersion = rfspy.getBLEVersionCached();
RileyLinkFirmwareVersion rlVersion = rfspy.getRLVersionCached();
else {
LOG.error("Unhandled broadcast: action=" + action);
LOG.debug("RfSpy version (BLE113): " + bleVersion);
rileyLinkServiceData.versionBLE113 = bleVersion;
LOG.debug("RfSpy Radio version (CC110): " + rlVersion.name());
rileyLinkServiceData.versionCC110 = rlVersion;
ServiceTask task = new InitializePumpManagerTask(getRileyLinkTargetDevice());
ServiceTaskExecutor.startTask(task);
LOG.info("Announcing RileyLink open For business");
} else if (action.equals(RileyLinkConst.Intents.BluetoothReconnected)) {
LOG.debug("BroadcastReceive: 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) || //
action.equals(RileyLinkConst.IPC.MSG_PUMP_quickTune)) {
if (getRileyLinkTargetDevice().isTuneUpEnabled()) {
doTuneUpDevice();
}
} else if (action.startsWith("MSG_PUMP_")) {
handlePumpSpecificIntents(intent);
} else if (RileyLinkConst.IPC.MSG_ServiceCommand.equals(action)) {
handleIncomingServiceTransport(intent);
} 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 (action.equals(RileyLinkConst.Intents.RileyLinkDisconnect)) {
disconnectRileyLink();
}
/*
* else if (RT2Const.serviceLocal.INTENT_sessionCompleted.equals(action)) {
* Bundle bundle = intent.getBundleExtra(RT2Const.IPC.bundleKey);
* if (bundle != null) {
* ServiceTransport transport = new ServiceTransport(bundle);
* //rileyLinkIPCConnection.sendTransport(transport, transport.getSenderHashcode());
* //RileyLinkUtil.send
* } else {
* LOG.error("sessionCompleted: no bundle!");
* }
* }
*/
/*
* else
*
* if (case RT2Const.local.INTENT_serviceConnected:
* case RT2Const.local.INTENT_NEW_rileylinkAddressKey:
* showIdle();
* /**
* Client MUST send a "UseThisRileylink" message because it asserts that
* the user has given explicit permission to use bluetooth.
*
* We can change the format so that it is a simple "bluetooth OK" message,
* rather than an explicit address of a Rileylink, and the Service can
* use the last known good value. But the kick-off of bluetooth ops must
* come from an Activity.
*/
/*
* String RileylinkBLEAddress = SP.getString(MedtronicConst.Prefs.RileyLinkAddress, "");
* if (RileylinkBLEAddress.equals("")) {
* // TODO: 11/07/2016 @TIM UI message for user
* Log.e(TAG, "No Rileylink BLE Address saved in app");
* } else {
* //showBusy("Configuring Service", 50);
* MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress);
* }
* break;
* case RT2Const.local.INTENT_NEW_pumpIDKey:
* MainApp.getServiceClientConnection().sendPUMP_useThisDevice(SP.getString(MedtronicConst.Prefs.
* PumpSerial, ""));
* break;
*/
else {
LOG.error("Unhandled broadcast: action=" + action);
}
}
}
};
@ -293,24 +291,7 @@ public abstract class RileyLinkService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
LOG.debug("onStartCommand");
// if (intent != null) {
// PowerManager.WakeLock lock = getLock(this.getApplicationContext());
//
// if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) {
// lock.acquire();
// }
//
// // This will end up running onHandleIntent
// super.onStartCommand(intent, flags, startId);
// } else {
// LOG.error("Received null intent?");
// }
RileyLinkUtil.setContext(getApplicationContext());
// bluetoothInit();
// return (START_REDELIVER_INTENT | START_STICKY);
return (START_STICKY);
}
@ -328,7 +309,7 @@ public abstract class RileyLinkService extends Service {
if (!bluetoothAdapter.isEnabled()) {
sendBLERequestForAccess();
// sendBLERequestForAccess();
LOG.error("Bluetooth is not enabled.");
RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled);
@ -381,18 +362,6 @@ public abstract class RileyLinkService extends Service {
}
//
// public synchronized static PowerManager.WakeLock getLock(Context context) {
// if (lockStatic == null) {
// PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
//
// lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCKNAME);
// lockStatic.setReferenceCounted(true);
// }
//
// return lockStatic;
// }
public void sendServiceTransportResponse(ServiceTransport transport, ServiceResult serviceResult) {
// get the key (hashcode) of the client who requested this
/*
@ -414,15 +383,6 @@ public abstract class RileyLinkService extends Service {
}
protected void sendBLERequestForAccess() {
// FIXME
// serviceConnection.sendMessage(RT2Const.IPC.MSG_BLE_requestAccess);
// Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
// startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
// FIXME: This needs to be run in a session so that is interruptable, has a separate thread, etc.
public void doTuneUpDevice() {
@ -472,13 +432,16 @@ public abstract class RileyLinkService extends Service {
public void disconnectRileyLink() {
if (this.rileyLinkBLE.isConnected()) {
if (this.rileyLinkBLE != null && this.rileyLinkBLE.isConnected()) {
this.rileyLinkBLE.disconnect();
rileyLinkServiceData.rileylinkAddress = null;
}
}
/**
* Get Target Device for Service
*/
public RileyLinkTargetDevice getRileyLinkTargetDevice() {
return this.rileyLinkServiceData.targetDevice;
}

View file

@ -6,6 +6,7 @@ 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.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.ServiceTransport;
import info.nightscout.utils.SP;
@ -17,10 +18,12 @@ import info.nightscout.utils.SP;
public class InitializePumpManagerTask extends ServiceTask {
private static final String TAG = "InitPumpManagerTask";
private RileyLinkTargetDevice targetDevice;
public InitializePumpManagerTask() {
public InitializePumpManagerTask(RileyLinkTargetDevice targetDevice) {
super();
this.targetDevice = targetDevice;
}
@ -32,7 +35,6 @@ public class InitializePumpManagerTask extends ServiceTask {
@Override
public void run() {
// FIXME
double lastGoodFrequency = SP.getDouble(RileyLinkConst.Prefs.LastGoodDeviceFrequency, 0.0d);
lastGoodFrequency = Math.round(lastGoodFrequency * 1000d) / 1000d;
@ -41,18 +43,20 @@ public class InitializePumpManagerTask extends ServiceTask {
if ((lastGoodFrequency > 0.0d)
&& RileyLinkUtil.getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) {
RileyLinkUtil.setServiceState(RileyLinkServiceState.RileyLinkReady);
Log.i(TAG, String.format("Setting radio frequency to %.2fMHz", lastGoodFrequency));
RileyLinkUtil.getRileyLinkCommunicationManager().setRadioFrequencyForPump(lastGoodFrequency);
boolean foundThePump = RileyLinkUtil.getRileyLinkCommunicationManager().tryToConnectToDevice();
// FIXME maybe remove in AAPS
if (foundThePump) {
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady);
// RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpFound), null);
} else {
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorError,
RileyLinkError.NoContactWithDevice);
RileyLinkUtil.sendBroadcastMessage(RileyLinkConst.IPC.MSG_PUMP_tunePump);
// RileyLinkUtil.sendNotification(new ServiceNotification(RT2Const.IPC.MSG_PUMP_pumpLost), null);
}

View file

@ -0,0 +1,40 @@
package info.nightscout.androidaps.plugins.PumpCommon.ui;
import android.content.Context;
import android.preference.Preference;
import android.util.AttributeSet;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
/**
* Created by andy on 10/18/18.
*/
public class RileyLinkSelectPreference extends Preference {
public RileyLinkSelectPreference(Context context) {
super(context);
setInitialSummaryValue();
MedtronicUtil.setRileyLinkSelectPreference(this);
}
public RileyLinkSelectPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setInitialSummaryValue();
MedtronicUtil.setRileyLinkSelectPreference(this);
}
private void setInitialSummaryValue() {
String value = SP.getString("pref_rileylink_mac_address", null);
setSummary(value == null ? MainApp.gs(R.string.rileylink_error_address_not_set_short) : value);
}
}

View file

@ -5,7 +5,6 @@ import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
@ -43,6 +42,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandTyp
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPumpConfigurationChanged;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPumpValuesChanged;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
@ -55,6 +55,7 @@ import info.nightscout.utils.SetWarnColor;
public class MedtronicFragment extends SubscriberFragment {
private static Logger LOG = LoggerFactory.getLogger(MedtronicFragment.class);
@BindView(R.id.medtronic_lastconnection)
TextView lastConnectionView;
@BindView(R.id.medtronic_lastbolus)
@ -85,6 +86,10 @@ public class MedtronicFragment extends SubscriberFragment {
@BindView(R.id.medtronic_refresh)
Button refreshButton;
private Handler loopHandler = new Handler();
private static Activity localActivity;
static Button refreshButtonStatic;
private Runnable refreshLoop = new Runnable() {
@Override
@ -128,6 +133,8 @@ public class MedtronicFragment extends SubscriberFragment {
pumpStatusIconView.setTextSize(14);
pumpStatusIconView.setText("{fa-bed}");
refreshButtonStatic = refreshButton;
return view;
} catch (Exception e) {
Crashlytics.logException(e);
@ -152,7 +159,13 @@ public class MedtronicFragment extends SubscriberFragment {
@Override
public void run() {
refreshButton.setEnabled(true);
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(() -> {
refreshButton.setEnabled(true);
});
}
}
});
}
@ -170,23 +183,34 @@ public class MedtronicFragment extends SubscriberFragment {
}
public static void refreshButtonEnabled(boolean enable) {
if (localActivity != null) {
localActivity.runOnUiThread(() -> {
if (refreshButtonStatic != null) {
refreshButtonStatic.setEnabled(enable);
}
});
}
}
public static Activity getCustomActivity() {
return localActivity;
}
@Subscribe
public void onStatusEvent(final EventMedtronicDeviceStatusChange eventStatusChange) {
LOG.info("onStatusEvent(EventMedtronicDeviceStatusChange): {}", eventStatusChange);
Activity activity = getActivity();
// final String status = c.textStatus();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
setDeviceStatus(pumpStatus);
}
localActivity = activity;
activity.runOnUiThread(() -> {
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
setDeviceStatus(pumpStatus);
});
}
}
@ -235,7 +259,7 @@ public class MedtronicFragment extends SubscriberFragment {
case NeverContacted:
case WakingUp:
case ProblemContacting:
case PumpUnreachable:
case ErrorWhenCommunicating:
case TimeoutWhenCommunicating:
case InvalidConfiguration:
@ -311,6 +335,15 @@ public class MedtronicFragment extends SubscriberFragment {
}
@Subscribe
public void onStatusEvent(final EventMedtronicPumpConfigurationChanged s) {
LOG.error("EventMedtronicPumpConfigurationChanged triggered");
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
pumpStatus.verifyConfiguration();
updateGUI();
}
@Subscribe
public void onStatusEvent(final EventTempBasalChange s) {
updateGUI();
@ -334,85 +367,97 @@ public class MedtronicFragment extends SubscriberFragment {
protected void updateGUI() {
Activity activity = getActivity();
if (activity != null && basaBasalRateView != null)
activity.runOnUiThread(new Runnable() {
activity.runOnUiThread(() -> {
@SuppressLint("SetTextI18n")
@Override
public void run() {
localActivity = activity;
MedtronicPumpPlugin plugin = (MedtronicPumpPlugin)MedtronicPumpPlugin.getPlugin();
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
MedtronicPumpPlugin plugin = (MedtronicPumpPlugin)MedtronicPumpPlugin.getPlugin();
MedtronicPumpStatus pumpStatus = MedtronicUtil.getPumpStatus();
setDeviceStatus(pumpStatus);
setDeviceStatus(pumpStatus);
// last connection
String minAgo = DateUtil.minAgo(pumpStatus.lastConnection);
long min = (System.currentTimeMillis() - pumpStatus.lastConnection) / 1000 / 60;
if (pumpStatus.lastConnection + 60 * 1000 > System.currentTimeMillis()) {
lastConnectionView.setText(R.string.combo_pump_connected_now);
lastConnectionView.setTextColor(Color.WHITE);
} else if (pumpStatus.lastConnection + 30 * 60 * 1000 < System.currentTimeMillis()) {
// last connection
String minAgo = DateUtil.minAgo(pumpStatus.lastConnection);
long min = (System.currentTimeMillis() - pumpStatus.lastConnection) / 1000 / 60;
if (pumpStatus.lastConnection + 60 * 1000 > System.currentTimeMillis()) {
lastConnectionView.setText(R.string.combo_pump_connected_now);
lastConnectionView.setTextColor(Color.WHITE);
} else if (pumpStatus.lastConnection + 30 * 60 * 1000 < System.currentTimeMillis()) {
lastConnectionView.setText(MainApp.gs(R.string.combo_no_pump_connection, min));
lastConnectionView.setTextColor(Color.RED);
if (min < 60) {
lastConnectionView.setText(MainApp.gs(R.string.minago, min));
} else if (min < 1440) {
int h = (int)(min / 60);
lastConnectionView.setText(MainApp.gq(R.plurals.objective_hours, h, h) + " "
+ MainApp.gs(R.string.ago));
} else {
lastConnectionView.setText(minAgo);
lastConnectionView.setTextColor(Color.WHITE);
int h = (int)(min / 60);
int d = h / 24;
// h = h - (d * 24);
lastConnectionView.setText(MainApp.gq(R.plurals.objective_days, d, d) + " "
+ MainApp.gs(R.string.ago));
}
// last bolus
Double bolus = pumpStatus.lastBolusAmount;
Date bolusTime = pumpStatus.lastBolusTime;
if (bolus != null && bolusTime != null) {
long agoMsc = System.currentTimeMillis() - pumpStatus.lastBolusTime.getTime();
double bolusMinAgo = agoMsc / 60d / 1000d;
String unit = MainApp.gs(R.string.insulin_unit_shortname);
String ago;
if ((agoMsc < 60 * 1000)) {
ago = MainApp.gs(R.string.combo_pump_connected_now);
} else if (bolusMinAgo < 60) {
ago = DateUtil.minAgo(pumpStatus.lastBolusTime.getTime());
} else {
ago = DateUtil.hourAgo(pumpStatus.lastBolusTime.getTime());
}
lastBolusView.setText(MainApp.gs(R.string.combo_last_bolus, bolus, unit, ago));
} else {
lastBolusView.setText("");
}
// base basal rate
basaBasalRateView.setText("(" + (pumpStatus.activeProfileName) + ") "
+ MainApp.gs(R.string.pump_basebasalrate, plugin.getBaseBasalRate()));
// FIXME temp basal - check - maybe set as combo ??
if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
tempBasalView.setText(TreatmentsPlugin.getPlugin()
.getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
} else {
tempBasalView.setText("");
}
} else {
// v2 plugin
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
tempBasalView.setText(TreatmentsPlugin.getPlugin()
.getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
} else {
tempBasalView.setText("");
}
}
// battery
batteryView.setText("{fa-battery-" + (pumpStatus.batteryRemaining / 25) + "}");
SetWarnColor.setColorInverse(batteryView, pumpStatus.batteryRemaining, 51d, 26d);
// reservoir
reservoirView.setText(DecimalFormatter.to0Decimal(pumpStatus.reservoirRemainingUnits) + " / "
+ pumpStatus.reservoirFullUnits + " " + MainApp.gs(R.string.insulin_unit_shortname));
SetWarnColor.setColorInverse(reservoirView, pumpStatus.reservoirRemainingUnits, 50d, 20d);
errorsView.setText(pumpStatus.getErrorInfo());
lastConnectionView.setTextColor(Color.RED);
} else {
lastConnectionView.setText(minAgo);
lastConnectionView.setTextColor(Color.WHITE);
}
// last bolus
Double bolus = pumpStatus.lastBolusAmount;
Date bolusTime = pumpStatus.lastBolusTime;
if (bolus != null && bolusTime != null) {
long agoMsc = System.currentTimeMillis() - pumpStatus.lastBolusTime.getTime();
double bolusMinAgo = agoMsc / 60d / 1000d;
String unit = MainApp.gs(R.string.insulin_unit_shortname);
String ago;
if ((agoMsc < 60 * 1000)) {
ago = MainApp.gs(R.string.combo_pump_connected_now);
} else if (bolusMinAgo < 60) {
ago = DateUtil.minAgo(pumpStatus.lastBolusTime.getTime());
} else {
ago = DateUtil.hourAgo(pumpStatus.lastBolusTime.getTime());
}
lastBolusView.setText(MainApp.gs(R.string.combo_last_bolus, bolus, unit, ago));
} else {
lastBolusView.setText("");
}
// base basal rate
basaBasalRateView.setText("(" + (pumpStatus.activeProfileName) + ") "
+ MainApp.gs(R.string.pump_basebasalrate, plugin.getBaseBasalRate()));
// FIXME temp basal - check - maybe set as combo ??
if (ConfigBuilderPlugin.getActivePump().isFakingTempsByExtendedBoluses()) {
if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
tempBasalView.setText(TreatmentsPlugin.getPlugin()
.getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
} else {
tempBasalView.setText("");
}
} else {
// v2 plugin
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
tempBasalView.setText(TreatmentsPlugin.getPlugin()
.getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
} else {
tempBasalView.setText("");
}
}
// battery
batteryView.setText("{fa-battery-" + (pumpStatus.batteryRemaining / 25) + "}");
SetWarnColor.setColorInverse(batteryView, pumpStatus.batteryRemaining, 51d, 26d);
// reservoir
reservoirView.setText(DecimalFormatter.to0Decimal(pumpStatus.reservoirRemainingUnits) + " / "
+ pumpStatus.reservoirFullUnits + " " + MainApp.gs(R.string.insulin_unit_shortname));
SetWarnColor.setColorInverse(reservoirView, pumpStatus.reservoirRemainingUnits, 50d, 20d);
errorsView.setText(pumpStatus.getErrorInfo());
});
}

View file

@ -14,6 +14,9 @@ import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import com.crashlytics.android.answers.CustomEvent;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
@ -27,34 +30,37 @@ 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.PumpDriverState;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
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.MedtronicCommunicationManager;
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.MedtronicHistoryData;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicStatusRefreshType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpDriver;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicPumpValuesChanged;
import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
/**
* Created by andy on 23.04.18.
*/
public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInterface {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpPlugin.class);
protected static MedtronicPumpPlugin plugin = null;
private RileyLinkMedtronicService medtronicService;
private MedtronicPumpStatus pumpStatusLocal = null;
@ -62,32 +68,32 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// variables for handling statuses and history
private boolean firstRun = true;
private boolean relevantConfigurationChangeFound = false;
private boolean hasBasalProfileChanged = false;
private boolean isRefresh = false;
private boolean isBasalProfileInvalid = false;
private Map<MedtronicStatusRefreshType, Long> statusRefreshMap = new HashMap<>();
private boolean isInitialized = false;
private MedtronicHistoryData medtronicHistoryData;
private MedtronicCommunicationManager medtronicCommunicationManager;
private MedtronicPumpPlugin() {
// super(new PluginDescription() //
// .mainType(PluginType.PUMP) //
// .fragmentClass(MedtronicFragment.class.getName()) //
// .pluginName(R.string.medtronic_name) //
// .shortName(R.string.medtronic_name_short) //
// .preferencesId(R.xml.pref_medtronic));
super(new MedtronicPumpDriver(), //
"MedtronicPump", //
new PluginDescription() //
.mainType(PluginType.PUMP) //
.fragmentClass(MedtronicFragment.class.getName()) //
.pluginName(R.string.medtronic_name) //
.shortName(R.string.medtronic_name_short) //
.preferencesId(R.xml.pref_medtronic), //
PumpType.Medtronic_512_712 // we default to most basic model, correct model from config is loaded later
super(new PluginDescription() //
.mainType(PluginType.PUMP) //
.fragmentClass(MedtronicFragment.class.getName()) //
.pluginName(R.string.medtronic_name) //
.shortName(R.string.medtronic_name_short) //
.preferencesId(R.xml.pref_medtronic).description(R.string.description_pump_medtronic), //
PumpType.Medtronic_522_722 // we default to most basic model, correct model from config is loaded later
);
// TODO remove this later
displayConnectionMessages = true;
medtronicHistoryData = new MedtronicHistoryData();
// medtronicCommunicationManager = MedtronicCommunicationManager.getInstance();
// medtronicCommunicationManager.setDoWakeUpBeforeCommand(false);
serviceConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
@ -141,8 +147,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
this.pumpStatus = pumpStatusLocal;
if (pumpStatusLocal.maxBasal != null)
pumpDescription.maxTempAbsolute = (pumpStatusLocal.maxBasal != null) ? pumpStatusLocal.maxBasal : 35.0d;
pumpDescription.maxTempAbsolute = (pumpStatusLocal.maxBasal != null) ? pumpStatusLocal.maxBasal : 35.0d;
// needs to be changed in configuration, after all functionalities are done
pumpDescription.isBolusCapable = true;
@ -170,14 +175,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
public void onStartCustomActions() {
// check status every minute
// check status every minute (if any status needs refresh we send readStatus command)
new Thread(() -> {
do {
SystemClock.sleep(60000);
if (doWeHaveAnyStatusNeededRefereshing()) {
ConfigBuilderPlugin.getCommandQueue().readStatus("Manual Status Request", null);
ConfigBuilderPlugin.getCommandQueue().readStatus("Manual Status Refresh", null);
}
} while (serviceRunning);
@ -197,12 +202,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
@Override
public PumpDescription getPumpDescription() {
return this.pumpDescription;
}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return false;
@ -216,42 +215,43 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
@Override
public boolean isInitialized() {
return isServiceSet() && medtronicService.isInitialized();
// TODO remove
LOG.debug("MedtronicPumpPlugin::isInitialized");
return isServiceSet() && isInitialized;
}
// FIXME
@Override
public boolean isSuspended() {
return isServiceSet() && medtronicService.isSuspended();
// TODO remove
LOG.debug("MedtronicPumpPlugin::isSuspended");
return isServiceSet() && medtronicHistoryData.isSuspended();
}
@Override
public boolean isBusy() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isBusy");
return isServiceSet() && medtronicService.isBusy();
}
@Override
public boolean isConnected() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isConnected");
return isServiceSet() && medtronicService.isInitialized();
}
@Override
public boolean isConnecting() {
if (!isServiceSet())
return true;
else
return !medtronicService.isInitialized();
}
@Override
public boolean isHandshakeInProgress() {
return false;
}
@Override
public void finishHandshaking() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isConnecting");
return !isServiceSet() || !medtronicService.isInitialized();
}
@ -261,7 +261,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
getMDTPumpStatus();
if (firstRun) {
initializePump(true);
initializePump(!isRefresh);
} else {
refreshAnyStatusThatNeedsToBeRefreshed();
}
@ -272,6 +272,22 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
public void resetStatusState() {
firstRun = true;
isRefresh = true;
}
private boolean isPumpNotReachable() {
RileyLinkServiceState rileyLinkServiceState = MedtronicUtil.getServiceState();
if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady //
&& rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady //
&& rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice) {
LOG.error("RileyLink unreachable.");
return false;
}
return (!medtronicCommunicationManager.isDeviceReachable());
}
@ -283,6 +299,20 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
boolean resetTime = false;
if (isPumpNotReachable()) {
LOG.error("Pump unreachable.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
return;
// new PumpEnactResult() //
// .success(false) //
// .enacted(false) //
// .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
}
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefreshMap.entrySet()) {
if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) {
@ -295,13 +325,20 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
case PumpTime:
case BatteryStatus:
case RemainingInsulin:
case Configuration: {
case RemainingInsulin: {
medtronicUIComm.executeCommand(refreshType.getKey().getCommandType());
scheduleNextRefresh(refreshType.getKey());
resetTime = true;
}
break;
case Configuration: {
medtronicUIComm.executeCommand(refreshType.getKey().getCommandType());
resetTime = true;
medtronicHistoryData.resetRelevantConfigurationChanged();
}
break;
}
}
}
@ -325,21 +362,44 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
private void setRefreshButtonEnabled(boolean enabled) {
MedtronicFragment.refreshButtonEnabled(enabled);
}
private void initializePump(boolean realInit) {
LOG.error("initializePump - start");
if (medtronicCommunicationManager == null) {
medtronicCommunicationManager = MedtronicCommunicationManager.getInstance();
medtronicCommunicationManager.setDoWakeUpBeforeCommand(false);
}
setRefreshButtonEnabled(false);
getMDTPumpStatus();
if (isRefresh) {
if (isPumpNotReachable()) {
LOG.error("initializePump::Pump unreachable.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
setRefreshButtonEnabled(true);
return;
}
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
}
// model (once)
if (MedtronicUtil.getMedtronicPumpModel() == null) {
medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel);
} else {
if (pumpStatusLocal.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) {
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));
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame);
}
}
@ -373,10 +433,23 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (errorCount >= 5) {
LOG.error("Number of error counts was 5 or more. Starting tunning.");
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
setRefreshButtonEnabled(true); // FIXME
return;
}
pumpStatusLocal.setLastCommunicationToNow();
setRefreshButtonEnabled(true);
if (!isRefresh) {
pumpState = PumpDriverState.Initialized;
}
FabricPrivacy.getInstance().logCustom( //
new CustomEvent("MedtronicInitializePump") //
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION) //
.putCustomAttribute("version", BuildConfig.VERSION));
isInitialized = true;
this.firstRun = false;
}
@ -385,14 +458,29 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public boolean isThisProfileSet(Profile profile) {
if (!isConnected()) {
if (!this.isInitialized) {
return true;
}
if (!hasBasalProfileChanged && getMDTPumpStatus().basalsByHour != null) {
if (!medtronicHistoryData.hasBasalProfileChanged() && getMDTPumpStatus().basalsByHour != null) {
return (!isBasalProfileInvalid);
}
setRefreshButtonEnabled(false);
if (isPumpNotReachable()) {
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
setRefreshButtonEnabled(true);
return false;
// new PumpEnactResult() //
// .success(false) //
// .enacted(false) //
// .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
}
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.GetBasalProfileSTD);
boolean invalid = false;
@ -433,13 +521,20 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
isBasalProfileInvalid = invalid;
if (!invalid)
medtronicHistoryData.resetBasalProfileChanged();
setRefreshButtonEnabled(true);
return (!invalid);
}
@Override
public long lastDataTime() {
if (pumpStatusLocal.lastConnection!=0) {
getMDTPumpStatus();
if (pumpStatusLocal.lastConnection != 0) {
return pumpStatusLocal.lastConnection;
}
@ -471,11 +566,23 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@NonNull
protected PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) {
setRefreshButtonEnabled(false);
if (isPumpNotReachable()) {
setRefreshButtonEnabled(true);
return new PumpEnactResult() //
.success(false) //
.enacted(false) //
.comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
}
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
try {
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);
@ -496,7 +603,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
: MedtronicConst.Statistics.StandardBoluses);
}
readPumpHistory();
// readPumpHistory();
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(response).enacted(response);
@ -632,7 +741,19 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
LOG.error("MedtronicPumpPlugin::setTempBasalAbsolute Not fully implemented - Just base command.");
setRefreshButtonEnabled(false);
if (isPumpNotReachable()) {
setRefreshButtonEnabled(true);
return new PumpEnactResult() //
.success(false) //
.enacted(false) //
.comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
}
MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
getMDTPumpStatus();
@ -643,14 +764,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (tbrCurrent == null) {
LOG.warn("MedtronicPumpPlugin::setTempBasalAbsolute - Could not read current TBR, canceling operation.");
// TODO translate
return new PumpEnactResult().success(false).enacted(false).comment("Couldn't read current TBR.");
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr));
} else {
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)) {
@ -663,6 +784,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (sameRate) {
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - No enforceNew and same rate. Exiting.");
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(true).enacted(false);
}
}
@ -683,8 +805,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
LOG.info("MedtronicPumpPlugin::setTempBasalAbsolute - Current TBR cancelled.");
} else {
LOG.error("MedtronicPumpPlugin::setTempBasalAbsolute - Cancel TBR failed.");
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(false).enacted(false)
.comment("Couldn't cancel current TBR. Stopping operation. ");
.comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr));
}
}
@ -702,19 +827,22 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
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);
TemporaryBasal tempStart = new TemporaryBasal() //
.date(System.currentTimeMillis()) //
.duration(durationInMinutes) //
.absolute(absoluteRate) //
.source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStart);
incrementStatistics(MedtronicConst.Statistics.TBRsSet);
}
readPumpHistory(); // TODO maybe this is not needed here
MainApp.bus().post(new EventRefreshOverview("TBR"));
triggerUIChange();
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(response).enacted(response);
}
@ -722,16 +850,11 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private void readPumpHistory() {
LOG.error("MedtronicPumpPlugin::readPumpHistory NOT IMPLEMENTED.");
// TODO implement logic here fror config changes
relevantConfigurationChangeFound = false;
// TODO read History
// 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);
if (relevantConfigurationChangeFound) {
if (medtronicHistoryData.hasRelevantConfigurationChanged()) {
scheduleNextRefresh(MedtronicStatusRefreshType.Configuration, -1);
}
@ -781,15 +904,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
// TODO
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT IMPLEMENTED YET.");
return OPERATION_NOT_YET_SUPPORTED;
}
private TempBasalPair readTBR() {
MedtronicUITask responseTask = medtronicUIComm.executeCommand(MedtronicCommandType.ReadTemporaryBasal);
@ -808,22 +922,26 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
// TODO
@Override
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
LOG.info("cancelTempBasal - started");
setRefreshButtonEnabled(false);
TempBasalPair tbrCurrent = readTBR();
if (tbrCurrent != null) {
if (tbrCurrent.getInsulinRate() == 0.0f && tbrCurrent.getDurationMinutes() == 0) {
LOG.info("MedtronicPumpPlugin::cancelTempBasal - TBR already canceled.");
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(true).enacted(false);
}
} else {
LOG.warn("MedtronicPumpPlugin::cancelTempBasal - Could not read currect TBR, canceling operation.");
return new PumpEnactResult().success(false).enacted(false).comment("Couldn't read current TBR. ");
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr));
}
MedtronicUITask responseTask2 = medtronicUIComm.executeCommand(MedtronicCommandType.CancelTBR);
@ -837,7 +955,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
LOG.info("MedtronicPumpPlugin::cancelTempBasal - Cancel TBR failed.");
}
readPumpHistory();
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(response).enacted(response);
}
@ -847,6 +965,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
public PumpEnactResult setNewBasalProfile(Profile profile) {
LOG.warn("MedtronicPumpPlugin::setNewBasalProfile NOT IMPLEMENTED YET.");
// TODO implement this
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_profile_not_set));
}
@ -854,10 +974,16 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// OPERATIONS not supported by Pump or Plugin
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT SUPPORTED.");
return OPERATION_NOT_SUPPORTED;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
LOG.warn("cancelExtendedBolus - operation not supported.");
return getOperationNotSupportedWithCustomText(R.string.medtronic_cmd_cancel_bolus_not_supported);
}
@ -871,7 +997,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
// we don't loadTDD
// we don't loadTDD. TDD is read from Pump History
@Override
public PumpEnactResult loadTDDs() {
return OPERATION_NOT_SUPPORTED;
@ -882,16 +1008,23 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// we don't use this.
// we connect to RileyLink on startup and keep connection opened, then connection to pump
// is established when needed.
// TODO remove
LOG.debug("MedtronicPumpPlugin::connect (reason: {})", reason);
}
public void disconnect(String reason) {
// see comment in connect
// TODO remove
LOG.debug("MedtronicPumpPlugin::disconnect (reason: {})", reason);
}
public void stopConnecting() {
// see comment in connect
// TODO remove
LOG.debug("MedtronicPumpPlugin::stopConnecting");
}

View file

@ -9,11 +9,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.content.Context;
import android.os.SystemClock;
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.ble.RFSpy;
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.RLMessageType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
@ -38,6 +41,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
/**
* Original file created by geoff on 5/30/16.
@ -54,12 +58,16 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
String errorMessage;
private MedtronicConverter medtronicConverter;
private boolean debugSetCommands = true;
private boolean doWakeUpBeforeCommand = true;
private boolean firstConnection = true;
public MedtronicCommunicationManager(Context context, RFSpy rfspy, RileyLinkTargetFrequency targetFrequency) {
super(context, rfspy, targetFrequency);
medtronicCommunicationManager = this;
this.medtronicConverter = new MedtronicConverter();
MedtronicUtil.getPumpStatus().previousConnection = SP.getLong(
RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L);
}
@ -81,31 +89,121 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
public void setDoWakeUpBeforeCommand(boolean doWakeUp) {
this.doWakeUpBeforeCommand = doWakeUp;
}
/**
* We do actual wakeUp and compare PumpModel with currently selected one. If returned model is not Unknown,
* pump is reachable.
*
* @return
*/
public boolean isDeviceReachable() {
PumpDeviceState state = MedtronicUtil.getPumpDeviceState();
if (state != PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.WakingUp);
for (int retry = 0; retry < 5; retry++) {
LOG.error("isDeviceReachable. Waking pump... " + (retry != 0 ? " (retry " + retry + ")" : ""));
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple
RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0,
(byte)200, (byte)0, (byte)0, 25000, (byte)0);
LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
if (rfSpyResponse.wasTimeout()) {
LOG.error("isDeviceReachable. Failed to find pump (timeout).");
} else if (rfSpyResponse.looksLikeRadioPacket()) {
RadioResponse radioResponse = new RadioResponse(rfSpyResponse.getRaw());
if (radioResponse.isValid()) {
PumpMessage pumpResponse = createResponseMessage(radioResponse.getPayload(), PumpMessage.class);
if (!pumpResponse.isValid()) {
LOG.warn("Response is invalid ! [interrupted={}, timeout={}]", rfSpyResponse.wasInterrupted(),
rfSpyResponse.wasTimeout());
} else {
rememberLastGoodDeviceCommunicationTime();
// radioResponse.rssi;
Object dataResponse = medtronicConverter.convertResponse(MedtronicCommandType.PumpModel,
pumpResponse.getRawContent());
MedtronicDeviceType pumpModel = (MedtronicDeviceType)dataResponse;
boolean valid = pumpModel != MedtronicDeviceType.Unknown_Device;
LOG.debug("isDeviceReachable. PumpModel is {} - Valid: {} (rssi={})", pumpModel.name(), valid,
radioResponse.rssi);
if (valid) {
if (state == PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.WakingUp);
if (firstConnection)
checkFirstConnectionTime();
rememberLastGoodDeviceCommunicationTime();
return true;
} else {
if (state != PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable);
}
}
} else {
LOG.warn("isDeviceReachable. Failed to parse radio response: "
+ ByteUtil.shortHexString(rfSpyResponse.getRaw()));
}
} else {
LOG.warn("isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
}
}
if (state != PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable);
return false;
}
// FIXME must not call getPumpModel !!!!!!!!!!!!!
@Override
public boolean tryToConnectToDevice() {
wakeUp(true);
return isDeviceReachable();
MedtronicDeviceType pumpModel = getPumpModel();
// Andy (4.6.2018): we do retry if no data returned. We might need to do that everywhere, but that might require
// little bit of rewrite of RF Code.
if (pumpModel == MedtronicDeviceType.Unknown_Device) {
SystemClock.sleep(1000);
pumpModel = getPumpModel();
}
boolean connected = (pumpModel != MedtronicDeviceType.Unknown_Device);
if (connected) {
checkFirstConnectionTime();
setLastConnectionTime();
}
return (pumpModel != MedtronicDeviceType.Unknown_Device);
// wakeUp(true);
//
// MedtronicDeviceType pumpModel = getPumpModel();
//
// // Andy (4.6.2018): we do retry if no data returned. We might need to do that everywhere, but that might
// require
// // little bit of rewrite of RF Code.
// if (pumpModel == MedtronicDeviceType.Unknown_Device) {
//
// SystemClock.sleep(1000);
//
// pumpModel = getPumpModel();
// }
//
// boolean connected = (pumpModel != MedtronicDeviceType.Unknown_Device);
//
// if (connected) {
// checkFirstConnectionTime();
// rememberLastGoodDeviceCommunicationTime();
// }
//
// return (pumpModel != MedtronicDeviceType.Unknown_Device);
}
@ -121,6 +219,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
private void checkFirstConnectionTime() {
// FIXME set to SP
firstConnection = false;
}
@ -217,7 +317,10 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// TODO fix this with new code, and new response (Page)
public Page getPumpHistoryPage(int pageNumber) {
RawHistoryPage rval = new RawHistoryPage();
wakeUp(receiverDeviceAwakeForMinutes, false);
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
PumpMessage getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData,
new GetHistoryPageCarelinkMessageBody(pageNumber));
// LOG.info("getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData()));
@ -325,7 +428,9 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// See ButtonPressCarelinkMessageBody
public void pressButton(int which) {
wakeUp(receiverDeviceAwakeForMinutes, false);
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
PumpMessage pressButtonMessage = makePumpMessage(MedtronicCommandType.PushButton,
new ButtonPressCarelinkMessageBody(which));
PumpMessage resp = sendAndListen(pressButtonMessage);
@ -335,25 +440,6 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
// FIXME
// @Override
// public RLMessage makeRLMessage(RLMessageType type, byte[] data) {
// switch (type) {
// case PowerOn:
// return makePumpMessage(MedtronicCommandType.RFPowerOn, new CarelinkShortMessageBody(data));
//
// case ReadSimpleData:
// return makePumpMessage(MedtronicCommandType.PumpModel, new GetPumpModelCarelinkMessageBody());
//
// }
// return null;
// }
// @Override
// public RLMessage makeRLMessage(byte[] data) {
// return makePumpMessage(data);
// }
@Override
public byte[] createPumpMessageContent(RLMessageType type) {
switch (type) {
@ -421,7 +507,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
*/
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs) {
// wakeUp
wakeUp(receiverDeviceAwakeForMinutes, false);
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active);
@ -602,7 +689,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
public BasalProfile getBasalProfile() {
// wakeUp
wakeUp(receiverDeviceAwakeForMinutes, false);
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active);
@ -728,9 +816,10 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// TODO test with values bigger than 30U
public Boolean setBolus(double units) {
LOG.warn("setBolus: " + units);
LOG.info("setBolus: " + units);
wakeUp(false);
if (this.doWakeUpBeforeCommand)
wakeUp(false);
byte[] body = MedtronicUtil.getBolusStrokes(units);
@ -752,7 +841,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// TODO WIP test
public boolean setTBR(TempBasalPair tbr) {
wakeUp(false);
if (this.doWakeUpBeforeCommand)
wakeUp(false);
byte[] body = tbr.getAsRawData();

View file

@ -38,10 +38,15 @@ public class MedtronicConverter {
this.pumpModel = MedtronicUtil.getMedtronicPumpModel();
// if (this.pumpModel == null) {
// LOG.warn("Pump model was not identified. Defaulting to 522.");
// this.pumpModel = MedtronicDeviceType.Medtronic_522;
// }
switch (commandType) {
case PumpModel: {
return MedtronicDeviceType.getByDescription(StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3)));
return decodeModel(rawContent);
}
case RealTimeClock: {
@ -87,6 +92,19 @@ public class MedtronicConverter {
}
private MedtronicDeviceType decodeModel(byte[] rawContent) {
String rawModel = StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3));
MedtronicDeviceType pumpModel = MedtronicDeviceType.getByDescription(rawModel);
LOG.debug("PumpModel: [raw={}, resolved={}]", rawModel, pumpModel.name());
if (pumpModel != MedtronicDeviceType.Unknown_Device) {
MedtronicUtil.setMedtronicPumpModel(pumpModel);
}
return pumpModel;
}
protected BasalProfile decodeProfile2(byte[] rep) {
// byte rep[] = minimedReply.getRawData();

View file

@ -126,7 +126,7 @@ public class PumpMessage implements RLMessage {
System.arraycopy(messageBody.getTxData(), 1, arrayOut, 0, length);
Log.d("PumpMessage", "Length: " + length + ", Original Length: " + originalLength + ", CommandType: "
Log.v("PumpMessage", "Length: " + length + ", Original Length: " + originalLength + ", CommandType: "
+ commandType);
return arrayOut;

View file

@ -1,5 +1,7 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui;
import static info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil.sendNotification;
import java.util.Date;
import java.util.Map;
@ -7,13 +9,10 @@ import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BatteryStatusDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
@ -37,6 +36,11 @@ public class MedtronicUIPostprocessor {
// where responses won't be directly used
public void postProcessData(MedtronicUITask uiTask) {
if (!uiTask.haveData()) {
LOG.error("Error reading data [{}]: {}", uiTask.commandType, uiTask.errorDescription);
return;
}
switch (uiTask.commandType) {
case GetBasalProfileSTD: {
@ -81,7 +85,7 @@ public class MedtronicUIPostprocessor {
case PumpModel: {
if (pumpStatus.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) {
LOG.warn("Configured pump is different then pump detected !");
sendNotification(R.string.medtronic_error_pump_type_set_differs_from_detected, Notification.NORMAL);
sendNotification(MedtronicNotificationType.PumpTypeNotSame);
}
}
break;
@ -117,47 +121,42 @@ public class MedtronicUIPostprocessor {
if (diff >= 10 * 60 * 1000) {
LOG.debug("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")");
sendNotification(R.string.combo_notification_check_time_date, Notification.URGENT);
sendNotification(MedtronicNotificationType.PumpWrongTimeUrgent);
} else if (diff >= 4 * 60 * 1000) {
LOG.debug("Pump clock needs update, pump time: " + ldt + " (" + ldt + ")");
sendNotification(R.string.combo_notification_check_time_date, Notification.NORMAL);
sendNotification(MedtronicNotificationType.PumpWrongTimeNormal);
}
}
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 sendNotification(int resourceId, int notificationUrgencyType, Object... parameters) {
Notification notification = new Notification(Notification.MEDTRONIC_PUMP_ALARM, MainApp.gs(resourceId,
parameters), notificationUrgencyType);
MainApp.bus().post(new EventNewNotification(notification));
}
private void postProcessSettings(MedtronicUITask uiTask) {
Map<String, PumpSettingDTO> settings = (Map<String, PumpSettingDTO>)uiTask.returnData;
MedtronicUtil.setSettings(settings);
PumpSettingDTO checkValue = null;
if (pumpStatus == null) {
LOG.debug("Pump Status: was null");
pumpStatus = MedtronicUtil.getPumpStatus();
LOG.debug("Pump Status: " + this.pumpStatus);
}
this.pumpStatus.verifyConfiguration();
// check profile
if (!"Yes".equals(settings.get("PCFG_BASAL_PROFILES_ENABLED").value)) {
LOG.error("Basal profiles are not enabled on pump.");
sendNotification(R.string.medtronic_error_pump_basal_profiles_not_enabled, Notification.URGENT);
sendNotification(MedtronicNotificationType.PumpBasalProfilesNotEnabled);
} else {
checkValue = settings.get("PCFG_ACTIVE_BASAL_PROFILE");
if (!"STD".equals(checkValue.value)) {
LOG.error("Basal profile set on pump is incorrect (must be STD).");
sendNotification(R.string.medtronic_error_pump_incorrect_basal_profile_selected, Notification.URGENT);
sendNotification(MedtronicNotificationType.PumpIncorrectBasalProfileSelected);
}
}
@ -167,7 +166,7 @@ public class MedtronicUIPostprocessor {
if (!"Units".equals(checkValue.value)) {
LOG.error("Wrong TBR type set on pump (must be Absolute).");
sendNotification(R.string.medtronic_error_pump_wrong_tbr_type_set, Notification.URGENT);
sendNotification(MedtronicNotificationType.PumpWrongTBRTypeSet);
}
// MAXes
@ -176,16 +175,14 @@ public class MedtronicUIPostprocessor {
if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBolus)) {
LOG.error("Wrong Max Bolus set on Pump (must be {}).", pumpStatus.maxBolus);
sendNotification(R.string.medtronic_error_pump_wrong_max_bolus_set, Notification.NORMAL,
pumpStatus.maxBolus);
sendNotification(MedtronicNotificationType.PumpWrongMaxBolusSet, pumpStatus.maxBolus);
}
checkValue = settings.get("PCFG_MAX_BASAL");
if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBasal)) {
LOG.error("Wrong Max Basal set on Pump (must be {}).", pumpStatus.maxBasal);
sendNotification(R.string.medtronic_error_pump_wrong_max_basal_set, Notification.NORMAL,
pumpStatus.maxBasal);
sendNotification(MedtronicNotificationType.PumpWrongMaxBasalSet, pumpStatus.maxBasal);
}
}

View file

@ -7,6 +7,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicUIResponseType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
@ -15,6 +16,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
* Created by andy on 6/14/18.
*/
// FIXME we could refactor this and create sperate class for each command, perhaps
public class MedtronicUITask {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicUITask.class);
@ -25,6 +27,7 @@ public class MedtronicUITask {
boolean invalid = false;
private Object[] parameters;
private boolean received;
MedtronicUIResponseType responseType;
public MedtronicUITask(MedtronicCommandType commandType) {
@ -137,16 +140,19 @@ public class MedtronicUITask {
default: {
LOG.warn("This commandType is not supported (yet) - {}.", commandType);
invalid = true;
responseType = MedtronicUIResponseType.Invalid;
}
}
if (returnData == null) {
if (!invalid)
errorDescription = communicationManager.getErrorResponse();
received = true;
} else {
received = true;
if (responseType != null) {
if (returnData == null) {
if (!invalid)
errorDescription = communicationManager.getErrorResponse();
received = true;
} else {
received = true;
}
}
}

View file

@ -0,0 +1,52 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.data;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
/**
* Created by andy on 10/12/18.
*/
public class MedtronicHistoryData {
List<PumpHistoryEntry> history = null;
private boolean suspended = false;
private boolean relevantConfigurationChanged = false;
private boolean basalProfileChanged = true;
public MedtronicHistoryData() {
this.history = new ArrayList<>();
}
// TODO
public boolean isSuspended() {
return suspended;
}
// TODO implement logic here fror config changes
public boolean hasRelevantConfigurationChanged() {
return relevantConfigurationChanged;
}
public void resetRelevantConfigurationChanged() {
relevantConfigurationChanged = false;
}
// TODO implement logic to see if Basalrates changed from last time
public boolean hasBasalProfileChanged() {
return basalProfileChanged;
}
public void resetBasalProfileChanged() {
basalProfileChanged = true; // FIXME when this works this should reset to false
}
}

View file

@ -10,7 +10,16 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.UnknownMess
/**
* Taken from GNU Gluco Control diabetes management software (ggc.sourceforge.net)
* <p>
*
* Description: Medtronic Commands (Pump and CGMS) for all 512 and later models (just 5xx)
*
* Link to original/unmodified file:
* https://sourceforge.net/p/ggc/code/HEAD/tree/trunk/ggc-plugins/ggc-plugins-base/src/
* main/java/ggc/plugin/device/impl/minimed/enums/MinimedCommandType.java
*
* A lot of stuff has been removed because it is not needed anymore (historical stuff from CareLink
* and Carelink USB communication.
*
* Author: Andy {andy@atech-software.com}
*/
@ -51,8 +60,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
DetectBolus(75, "Detect Bolus", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray(
0, 0, 0)), //
ReadTemporaryBasal_511(120, "Read Temporary Basal", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters), //
RemoteControlIds(118, "Remote Control Ids", MinimedTargetType.PumpConfiguration_NA, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
FirmwareVersion(116, "Firmware Version", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
@ -66,16 +73,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
GetRemainingInsulin(0x73, "Read Remaining Insulin", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters, 2), // 115
Settings_511(127, "Settings", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters), //
HistoryData_511(128, "History data", MinimedTargetType.PumpData, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.SubCommands, 1024, 32, 0), // 0x80
Profile_STD_511(122, "Profile Standard", MinimedTargetType.PumpDataAndConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters, 128, 1, 8), // FIXME_
Profile_A_511(123, "Profile A", MinimedTargetType.PumpDataAndConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters, 128, 1, 9), // FIXME_
Profile_B_511(124, "Profile B", MinimedTargetType.PumpDataAndConfiguration, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.NoParameters, 128, 1, 10), // FIXME_
SetBolus(0x42, "Set Bolus", MinimedTargetType.PumpSetData, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 66
// 512
@ -112,10 +109,8 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
GetBasalProfileSTD(146, "Get Profile Standard", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8, 1), // 146
GetBasalProfileA(147, "Get Profile A", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 9), // 147
// FIXME
GetBasalProfileB(148, "Get Profile B", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 10), // 148
// FIXME
SetBasalProfileSTD(0x6f, "Set Profile Standard", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8), // 111
@ -123,47 +118,17 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
SetBasalProfileB(0x31, "Set Profile B", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8), // 49
BolusWizardSetupStatus(135, "Bolus Wizard Setup Status", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), //
GetCarbohydrateRatios(0x8a, "Get Carbohydrate Ratios", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), // 138
CarbohydrateUnits(136, "Carbohydrate Units", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters), //
// 515
PumpStatus(206, "Pump Status", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), // PumpConfiguration
Settings(192, "Settings", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), //
BGTargets(159, "BG Targets", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), //
MissedBolusReminderEnable(197, "Missed Bolus Reminder Enable", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), //
MissedBolusReminders(198, "Missed Bolus Reminder", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_515andHigher, MinimedCommandParameterType.NoParameters), //
// 522
CalibrationFactor(156, "Calibration Factor", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.NoParameters), //
SensorSettings_522(153, "Sensor Settings", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_522_722, MinimedCommandParameterType.NoParameters), //
GlucoseHistory(154, "Glucose History", MinimedTargetType.CGMSData, MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0), //
ISIGHistory(155, "Isig History", MinimedTargetType.CGMSData_NA, MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 2048, 32, 0), //
SensorSettings_522(153, "Sensor Settings", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.NoParameters), //
GlucoseHistory(154, "Glucose History", MedtronicDeviceType.Medtronic_522andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0, null), //
// 523
SensorPredictiveAlerts(209, "Sensor Predictive Alerts", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
SensorRateOfChangeAlerts(212, "Sensor Rate Of Change Alerts", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
SensorDemoAndGraphTimeout(210, "Sensor Demo and Graph Timeout", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
SensorAlarmSilence(211, "Sensor Alarm Silence", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
SensorSettings(207, "Sensor Settings", MinimedTargetType.CGMSConfiguration, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
OtherDevicesIds(240, "Other Devices ID", MinimedTargetType.CGMSConfiguration_NA, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.NoParameters), //
VCntrHistory(213, "Vcntr History", MinimedTargetType.CGMSData_NA, MedtronicDeviceType.Medtronic_523andHigher, MinimedCommandParameterType.SubCommands, 1024, 32, 0), //
// 553
// 554
@ -269,6 +234,58 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
}
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType) {
this(code, description, devices, parameterType, 64, 1, 0, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) {
this(code, description, devices, parameterType, recordLength, maxRecords, 0, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int expectedLength) {
this(code, description, devices, parameterType, 64, 1, expectedLength, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int expectedLength, int resourceId) {
this(code, description, devices, parameterType, 64, 1, expectedLength, resourceId);
}
// NEW
MedtronicCommandType(int code, String description,
MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int expectedLength,
Integer resourceId) {
this.commandCode = (byte)code;
this.commandDescription = description;
this.devices = devices;
this.recordLength = recordLength;
this.maxRecords = max_recs;
this.commandParametersCount = 0;
this.allowedRetries = 2;
this.parameterType = parameterType;
this.expectedLength = expectedLength;
if (this.parameterType == MinimedCommandParameterType.SubCommands) {
this.minimalBufferSizeToStartReading = 200;
}
}
@Deprecated
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int addy, //
int addy_len, int cmd_type, int expectedLength) {
@ -319,15 +336,6 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
}
public static MedtronicCommandType getReadTemporaryBasal(MedtronicDeviceType device) {
if (device == MedtronicDeviceType.Medtronic_511) {
return MedtronicCommandType.ReadTemporaryBasal_511;
} else {
return MedtronicCommandType.ReadTemporaryBasal;
}
}
public static MedtronicCommandType getDetectBolus(MedtronicDeviceType device) {
if (device == MedtronicDeviceType.Medtronic_511) {
return MedtronicCommandType.DetectBolus;
@ -374,9 +382,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
public static MedtronicCommandType getSettings(MedtronicDeviceType medtronicPumpModel) {
if (medtronicPumpModel == MedtronicDeviceType.Medtronic_511)
return MedtronicCommandType.Settings_511;
else if (MedtronicDeviceType.isSameDevice(medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712))
if (MedtronicDeviceType.isSameDevice(medtronicPumpModel, MedtronicDeviceType.Medtronic_512_712))
return MedtronicCommandType.Settings_512;
else
return MedtronicCommandType.Settings;

View file

@ -0,0 +1,65 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
/**
* Created by andy on 10/15/18.
*/
public enum MedtronicNotificationType {
PumpUnreachable(Notification.RILEYLINK_CONNECTION, R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL), //
PumpTypeNotSame(R.string.medtronic_error_pump_type_set_differs_from_detected, Notification.NORMAL), //
PumpBasalProfilesNotEnabled(R.string.medtronic_error_pump_basal_profiles_not_enabled, Notification.URGENT), //
PumpIncorrectBasalProfileSelected(R.string.medtronic_error_pump_incorrect_basal_profile_selected, Notification.URGENT), //
PumpWrongTBRTypeSet(R.string.medtronic_error_pump_wrong_tbr_type_set, Notification.URGENT), //
PumpWrongMaxBolusSet(R.string.medtronic_error_pump_wrong_max_bolus_set, Notification.NORMAL), //
PumpWrongMaxBasalSet(R.string.medtronic_error_pump_wrong_max_basal_set, Notification.NORMAL), //
PumpWrongTimeUrgent(R.string.combo_notification_check_time_date, Notification.URGENT),
PumpWrongTimeNormal(R.string.combo_notification_check_time_date, Notification.NORMAL),
//
;
private int notificationType;
private int resourceId;
private int notificationUrgency;
MedtronicNotificationType(int resourceId, int notificationUrgency) {
this(Notification.MEDTRONIC_PUMP_ALARM, resourceId, notificationUrgency);
}
MedtronicNotificationType(int notificationType, int resourceId, int notificationUrgency) {
this.notificationType = notificationType;
this.resourceId = resourceId;
this.notificationUrgency = notificationUrgency;
}
public int getNotificationType() {
return notificationType;
}
public void setNotificationType(int notificationType) {
this.notificationType = notificationType;
}
public int getResourceId() {
return resourceId;
}
public int getNotificationUrgency() {
return notificationUrgency;
}
// Notification.MEDTRONIC_PUMP_ALARM R.string.medtronic_pump_status_pump_unreachable, Notification.NORMAL
}

View file

@ -0,0 +1,13 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
/**
* Created by andy on 10/18/18.
*/
public enum MedtronicUIResponseType {
Data,
Error,
Invalid;
}

View file

@ -14,7 +14,8 @@ public enum PumpDeviceState {
Active(R.string.medtronic_pump_status_active), //
ErrorWhenCommunicating(R.string.medtronic_pump_status_error_comm), //
TimeoutWhenCommunicating(R.string.medtronic_pump_status_timeout_comm), //
ProblemContacting(R.string.medtronic_pump_status_problem_contacting), //
// ProblemContacting(R.string.medtronic_pump_status_problem_contacting), //
PumpUnreachable(R.string.medtronic_pump_status_pump_unreachable), //
InvalidConfiguration(R.string.medtronic_pump_status_invalid_config);
Integer resourceId = null;

View file

@ -1,89 +0,0 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.driver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
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.logging.L;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpDriver;
import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
/**
* Created by andy on 4/28/18.
*/
@Deprecated
public class MedtronicPumpDriver extends VirtualPumpDriver /* implements PumpInterface */{
private static final Logger LOG = LoggerFactory.getLogger(MedtronicPumpDriver.class);
// MedtronicPumpStatus pumpStatusLocal;
public MedtronicPumpDriver() {
}
@Override
public boolean isConnected() {
return true;
}
@Override
public boolean isConnecting() {
return false;
}
@Override
public void connect(String reason) {
// connection is established by each command specifically
}
@Override
public void stopConnecting() {
// we're not doing that
}
@Override
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
// FIXME
// send Cancel Temp Basal
return super.cancelTempBasal(enforceNew);
}
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
TemporaryBasal tempBasal = new TemporaryBasal().date(System.currentTimeMillis()).absolute(absoluteRate)
.duration(durationInMinutes).source(Source.USER);
PumpEnactResult result = new PumpEnactResult();
result.success = true;
result.enacted = true;
result.isTempCancel = false;
result.absolute = absoluteRate;
result.duration = durationInMinutes;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
if (L.isEnabled(L.PUMP))
LOG.debug("Setting temp basal absolute: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
getPumpStatusData().setLastCommunicationToNow();
return result;
}
}

View file

@ -42,6 +42,7 @@ public class MedtronicPumpStatus extends PumpStatus {
public Double maxBolus;
public Double maxBasal;
public boolean inPreInit = true;
// statuses
public RileyLinkServiceState rileyLinkServiceState = RileyLinkServiceState.NotStarted;
public RileyLinkError rileyLinkError;
@ -225,6 +226,8 @@ public class MedtronicPumpStatus extends PumpStatus {
private boolean startService() {
LOG.debug("MedtronicPumpStatus::startService");
if (serialChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
MedtronicUtil.getMedtronicService().setPumpIDString(this.serialNumber); // short operation
serialChanged = false;

View file

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

View file

@ -16,9 +16,6 @@ import android.os.IBinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
@ -52,15 +49,9 @@ public class RileyLinkMedtronicService extends RileyLinkService {
private static RileyLinkMedtronicService instance;
private static ServiceTask currentTask = null;
// saved settings
// private String pumpIDString;
// private byte[] pumpIDBytes;
// cache of most recently received set of pump history pages. Probably shouldn't be here.
// ArrayList<Page> mHistoryPages;
// PumpHistoryManager pumpHistoryManager;
public MedtronicCommunicationManager medtronicCommunicationManager;
MedtronicPumpStatus pumpStatus = (MedtronicPumpStatus)MedtronicPumpPlugin.getPlugin().getPumpStatusData();
MedtronicPumpStatus pumpStatus = null;
private IBinder mBinder = new LocalBinder();
@ -413,7 +404,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
}
// PumpInterface
// PumpInterface - REMOVE
public boolean isInitialized() {
return RileyLinkServiceState.isReady(RileyLinkUtil.getRileyLinkServiceData().serviceState);
@ -440,47 +431,9 @@ public class RileyLinkMedtronicService extends RileyLinkService {
}
// FIXME to do 1st command
public void getPumpStatus() {
}
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
return null;
}
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
return null;
}
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
return null;
}
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
return null;
}
public PumpEnactResult cancelExtendedBolus() {
return null;
}
public PumpEnactResult loadTDDs() {
return null;
}
public MedtronicCommunicationManager getPumpManager() {
return this.medtronicCommunicationManager;
}
// public MedtronicCommunicationManager getPumpManager() {
// return this.medtronicCommunicationManager;
// }
// FIXME remove
public void sendNotification(ServiceNotification serviceNotification, Object o) {

View file

@ -10,6 +10,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.data.RLHistoryItem;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice;
@ -20,6 +23,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.MessageType
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.events.EventMedtronicDeviceStatusChange;
@ -189,6 +193,47 @@ public class MedtronicUtil extends RileyLinkUtil {
}
public static void sendNotification(MedtronicNotificationType notificationType) {
Notification notification = new Notification( //
notificationType.getNotificationType(), //
MainApp.gs(notificationType.getResourceId()), //
notificationType.getNotificationUrgency());
MainApp.bus().post(new EventNewNotification(notification));
}
public static void sendNotification(MedtronicNotificationType notificationType, Object... parameters) {
Notification notification = new Notification( //
notificationType.getNotificationType(), //
MainApp.gs(notificationType.getResourceId(), parameters), //
notificationType.getNotificationUrgency());
MainApp.bus().post(new EventNewNotification(notification));
}
public static void dismissNotification(MedtronicNotificationType notificationType) {
MainApp.bus().post(new EventDismissNotification(notificationType.getNotificationType()));
}
// @Deprecated
// public static void sendNotification(int resourceId, int notificationUrgencyType) {
// Notification notification = new Notification( //
// Notification.MEDTRONIC_PUMP_ALARM, //
// MainApp.gs(resourceId), //
// notificationUrgencyType);
// MainApp.bus().post(new EventNewNotification(notification));
// }
// @Deprecated
// public static void sendNotification(int resourceId, int notificationUrgencyType, Object... parameters) {
// Notification notification = new Notification( //
// Notification.MEDTRONIC_PUMP_ALARM, //
// MainApp.gs(resourceId, parameters), //
// notificationUrgencyType);
// MainApp.bus().post(new EventNewNotification(notification));
// }
public static byte[] buildCommandPayload(MessageType commandType, byte[] parameters) {
return buildCommandPayload(commandType.getValue(), parameters);
}

View file

@ -1,382 +0,0 @@
package info.nightscout.androidaps.plugins.PumpVirtual;
import android.os.SystemClock;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.ConfigBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
import info.nightscout.androidaps.plugins.PumpCommon.driver.PumpDriverAbstract;
import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui;
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
import info.nightscout.utils.DateUtil;
import info.nightscout.utils.SP;
/**
* Created by andy on 4/28/18.
*/
public class VirtualPumpDriver extends PumpDriverAbstract {
private static final Logger LOG = LoggerFactory.getLogger(VirtualPumpDriver.class);
public static boolean fromNSAreCommingFakedExtendedBoluses = false;
public VirtualPumpDriver() {
setFakingStatus(true);
this.pumpDescription = VirtualPumpPlugin.getPlugin().getPumpDescription();
this.pumpStatusData = new VirtualPumpStatus(this.pumpDescription);
}
private static void loadFakingStatus() {
fromNSAreCommingFakedExtendedBoluses = SP.getBoolean("fromNSAreCommingFakedExtendedBoluses", false);
}
public static void setFakingStatus(boolean newStatus) {
fromNSAreCommingFakedExtendedBoluses = newStatus;
SP.putBoolean("fromNSAreCommingFakedExtendedBoluses", fromNSAreCommingFakedExtendedBoluses);
}
public static boolean getFakingStatus() {
return fromNSAreCommingFakedExtendedBoluses;
}
@Override
public String deviceID() {
return null;
}
@Override
public String shortStatus(boolean veryShort) {
return null;
}
@Override
public boolean isFakingTempsByExtendedBoluses() {
return (Config.NSCLIENT) && fromNSAreCommingFakedExtendedBoluses;
}
@Override
public boolean isInitialized() {
return true;
}
@Override
public boolean isSuspended() {
return false;
}
@Override
public boolean isBusy() {
return false;
}
@Override
public boolean isConnected() {
return true;
}
public boolean isHandshakeInProgress()
{
return false;
} // true if BT is connected but initial handshake is still in progress
public void finishHandshaking()
{
}// set initial handshake completed
@Override
public boolean isConnecting() {
return false;
}
@Override
public void connect(String reason) {
if (!Config.NSCLIENT)
NSUpload.uploadDeviceStatus();
pumpStatusData.setLastCommunicationToNow();
}
@Override
public void disconnect(String reason) {
}
@Override
public void stopConnecting() {
}
@Override
public void getPumpStatus() {
pumpStatusData.setLastCommunicationToNow();
}
@Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
pumpStatusData.setLastCommunicationToNow();
// Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile();
PumpEnactResult result = new PumpEnactResult();
result.success = true;
Notification notification = new Notification(Notification.PROFILE_SET_OK, MainApp.sResources.getString(R.string.profile_set_ok), Notification.INFO, 60);
MainApp.bus().post(new EventNewNotification(notification));
return result;
}
@Override
public boolean isThisProfileSet(Profile profile) {
return true;
}
@Override
public long lastDataTime() {
return pumpStatusData.lastConnection;
}
@Override
public double getBaseBasalRate() {
Profile profile = ProfileFunctions.getInstance().getProfile();
if (profile != null)
return profile.getBasal();
else
return 0d;
}
@Override
public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) {
PumpEnactResult result = new PumpEnactResult();
result.success = true;
result.bolusDelivered = detailedBolusInfo.insulin;
result.carbsDelivered = detailedBolusInfo.carbs;
result.enacted = result.bolusDelivered > 0 || result.carbsDelivered > 0;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
Double delivering = 0d;
while (delivering < detailedBolusInfo.insulin) {
SystemClock.sleep(200);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivering), delivering);
bolusingEvent.percent = Math.min((int) (delivering / detailedBolusInfo.insulin * 100), 100);
MainApp.bus().post(bolusingEvent);
delivering += 0.1d;
}
SystemClock.sleep(200);
EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance();
bolusingEvent.status = String.format(MainApp.gs(R.string.bolusdelivered), detailedBolusInfo.insulin);
bolusingEvent.percent = 100;
MainApp.bus().post(bolusingEvent);
SystemClock.sleep(1000);
if (L.isEnabled(L.PUMPCOMM))
LOG.debug("Delivering treatment insulin: " + detailedBolusInfo.insulin + "U carbs: " + detailedBolusInfo.carbs + "g " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastCommunicationToNow();
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
return result;
}
@Override
public void stopBolusDelivering() {
}
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile, boolean enforceNew) {
TemporaryBasal tempBasal = new TemporaryBasal()
.date(System.currentTimeMillis())
.absolute(absoluteRate)
.duration(durationInMinutes)
.source(Source.USER);
PumpEnactResult result = new PumpEnactResult();
result.success = true;
result.enacted = true;
result.isTempCancel = false;
result.absolute = absoluteRate;
result.duration = durationInMinutes;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
if (L.isEnabled(L.PUMPCOMM))
LOG.debug("Setting temp basal absolute: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastCommunicationToNow();
return result;
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) {
PumpEnactResult result = new PumpEnactResult();
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
result = cancelTempBasal(false);
if (!result.success)
return result;
}
TemporaryBasal tempBasal = new TemporaryBasal()
.date(System.currentTimeMillis())
.percent(percent)
.duration(durationInMinutes)
.source(Source.USER);
result.success = true;
result.enacted = true;
result.percent = percent;
result.isPercent = true;
result.isTempCancel = false;
result.duration = durationInMinutes;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
if (L.isEnabled(L.PUMPCOMM))
LOG.debug("Settings temp basal percent: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastCommunicationToNow();
return result;
}
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
PumpEnactResult result = cancelExtendedBolus();
if (!result.success)
return result;
ExtendedBolus extendedBolus = new ExtendedBolus();
extendedBolus.date = System.currentTimeMillis();
extendedBolus.insulin = insulin;
extendedBolus.durationInMinutes = durationInMinutes;
extendedBolus.source = Source.USER;
result.success = true;
result.enacted = true;
result.bolusDelivered = insulin;
result.isTempCancel = false;
result.duration = durationInMinutes;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(extendedBolus);
if (L.isEnabled(L.PUMPCOMM))
LOG.debug("Setting extended bolus: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastCommunicationToNow();
return result;
}
@Override
public PumpEnactResult cancelTempBasal(boolean force) {
PumpEnactResult result = new PumpEnactResult();
result.success = true;
result.isTempCancel = true;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
result.enacted = true;
TemporaryBasal tempStop = new TemporaryBasal().date(System.currentTimeMillis()).source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStop);
//tempBasal = null;
if (L.isEnabled(L.PUMPCOMM))
LOG.debug("Canceling temp basal: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
}
pumpStatusData.setLastCommunicationToNow();
return result;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
PumpEnactResult result = new PumpEnactResult();
if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress()) {
ExtendedBolus exStop = new ExtendedBolus(System.currentTimeMillis());
exStop.source = Source.USER;
TreatmentsPlugin.getPlugin().addToHistoryExtendedBolus(exStop);
}
result.success = true;
result.enacted = true;
result.isTempCancel = true;
result.comment = MainApp.gs(R.string.virtualpump_resultok);
if (L.isEnabled(L.PUMPCOMM))
LOG.debug("Canceling extended basal: " + result);
MainApp.bus().post(new EventVirtualPumpUpdateGui());
pumpStatusData.setLastCommunicationToNow();
return result;
}
@Override
public JSONObject getJSONStatus(Profile profile, String profileName) {
long now = System.currentTimeMillis();
if (!SP.getBoolean("virtualpump_uploadstatus", false)) {
return null;
}
JSONObject pump = new JSONObject();
JSONObject battery = new JSONObject();
JSONObject status = new JSONObject();
JSONObject extended = new JSONObject();
try {
battery.put("percent", pumpStatusData.batteryRemaining);
status.put("status", "normal");
extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION);
try {
extended.put("ActiveProfile", profileName);
} catch (Exception e) {
}
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now);
if (tb != null) {
extended.put("TempBasalAbsoluteRate", tb.tempBasalConvertedToAbsolute(now, profile));
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
}
ExtendedBolus eb = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(now);
if (eb != null) {
extended.put("ExtendedBolusAbsoluteRate", eb.absoluteRate());
extended.put("ExtendedBolusStart", DateUtil.dateAndTimeString(eb.date));
extended.put("ExtendedBolusRemaining", eb.getPlannedRemainingMinutes());
}
status.put("timestamp", DateUtil.toISOString(now));
pump.put("battery", battery);
pump.put("status", status);
pump.put("extended", extended);
pump.put("reservoir", pumpStatusData.reservoirRemainingUnits);
pump.put("clock", DateUtil.toISOString(now));
} catch (JSONException e) {
LOG.error("Unhandled exception", e);
}
return pump;
}
@Override
public PumpEnactResult loadTDDs() {
//no result, could read DB in the future?
PumpEnactResult result = new PumpEnactResult();
return result;
}
}

View file

@ -1207,7 +1207,7 @@
<string name="key_short_tabtitles" translatable="false">short_tabtitles</string>
<!-- Pump Abstract -->
<string name="pump_operation_not_supported_by_pump">Operation not supported by pump.</string>
<string name="pump_operation_not_supported_by_pump_driver">Operation not supported by pump and/or driver.</string>
<string name="pump_operation_not_yet_supported_by_pump">Operation not YET supported by pump.</string>
<string name="location_not_found_title">Location Is Not Enabled</string>
<string name="location_not_found_message">For Bluetooth discovery to work on newer devices, location must be enabled. AAPS does not track your location and it can be disabled after pairing is successful.</string>
@ -1217,6 +1217,7 @@
<!-- Medtronic (MDT) - Base -->
<string name="medtronic_name" translatable="false">Medtronic</string>
<string name="medtronic_name_short" translatable="false">MDT</string>
<string name="description_pump_medtronic">Pump integration for Medtronic, requires RileyLink device and specific Pump Model</string>
<!-- MDT Configuration -->
@ -1271,6 +1272,7 @@
<string name="rileylink_error_tuneup_failed">TuneUp Failed</string>
<string name="rileylink_error_pump_unreachable">Pump unreachable</string>
<string name="rileylink_error_pod_unreachable">Pod unreachable</string>
<string name="rileylink_error_address_not_set_short">Not set</string>
<!-- RL Target Device -->
<string name="rileylink_target_device_medtronic">Medtronic Pump</string>
@ -1301,12 +1303,18 @@
<string name="medtronic_pump_status_error_comm">Error with communication</string>
<string name="medtronic_pump_status_timeout_comm">Timeout on communication</string>
<string name="medtronic_pump_status_problem_contacting">Problem contacting Pump</string>
<string name="medtronic_pump_status_pump_unreachable">Pump unreachable</string>
<string name="medtronic_pump_status_invalid_config">Invalid configuration</string>
<string name="medtronic_pump_status_active">Active</string>
<string name="medtronic_pump_status_sleeping">Sleeping</string>
<string name="medtronic_cmd_profile_not_set">Remote Basal profile setting is not supported. Please modify Basal profile on your pump manually.</string>
<string name="medtronic_cmd_cancel_bolus_not_supported">Remote cancel of Bolus is not supported. If you wish to cancel bolus, go to pump put it in suspend and then resume. This will cancel the bolus.</string>
<string name="medtronic_cmd_cant_read_tbr">Could not read current TBR.</string>
<string name="medtronic_cmd_cant_cancel_tbr">Could not cancel current TBR. Stopping operation.</string>
<string name="pump_no_connection_h">No connection for %1$d hour(s) %2$d min</string>
<string name="pump_no_connection_d">No connection for %1$d day(s) %2$d hours</string>
<plurals name="objective_days">

View file

@ -44,23 +44,29 @@
android:digits="0123456789."
android:title="@string/medtronic_pump_max_bolus" />
<Preference
android:enabled="true"
android:key="rileylink_scanner"
android:title="RileyLink Configuration">
<intent android:action="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
</Preference>
<EditTextPreference
<info.nightscout.androidaps.plugins.PumpCommon.ui.RileyLinkSelectPreference
android:id="@+id/rileylink_mac_address_mdt"
android:defaultValue="xx:xx:xx:xx:xx:xx"
android:editable="false"
android:inputType="textFilter"
android:key="pref_rileylink_mac_address"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/rileylink_mac_address" />
android:enabled="true"
android:summary=""
android:title="RileyLink Configuration"
android:key="pref_rileylink_mac_address">
<intent android:action="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
</info.nightscout.androidaps.plugins.PumpCommon.ui.RileyLinkSelectPreference>
<!-- android:key="rileylink_scanner" -->
<!--
<EditTextPreference
android:id="@+id/rileylink_mac_address_mdt"
android:defaultValue="xx:xx:xx:xx:xx:xx"
android:editable="false"
android:inputType="textFilter"
android:key="pref_rileylink_mac_address"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="@string/rileylink_mac_address" />
-->
</PreferenceCategory>
</PreferenceScreen>